diff --git a/include/core/Admin.h b/include/core/Admin.h new file mode 100644 index 0000000..a44f871 --- /dev/null +++ b/include/core/Admin.h @@ -0,0 +1,55 @@ +#pragma once + +#include "Network.h" + +/** + * @class Admin + * @brief Provides administrative functions for monitoring and controlling the network simulation. + * + * The Admin class serves as an interface for generating reports on the network's performance and + * running the simulation for a specified number of ticks with periodic reporting. It holds a + * reference to the Network object and uses its methods to retrieve statistics and advance the + * simulation. + */ +class Admin { + /** Pointer to the Network object that this Admin instance will manage and report on. */ + Network* network; + +public: + /** + * @brief Constructor that initializes the Admin with a reference to the Network object. + * + * @param net Reference to the Network object that this Admin will manage. + */ + explicit Admin(Network& net) : network(&net) {} + + /** + * @brief Destructor for Admin. Defaulted to allow automatic cleanup of resources. + */ + ~Admin() = default; + + /** + * @brief Deleted copy constructor to prevent copying of the Admin object. + */ + Admin(const Admin&) = delete; + + /** + * @brief Deleted copy assignment operator to prevent copying of the Admin object. + * + * @return Reference to this Admin object. + */ + Admin& operator=(const Admin&) = delete; + + /** + * @brief Deleted move constructor to prevent moving of the Admin object. + */ + void printReport() const; + + /** + * @brief Deleted move assignment operator to prevent moving of the Admin object. + * + * @param ticks The number of ticks to run the simulation for. + * @param reportInterval The interval (in ticks) at which to print the network report. + */ + void runFor(size_t ticks, size_t reportInterval = 10) const; +}; diff --git a/include/core/Network.h b/include/core/Network.h index 154cae0..bb148b5 100755 --- a/include/core/Network.h +++ b/include/core/Network.h @@ -5,6 +5,64 @@ #include "Router.h" #include "algorithms/Dijkstra.h" +/** + * @struct NetworkStats + * @brief A structure to hold various statistics about the network's performance and state. + * + * This structure is designed to collect and store key metrics related to the network's operation, + * including counts of routers, terminals, packets, and pages, as well as derived ratios such as + * delivery and drop rates. It provides a convenient way to encapsulate all relevant statistics for + * reporting and analysis purposes. + */ +struct NetworkStats { + size_t totalRouters = 0; /**< Number of routers in the network */ + size_t totalTerminals = 0; /**< Number of terminals in the network */ + size_t currentTick = 0; /**< Current simulation tick */ + + size_t packetsGenerated = 0; /**< Total of packets generated by all the terminals */ + size_t packetsSent = 0; /**< Total of packets sent by all the terminals */ + size_t packetsDelivered = 0; /**< Total of packets that successfully completed a page */ + size_t packetsDropped = 0; /**< Total of packets dropped due to buffer overflows */ + size_t packetsTimedOut = 0; /**< Total of packets that timed out while in transit */ + size_t packetsInFlight = 0; /**< Total of packets currently in transit within the network */ + + size_t pagesCreated = 0; /**< Total of pages created by all the terminals */ + size_t pagesCompleted = 0; /**< Total of pages successfully reassembled */ + size_t pagesDropped = 0; /**< Total of pages dropped due to buffer overflows */ + size_t pagesTimedOut = 0; /**< Total of pages that timed out while in transit */ + + /** + * @brief Calculates the delivery rate as the ratio of packets delivered to packets sent. + * + * @return The delivery rate as a float between 0.0 and 1.0. + */ + [[nodiscard]] float deliveryRate() const { + return packetsSent > 0 ? static_cast(packetsDelivered) / packetsSent : 0.0f; + } + + /** + * @brief Calculates the drop rate as the ratio of packets dropped to packets sent. + * + * @return The drop rate as a float between 0.0 and 1.0. + */ + [[nodiscard]] float dropRate() const { + return packetsSent > 0 ? static_cast(packetsDropped) / packetsSent : 0.0f; + } + + /** + * @brief Calculates the success rate for pages as the ratio of pages completed to total + * finished pages (completed + dropped + timed out). + * + * @return The success rate for pages as a float between 0.0 and 1.0. + */ + [[nodiscard]] float successRate() const { + size_t totalFinishedPages = pagesCompleted + pagesDropped + pagesTimedOut; + + return totalFinishedPages > 0 ? static_cast(pagesCompleted) / totalFinishedPages + : 0.0f; + } +}; + /** * @class Network * @brief Represents a network of routers and terminals, managing the overall topology, traffic @@ -18,15 +76,15 @@ class Network { public: /** Default number of routers in the network */ - static constexpr size_t DEF_ROUTERS_COUNT = 20; + static constexpr uint8_t DEF_ROUTERS_COUNT = 20; /** Default maximum number of terminals connected to each router */ - static constexpr size_t DEF_MAX_TERMINALS = 10; + static constexpr uint8_t DEF_MAX_TERMINALS = 10; /** Default complexity level for additional connections between routers */ - static constexpr size_t DEF_COMPLEXITY = 5; + static constexpr size_t DEF_COMPLEXITY = 5; /** Default probability of generating traffic for terminals in each tick (0.0 to 1.0) */ - static constexpr float DEF_PROBABILITY = 0.5; + static constexpr float DEF_PROBABILITY = 0.5; /** Default maximum page length for traffic generation for terminals */ - static constexpr size_t DEF_MAX_PAGE_LEN = 10; + static constexpr size_t DEF_MAX_PAGE_LEN = 10; /** Type alias for a unique pointer to a Router object. */ using RouterPtr = std::unique_ptr; @@ -96,7 +154,7 @@ class Network { explicit Network(const Config& config = Config{}); /** - * @brief Destructor for Network, defaulted to allow automatic cleanup of resources. + * @brief Destructor for Network. Defaulted to allow automatic cleanup of resources. */ ~Network() = default; @@ -185,6 +243,14 @@ class Network { */ const List& getRouters() const; + /** + * @brief Retrieves the current statistics of the network, including counts of routers, + * terminals, packets, and pages, as well as delivery and drop rates. + * + * @return A NetworkStats structure containing the current statistics of the network. + */ + NetworkStats getStats() const; + private: /** * @brief Connects routers in a minimal spanning tree configuration to ensure basic diff --git a/main.cpp b/main.cpp index 2ce3d43..3ccfc53 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,13 @@ -#include "structures/list.h" +#include "core/Admin.h" int main() { + Network network{}; + const Admin admin{network}; + + admin.runFor(100, 10); + + std::cout << "\n=== FINAL REPORT ===\n"; + admin.printReport(); + return 0; } diff --git a/src/core/Admin.cpp b/src/core/Admin.cpp new file mode 100644 index 0000000..8cc29f0 --- /dev/null +++ b/src/core/Admin.cpp @@ -0,0 +1,47 @@ +#include "core/Admin.h" + +void Admin::printReport() const { + const NetworkStats s = network->getStats(); + + std::cout << "\n╔══════════════════════════════════════╗\n"; + std::cout << "║ NETWORK REPORT ║\n"; + std::cout << "╠══════════════════════════════════════╣\n"; + std::cout << std::fixed << std::setprecision(1); + std::cout << "║ Tick: " << std::setw(6) << s.currentTick << " ║\n"; + std::cout << "║ Routers: " << std::setw(6) << s.totalRouters << " ║\n"; + std::cout << "║ Terminals: " << std::setw(6) << s.totalTerminals << " ║\n"; + std::cout << "╠══════════════════════════════════════╣\n"; + std::cout << "║ PACKETS ║\n"; + std::cout << "║ Generated: " << std::setw(6) << s.packetsGenerated << " ║\n"; + std::cout << "║ Sent: " << std::setw(6) << s.packetsSent << " ║\n"; + std::cout << "║ Delivered: " << std::setw(6) << s.packetsDelivered << " ║\n"; + std::cout << "║ Dropped: " << std::setw(6) << s.packetsDropped << " ║\n"; + std::cout << "║ Timed out: " << std::setw(6) << s.packetsTimedOut << " ║\n"; + std::cout << "║ In flight: " << std::setw(6) << s.packetsInFlight << " ║\n"; + std::cout << "╠══════════════════════════════════════╣\n"; + std::cout << "║ PAGES ║\n"; + std::cout << "║ Created: " << std::setw(6) << s.pagesCreated << " ║\n"; + std::cout << "║ Completed: " << std::setw(6) << s.pagesCompleted << " ║\n"; + std::cout << "║ Dropped: " << std::setw(6) << s.pagesDropped << " ║\n"; + std::cout << "║ Timed out: " << std::setw(6) << s.pagesTimedOut << " ║\n"; + std::cout << "╠══════════════════════════════════════╣\n"; + std::cout << "║ RATES ║\n"; + std::cout << "║ Delivery rate: " << std::setw(5) << s.deliveryRate() * 100 + << "% ║\n"; + std::cout << "║ Success rate: " << std::setw(5) << s.successRate() * 100 + << "% ║\n"; + std::cout << "║ Drop rate: " << std::setw(5) << s.dropRate() * 100 + << "% ║\n"; + std::cout << "╚══════════════════════════════════════╝\n"; +} + +void Admin::runFor(size_t ticks, size_t reportInterval) const { + for (size_t i = 1; i <= ticks; ++i) { + network->simulate(1); + + if (reportInterval > 0 && i % reportInterval == 0) { + std::cout << "── Tick " << std::setw(4) << i << " ──────────────────────────\n"; + printReport(); + } + } +} diff --git a/src/core/Network.cpp b/src/core/Network.cpp index b046039..6ecc5c7 100755 --- a/src/core/Network.cpp +++ b/src/core/Network.cpp @@ -1,5 +1,7 @@ #include "core/Network.h" +#include "core/Terminal.h" + Network::Network(const Config& config) : currentTick(1) { generateRandomNetwork(config.routerCount, config.maxTerminalCount, config.complexity, config.trafficProbability, config.maxPageLen); @@ -62,6 +64,36 @@ void Network::simulate(size_t ticks) { recalculateAllRoutes(); } +NetworkStats Network::getStats() const { + NetworkStats stats; + stats.currentTick = currentTick - 1; + for (auto& rtr : routers) { + stats.totalRouters++; + stats.totalTerminals += rtr->getTerminalCount(); + stats.packetsDropped += rtr->getPacketsDropped(); + stats.packetsTimedOut += rtr->getPacketsTimedOut(); + stats.packetsInFlight += rtr->getPacketsInPending(); + stats.packetsInFlight += rtr->getPacketsOutPending(); + stats.packetsInFlight += rtr->getPacketsLocPending(); + for (auto& terminal : rtr->getTerminals()) { + stats.pagesCreated += terminal->getPagesCreated(); + stats.pagesDropped += terminal->getPagesDropped(); + stats.pagesCompleted += terminal->getPagesCompleted(); + stats.pagesTimedOut += terminal->getPagesTimedOut(); + stats.packetsGenerated += terminal->getPacketsGenerated(); + stats.packetsSent += terminal->getPacketsSent(); + stats.packetsDropped += terminal->getPacketsInDropped(); + stats.packetsDropped += terminal->getPacketsOutDropped(); + stats.packetsTimedOut += terminal->getPacketsOutTimedOut(); + stats.packetsTimedOut += terminal->getPacketsInTimedOut(); + stats.packetsInFlight += terminal->getPacketsInPending(); + stats.packetsInFlight += terminal->getPacketsOutPending(); + stats.packetsDelivered += terminal->getPacketsSuccProcessed(); + } + } + return stats; +} + void Network::addRouter(uint8_t rtrID, uint8_t TerminalCount, float probability, size_t PageLen) { auto rtr = std::make_unique(IPAddress{rtrID}, TerminalCount); rtr->shareAddressBook(&addressBook); diff --git a/src/core/dummy.cpp b/src/core/dummy.cpp deleted file mode 100644 index b381604..0000000 --- a/src/core/dummy.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// -// Created by David on 22/01/2026. -//