From b624cfe11e110359ebfea5f35cce7d6a6496db8e Mon Sep 17 00:00:00 2001 From: Gaa56 Date: Sun, 7 Dec 2025 15:51:50 +0000 Subject: [PATCH] Documentation --- main/src/main/java/sd/ExitNodeProcess.java | 169 ++++++++---------- .../java/sd/protocol/MessageProtocol.java | 3 +- .../java/sd/protocol/SocketConnection.java | 32 +++- 3 files changed, 108 insertions(+), 96 deletions(-) diff --git a/main/src/main/java/sd/ExitNodeProcess.java b/main/src/main/java/sd/ExitNodeProcess.java index 44b1b88..a7e771a 100644 --- a/main/src/main/java/sd/ExitNodeProcess.java +++ b/main/src/main/java/sd/ExitNodeProcess.java @@ -20,58 +20,65 @@ import sd.protocol.MessageProtocol; import sd.protocol.SocketConnection; /** - * Processo responsável pelo nó de saída do sistema de simulação de tráfego - * distribuído. - * - * Este processo representa o ponto final ("S") onde os veículos completam as - * suas rotas. - * As suas principais responsabilidades são: - * - Receber veículos que terminam a sua rota vindos das interseções - * - Calcular e agregar estatísticas finais dos veículos - * - Enviar estatísticas periódicas para o dashboard - * - Gerar relatórios finais ao terminar a simulação + * Represents the final Exit Node ("S") of the distributed traffic simulation. + * + * This process acts as a "sink" for all vehicles completing their routes. + * Unlike intersections, it does not route traffic but focuses on data collection. + * Its primary responsibilities are: + * - Accepting TCP connections from intersection processes. + * - Receiving {@link Vehicle} objects via the network. + * - Calculating final performance metrics (Total System Time, Waiting Time, Crossing Time). + * - Aggregating statistics by {@link VehicleType}. + * - Reporting real-time data to the Dashboard service via {@link SocketClient}. + * - Generating a final statistical report upon shutdown. */ public class ExitNodeProcess { + // --- Configuration and Networking --- private final SimulationConfig config; private ServerSocket serverSocket; + + /** + * Thread pool to handle concurrent incoming connections from multiple intersections. + */ private final ExecutorService connectionHandlerPool; /** - * Flag para controlar a execução do processo (volatile para visibilidade entre - * threads) + * Volatile flag to control the lifecycle of the process. */ private volatile boolean running; - /** Simulation start time (milliseconds) to calculate relative times */ + /** * Simulation start time (in milliseconds) used to calculate relative arrival times. + * This is synchronized with the Coordinator. + */ private long simulationStartMillis; - /** Counter de veículos que completaram a rota */ + // --- Statistics and Metrics --- + + /** Total count of vehicles that have successfully completed their route. */ private int totalVehiclesReceived; - /** Soma dos tempos no sistema de todos os veículos */ + /** Accumulated time (in seconds) that all vehicles spent in the system. */ private double totalSystemTime; - /** Soma dos tempos de espera de todos os veículos */ + /** Accumulated time (in seconds) that all vehicles spent waiting at red lights. */ private double totalWaitingTime; - /** Soma dos tempos de travessia de todos os veículos */ + /** Accumulated time (in seconds) that all vehicles spent crossing intersections. */ private double totalCrossingTime; - /** Contagem de veículos por tipo */ + /** Counter of vehicles separated by {@link VehicleType}. */ private final Map vehicleTypeCount; - /** Tempo total de espera acumulado por tipo de veículo */ + /** Accumulated wait time separated by {@link VehicleType}. */ private final Map vehicleTypeWaitTime; - /** Socket para comunicação com o dashboard */ + /** Client connection to send updates to the Dashboard. */ private SocketClient dashboardClient; - /** - * Método para iniciar o processo - * - * @param args Argumentos da linha de comandos. Se fornecido, args[0] deve ser - * o caminho para um ficheiro de configuração personalizado. + /** + * Main entry point for the Exit Node process. + * * @param args Command line arguments. Optional args[0] for config file path. */ public static void main(String[] args) { System.out.println("=".repeat(60)); @@ -101,14 +108,10 @@ public class ExitNodeProcess { } /** - * Constrói um novo processo de nó de saída. - * - * Inicializa todas as estruturas de dados necessárias para recolher - * estatísticas - * e configura o pool de threads para processar as ligações concorrentes. - * - * @param config Configuração da simulação contendo portas e endereços dos - * serviços + * Constructs a new ExitNodeProcess. + * * Initializes all data structures required for statistics collection + * and sets up the thread pool for handling concurrent network connections. + * * @param config The loaded {@link SimulationConfig} containing ports and addresses. */ public ExitNodeProcess(SimulationConfig config) { this.config = config; @@ -133,12 +136,11 @@ public class ExitNodeProcess { System.out.println(" - Dashboard: " + config.getDashboardHost() + ":" + config.getDashboardPort()); } - /** - * Inicializa o processo de ligação ao dashboard. - * - * Tenta conectar-se ao dashboard. Se a ligação falhar, o processo - * continua a funcionar normalmente, mas sem enviar estatísticas. - * + /** + * Initializes the connection to the external Dashboard service. + * * Attempts to establish a TCP connection to the dashboard. If successful, + * this connection will be used to stream live statistics. + * If the connection fails, the process logs a warning but continues operation. */ public void initialize() { System.out.println("Connecting to dashboard..."); @@ -158,15 +160,12 @@ public class ExitNodeProcess { } /** - * Inicia o socket e começa a aceitar ligações. - * - * Este é o loop principal do processo que: - * 1. Cria um socket na porta definida - * 2. Aguarda pelas ligações das interseções - * 3. Delega cada ligação a uma thread da pool para processamento assíncrono - * - * @throws IOException Se o socket não puder ser criado ou houver erro na - * aceitação + * Starts the server socket and begins the main event loop. + * * This method: + * 1. Binds a {@link ServerSocket} to the configured exit port. + * 2. Enters a loop accepting incoming connections from Intersections. + * 3. Submits each new connection to the {@code connectionHandlerPool} for asynchronous processing. + * * @throws IOException If the server socket cannot be bound. */ public void start() throws IOException { int port = config.getExitPort(); @@ -189,14 +188,12 @@ public class ExitNodeProcess { } } - /** - * Processa uma ligação recebida de uma interseção. - * - * Mantém a ligação aberta e processa continuamente mensagens do tipo - * VEHICLE_TRANSFER. Cada mensagem representa um veículo que chegou ao nó de - * saída. - * - * @param clientSocket Socket da ligação estabelecida com a interseção + /** + * Handles an active connection from an Intersection process. + * * Continuously reads {@link MessageProtocol} objects from the socket. + * Expects primarily {@link MessageType#VEHICLE_TRANSFER} messages containing + * {@link Vehicle} payloads. + * * @param clientSocket The accepted socket connection. */ private void handleIncomingConnection(Socket clientSocket) { String clientAddress = clientSocket.getInetAddress().getHostAddress(); @@ -252,15 +249,14 @@ public class ExitNodeProcess { } /** - * Processa um veículo que chegou ao nó de saída. - * - * Método sincronizado para garantir thread-safety ao atualizar as estatísticas. - * Calcula as métricas finais do veículo e atualiza: - * - Counters globais; - * - Estatísticas por tipo de veículo; - * - Faz update ao dashboard a cada 10 veículos. - * - * @param vehicle Veículo que completou a sua rota + * Processes a vehicle that has completed its route. + * * This method is {@code synchronized} to ensure thread safety when updating + * shared statistical counters. It calculates final metrics: + * - System Time: Total time since entry. + * - Wait Time: Total time spent at red lights. + * - Crossing Time: Total time spent crossing intersections. + * * It triggers an immediate update to the Dashboard. + * * @param vehicle The vehicle that has arrived at the Exit Node. */ private synchronized void processExitingVehicle(Vehicle vehicle) { totalVehiclesReceived++; @@ -289,13 +285,10 @@ public class ExitNodeProcess { } /** - * Envia as estatísticas para o dashboard. - * - * Prepara e envia uma mensagem STATS_UPDATE com: - * - O total de veículos processados; - * - A média dos tempos (sistema, espera, travessia); - * - As contagens e médias por cada tipo de veículo. - * + * Sends current aggregated statistics to the Dashboard. + * * Constructs a {@link StatsUpdatePayload} containing global counters and + * per-type metrics, converting seconds to milliseconds as expected by the frontend. + * Wraps the payload in a {@link Message} and sends it via the dashboard client. */ private void sendStatsToDashboard() { if (dashboardClient == null || !dashboardClient.isConnected()) { @@ -346,15 +339,14 @@ public class ExitNodeProcess { } } - /** - * Termina o processo - * - * Executa a seguinte sequência: - * Imprime as estatísticas finais no terminal; - * Envia a última atualização de estatísticas ao dashboard; - * Fecha o socket; - * Aguarda pela finalização das threads; - * Fecha a ligação com o dashboard; + /** + * Gracefully shuts down the exit node process. + * * Sequence of operations: + * 1. Prints final statistics to the console. + * 2. Sends one last update to the dashboard. + * 3. Closes the server socket to stop accepting connections. + * 4. Shuts down the thread pool. + * 5. Closes the dashboard connection. */ public void shutdown() { System.out.println("\n[Exit] Shutting down..."); @@ -390,15 +382,12 @@ public class ExitNodeProcess { } /** - * Imprime as estatísticas finais detalhadas no terminal - * - * Gera um relatório com: - * Total de veículos que completaram a rota; - * Médias de tempo no sistema, espera e travessia; - * Distribuição e médias pelo tipo de veículo (BIKE, LIGHT, HEAVY); - * - * Este método é chamado durante o shutdown para fornecer um resumo - * da simulação antes de terminar o processo. + * Prints a detailed statistical report to the console. + * * Included metrics: + * - Total vehicles processed. + * - Average System Time, Waiting Time, and Crossing Time. + * - Distribution count and percentage by Vehicle Type. + * - Average wait time by Vehicle Type. */ private void printFinalStatistics() { System.out.println("\n=== EXIT NODE STATISTICS ==="); diff --git a/main/src/main/java/sd/protocol/MessageProtocol.java b/main/src/main/java/sd/protocol/MessageProtocol.java index 47975be..2ec121f 100644 --- a/main/src/main/java/sd/protocol/MessageProtocol.java +++ b/main/src/main/java/sd/protocol/MessageProtocol.java @@ -1,7 +1,8 @@ package sd.protocol; import java.io.Serializable; -import sd.model.MessageType; // Assuming MessageType is in sd.model or sd.protocol + +import sd.model.MessageType; /** * Interface defining the contract for all messages exchanged in the simulator. diff --git a/main/src/main/java/sd/protocol/SocketConnection.java b/main/src/main/java/sd/protocol/SocketConnection.java index c65680b..65dd4e5 100644 --- a/main/src/main/java/sd/protocol/SocketConnection.java +++ b/main/src/main/java/sd/protocol/SocketConnection.java @@ -23,9 +23,30 @@ import sd.serialization.SerializerFactory; */ public class SocketConnection implements Closeable { + // --- Network Resources --- + + /** + * The underlying TCP socket used for network communication. + */ private final Socket socket; + + /** + * The raw output stream for writing bytes to the network. + * Wrapped by {@link DataOutputStream} during message sending. + */ private final OutputStream outputStream; + + /** + * The raw input stream for reading bytes from the network. + * Wrapped by {@link DataInputStream} during message reception. + */ private final InputStream inputStream; + + // --- Serialization --- + + /** + * The serializer strategy used to convert objects to/from byte arrays (e.g., JSON). + */ private final MessageSerializer serializer; // --- Configuration for Retry Logic --- @@ -159,7 +180,7 @@ public class SocketConnection implements Closeable { } try { - // Lê um prefixo de 4 bytes - indicador de tamanho + DataInputStream dataIn = new DataInputStream(inputStream); int length = dataIn.readInt(); @@ -167,11 +188,11 @@ public class SocketConnection implements Closeable { throw new IOException("Invalid message length: " + length); } - // Ler dados da mensagem + byte[] data = new byte[length]; dataIn.readFully(data); - // Deserialize do JSON - use concrete Message class, not interface + // JSON deserialization- use concrete Message class, not interface return serializer.deserialize(data, sd.model.Message.class); } catch (SerializationException e) { @@ -179,7 +200,7 @@ public class SocketConnection implements Closeable { } } - /** + /** * Closes the socket and all streams (Input and Output). */ @Override @@ -190,7 +211,8 @@ public class SocketConnection implements Closeable { } /** - * @return true if the socket is still connected and not closed. + * Checks the current state of the connection. + * @return {@code true} if the socket is connected and currently open, {@code false} otherwise. */ public boolean isConnected() { return socket != null && socket.isConnected() && !socket.isClosed();