From 4710c96450d4f2a75defc69880769b379c48403b Mon Sep 17 00:00:00 2001 From: Gaa56 Date: Thu, 30 Oct 2025 18:06:02 +0000 Subject: [PATCH 1/2] Create TrafficLightThread Class --- .../src/main/java/sd/IntersectionProcess.java | 10 +- .../java/sd/engine/TrafficLightThread.java | 165 ++++++++++++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 main/src/main/java/sd/engine/TrafficLightThread.java diff --git a/main/src/main/java/sd/IntersectionProcess.java b/main/src/main/java/sd/IntersectionProcess.java index 11db78d..b2ed78f 100644 --- a/main/src/main/java/sd/IntersectionProcess.java +++ b/main/src/main/java/sd/IntersectionProcess.java @@ -261,7 +261,7 @@ public class IntersectionProcess { * * @param vehicle The vehicle that has crossed this intersection. */ - private void sendVehicleToNextDestination(Vehicle vehicle) { + public void sendVehicleToNextDestination(Vehicle vehicle) { String nextDestination = vehicle.getCurrentDestination(); try { @@ -460,6 +460,14 @@ public class IntersectionProcess { System.out.println("=".repeat(60)); } + /** + * Returns the Intersection (model) object managed by this process. + * @return The Intersection object. + */ + public Intersection getIntersection() { + return this.intersection; + } + // --- Inner class for Vehicle Transfer Messages --- /** diff --git a/main/src/main/java/sd/engine/TrafficLightThread.java b/main/src/main/java/sd/engine/TrafficLightThread.java new file mode 100644 index 0000000..4b9c988 --- /dev/null +++ b/main/src/main/java/sd/engine/TrafficLightThread.java @@ -0,0 +1,165 @@ +package sd.engine; + +import sd.IntersectionProcess; +import sd.config.SimulationConfig; +import sd.model.TrafficLight; +import sd.model.TrafficLightState; +import sd.model.Vehicle; + +/** + * Implements the control logic for a single TrafficLight + * as a Runnable task that runs in its own Thread. + * + * This class fulfills the assignment requirements: + * 1. Implements Runnable (to be executed by a Thread/ExecutorService). + * 2. Implements the GREEN/RED cycle logic. + * 3. Includes a graceful shutdown mechanism (via the 'running' flag). + */ +public class TrafficLightThread implements Runnable { + + /** + * The TrafficLight object (the *model*) that this thread controls. + * Contains the queue and the state. + */ + private final TrafficLight light; + + /** + * The IntersectionProcess (the Process) that "owns" this thread. + * Used to call methods on the process, such as sendVehicleToNextDestination(). + */ + private final IntersectionProcess process; + + /** + * The simulation configuration, used to get timings (e.g., crossing time). + */ + private final SimulationConfig config; + + /** + * Volatile flag to control the graceful shutdown mechanism. + * When set to 'false', the 'run()' loop terminates. + */ + private volatile boolean running; + + /** + * Constructor for the Traffic Light Thread. + * + * @param light The TrafficLight object (model) to be controlled. + * @param process The parent IntersectionProcess (for callbacks). + * @param config The simulation configuration (to get timings). + */ + public TrafficLightThread(TrafficLight light, IntersectionProcess process, SimulationConfig config) { + this.light = light; + this.process = process; + this.config = config; + this.running = false; // Starts as 'stopped' + } + + /** + * The main entry point for the thread. + * Implements the GREEN/RED cycle logic extracted from IntersectionProcess. + * + */ + @Override + public void run() { + this.running = true; + System.out.println("[" + light.getId() + "] Traffic light thread started."); + + try { + // Main thread loop, continues while 'running' is true + // This 'running' flag is controlled by the parent IntersectionProcess + while (running) { + + // --- GREEN Phase --- + light.changeState(TrafficLightState.GREEN); // + System.out.println("[" + light.getId() + "] State: GREEN"); + + // Process vehicles in the queue + processGreenLightQueue(); + + // Wait for green duration + Thread.sleep((long) (light.getGreenTime() * 1000)); // + + if (!running) break; // Check flag after sleep + + // --- RED Phase --- + light.changeState(TrafficLightState.RED); // + System.out.println("[" + light.getId() + "] State: RED"); + + // Wait for red duration + Thread.sleep((long) (light.getRedTime() * 1000)); // + + } + } catch (InterruptedException e) { + // Apanha a InterruptedException (outra forma de parar a thread) + System.out.println("[" + light.getId() + "] Traffic light thread interrupted."); + this.running = false; // Garante que o loop termina + } + + System.out.println("[" + light.getId() + "] Traffic light thread stopped."); + } + + /** + * Processes vehicles in the queue while the traffic light is GREEN. + * Logic extracted from IntersectionProcess.processGreenLight() + * + */ + private void processGreenLightQueue() throws InterruptedException { + // + while (running && light.getState() == TrafficLightState.GREEN && light.getQueueSize() > 0) { + + Vehicle vehicle = light.removeVehicle(); // + + if (vehicle != null) { + // 1. Get the crossing time (t_sem) + double crossingTime = getCrossingTimeForVehicle(vehicle); // + + // 2. Simulate the time the vehicle takes to cross + Thread.sleep((long) (crossingTime * 1000)); // + + // 3. Update vehicle statistics + vehicle.addCrossingTime(crossingTime); // + + // 4. Update intersection statistics + // (This requires getIntersection() to be public in IntersectionProcess) + process.getIntersection().incrementVehiclesSent(); // + + // 5. Call the parent Process to send the vehicle + // (This requires sendVehicleToNextDestination() to be public in IntersectionProcess) + process.sendVehicleToNextDestination(vehicle); // + } + } + } + + /** + * Gets the crossing time for a vehicle based on its type. + * Logic extracted from IntersectionProcess.getCrossingTimeForVehicle() + * + * + * @param vehicle The vehicle. + * @return The crossing time in seconds. + */ + private double getCrossingTimeForVehicle(Vehicle vehicle) { + switch (vehicle.getType()) { // + case BIKE: + return config.getBikeVehicleCrossingTime(); // + case LIGHT: + return config.getLightVehicleCrossingTime(); // + case HEAVY: + return config.getHeavyVehicleCrossingTime(); // + default: + return config.getLightVehicleCrossingTime(); // + } + } + + /** + * Requests the thread to stop gracefully (graceful shutdown). + * Sets the 'running' flag to false. The thread will finish + * its current sleep cycle and exit the 'run()' loop. + */ + public void shutdown() { + this.running = false; + // (Note: If the thread is sleeping, it will only stop + // *after* waking up. A more immediate shutdown would require + // calling .interrupt() on the thread running this Runnable) + } +} \ No newline at end of file From 484cba1eee4ac0587c98cec20afe9b33883ad931 Mon Sep 17 00:00:00 2001 From: Gaa56 Date: Wed, 5 Nov 2025 13:21:10 +0000 Subject: [PATCH 2/2] Update TrafficLightThread --- main/src/main/java/sd/engine/TrafficLightThread.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/main/src/main/java/sd/engine/TrafficLightThread.java b/main/src/main/java/sd/engine/TrafficLightThread.java index 4b9c988..6d40fdf 100644 --- a/main/src/main/java/sd/engine/TrafficLightThread.java +++ b/main/src/main/java/sd/engine/TrafficLightThread.java @@ -10,10 +10,6 @@ import sd.model.Vehicle; * Implements the control logic for a single TrafficLight * as a Runnable task that runs in its own Thread. * - * This class fulfills the assignment requirements: - * 1. Implements Runnable (to be executed by a Thread/ExecutorService). - * 2. Implements the GREEN/RED cycle logic. - * 3. Includes a graceful shutdown mechanism (via the 'running' flag). */ public class TrafficLightThread implements Runnable { @@ -120,11 +116,11 @@ public class TrafficLightThread implements Runnable { vehicle.addCrossingTime(crossingTime); // // 4. Update intersection statistics - // (This requires getIntersection() to be public in IntersectionProcess) + process.getIntersection().incrementVehiclesSent(); // // 5. Call the parent Process to send the vehicle - // (This requires sendVehicleToNextDestination() to be public in IntersectionProcess) + process.sendVehicleToNextDestination(vehicle); // } } @@ -158,8 +154,5 @@ public class TrafficLightThread implements Runnable { */ public void shutdown() { this.running = false; - // (Note: If the thread is sleeping, it will only stop - // *after* waking up. A more immediate shutdown would require - // calling .interrupt() on the thread running this Runnable) } } \ No newline at end of file