diff --git a/.gitignore b/.gitignore index f68d109..5d5dd5a 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,8 @@ bin/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store + +*.class +*.iml +*.idea \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 1b2d693..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 1eb3ab5..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml deleted file mode 100644 index 2b63946..0000000 --- a/.idea/uiDesigner.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/BridgeSimulator.iml b/BridgeSimulator.iml deleted file mode 100644 index c90834f..0000000 --- a/BridgeSimulator.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/BridgeSimulator.java b/src/BridgeSimulator.java index 451855e..bbdf147 100644 --- a/src/BridgeSimulator.java +++ b/src/BridgeSimulator.java @@ -1,5 +1,3 @@ - -import java.util.concurrent.Semaphore; import java.util.*; public class BridgeSimulator { @@ -7,78 +5,60 @@ public class BridgeSimulator { int simulationTime = 30; // In simulated seconds int emergencies = 2; - - TrafficController trafficController = new TrafficController(simulationTime, emergencies); - - - } - - Vehicle generateVehicle() { - Random rand = new Random(); - - int r = rand.nextInt(2); - if (r == 0) { - return new Truck(); - } else if (emegencyCounter > emergencies) { - return new EmergencyVehicle(); - } else { - return new Car(); + if (args.length == 2) { + simulationTime = Integer.parseInt(args[0]); + emergencies = Integer.parseInt(args[1]); } - } + TrafficController trafficController = new TrafficController(); + + List emergencyTimes = new ArrayList<>(); + + Random rand = new Random(); + for (int i = 0; i < emergencies; i++) + emergencyTimes.add(rand.nextInt(simulationTime)); + + int currentSimTime = 0; + long lastTime = System.currentTimeMillis(); + long currentTime; + + System.out.println("Simulation starts for " + simulationTime + " seconds with " + emergencies + " emergency vehicles prioritized."); + while (currentSimTime <= simulationTime) { + currentTime = System.currentTimeMillis(); + +// if (currentTime - lastTime > 1) +// { +// trafficController.addVehicle(); +// lastTime = currentTime; +// } + + trafficController.addVehicle(); + + Integer timeToRemove = null; + for (Integer time : emergencyTimes) { + if (currentSimTime > time) { + trafficController.haveEmergency(); + timeToRemove = time; + break; + } + } + + if (timeToRemove != null) { + emergencyTimes.remove(timeToRemove); + } + + if (!trafficController.queue.isEmpty()) + currentSimTime += trafficController.allowVehicle(); + +// System.out.println(currentSimTime); + +// trafficController.printQueue(); + } + + int totalVehicles = trafficController.carCounter + trafficController.emergencyCounter + trafficController.truckCounter; + + System.out.println("Total Vehicles: " + totalVehicles + ", Cars: " + trafficController.carCounter + ", Trucks: " + trafficController.truckCounter + ", Emergency Vehicles: " + trafficController.emergencyCounter + ", Vehicles Crossed: " + trafficController.crossings); + + } } - -class TrafficController { - int simulationTime; - int emergencies; - int currentTime = 0; - int trafficCounter = 0; - int emegencyCounter = 0; - - Semaphore northQueue = new Semaphore(10); - Semaphore southQueue = new Semaphore(10); - Semaphore bridge = new Semaphore(1); - Semaphore emergencyQueue = new Semaphore(10); - - TrafficController(int simulationTime, int emergencies) { - this.simulationTime = simulationTime; - this.emergencies = emergencies; - } - - // Simulate Vehicles arriving - void addVehicle() { - Vehicle vehicle = generateVehicle(); - - if (vehicle instanceof EmergencyVehicle) { - emergencyQueue.add(vehicle); - return; - } - - Random rand = new Random(); - int r = rand.nextInt(2); - if (r == 0) { - northQueue.add(vehicle); - } else { - southQueue.add(vehicle); - } - } - - - - public Semaphore getNorthQueue() { - return northQueue; - } - - public Semaphore getSouthQueue() { - return southQueue; - } - - public Semaphore getBridge() { - return bridge; - } - - public Semaphore getEmergencyQueue() { - return emergencyQueue; - } -} \ No newline at end of file diff --git a/src/Car.java b/src/Car.java index 8f4322c..9070732 100644 --- a/src/Car.java +++ b/src/Car.java @@ -1,15 +1,14 @@ public class Car extends Vehicle { - public static int crossingTime = 2; + public int crossingTime = 2; public static int priority = 2; - public Car() {} - - public void run() { - try { - Thread.sleep(crossingTime); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("Car failed to cross."); - } + public Car(int id) { + super(id); } + + String getType() { + return "Car"; + } + + public int getCrossingTime() { return crossingTime; } } diff --git a/src/EmergencyVehicle.java b/src/EmergencyVehicle.java index bb445a7..becc9ce 100644 --- a/src/EmergencyVehicle.java +++ b/src/EmergencyVehicle.java @@ -1,15 +1,14 @@ public class EmergencyVehicle extends Vehicle { - public static int crossingTime = 1; + public int crossingTime = 1; public static int priority = 1; - public EmergencyVehicle() {} - - public void run() { - try { - Thread.sleep(crossingTime); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("Car failed to cross."); - } + public EmergencyVehicle(int id) { + super(id); } + + String getType() { + return "Emergency Vehicle"; + } + + public int getCrossingTime() { return crossingTime; } } diff --git a/src/TrafficController.java b/src/TrafficController.java new file mode 100644 index 0000000..24edcb8 --- /dev/null +++ b/src/TrafficController.java @@ -0,0 +1,131 @@ +import java.util.*; +import java.util.Random; +import java.util.concurrent.Semaphore; + +public class TrafficController { + + public int truckCounter = 0; + public int carCounter = 0; + public int emergencyCounter = 0; + public int crossings = 0; + + boolean northLast = true; + + LinkedList queue = new LinkedList<>(); + + Semaphore northSemaphore = new Semaphore(10); + Semaphore southSemaphore = new Semaphore(10); + + Semaphore bridge = new Semaphore(1); + + Semaphore emergencySemaphore = new Semaphore(10); + + Thread runningVehicle; + Vehicle currentVehicle = null; + + public TrafficController() {} + + public void haveEmergency() { + Vehicle v = new EmergencyVehicle(emergencyCounter++ + 1); + v.arrive(this); + } + + Vehicle generateVehicle() { + Random rand = new Random(); + int r = rand.nextInt(2); + + if (r == 0) { + return new Truck(truckCounter++ + 1); + } else { + return new Car(carCounter++ + 1); + } + } + + // Simulate Vehicles arriving + public void addVehicle() { + Vehicle vehicle = generateVehicle(); + + vehicle.arrive(this); + } + + public int allowVehicle() { + + if (currentVehicle != null) { + if (!currentVehicle.hasRun) { + return 0; + } else { + queue.remove(currentVehicle); + currentVehicle.leave(this); + currentVehicle = null; + bridge.release(); + crossings++; + } + } + + for (Vehicle vehicle : queue) { + if (vehicle instanceof EmergencyVehicle) { + currentVehicle = vehicle; + break; + // North is ZERO so look for South going car + } else if (vehicle.direction == 1 && (northLast || northSemaphore.availablePermits() == 10)) { + currentVehicle = vehicle; + northLast = false; + break; + } else if (vehicle.direction == 0 && (!northLast || southSemaphore.availablePermits() == 10)) { + currentVehicle = vehicle; + northLast = true; + break; + } + } + + if (currentVehicle == null) { + if (!queue.isEmpty()) { + System.out.println("Queue is NOT empty"); + printQueue(); + System.exit(0); + } + System.out.println("No vehicle to cross."); + return 0; + } + + try { + bridge.acquire(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println(currentVehicle.getType() + " " + currentVehicle.id + " could not cross."); + } + + System.out.println(currentVehicle.getType() + " " + currentVehicle.id + " starts crossing the bridge."); + runningVehicle = new Thread(currentVehicle); + runningVehicle.start(); + + return currentVehicle.getCrossingTime(); + } + + public Semaphore getNorthSemaphore() { + return northSemaphore; + } + + public Semaphore getSouthSemaphore() { + return southSemaphore; + } + + public Semaphore getBridge() { + return bridge; + } + + public Semaphore getEmergencySemaphore() { + return emergencySemaphore; + } + + public void queueVehicle(Vehicle vehicle) { + this.queue.add(vehicle); + } + + public void printQueue() { + System.out.println("Queue:"); + for (Vehicle vehicle : queue) { + System.out.println(vehicle.getType() + ' ' + vehicle.id + " " + vehicle.direction); + } + } +} diff --git a/src/Truck.java b/src/Truck.java index ee1935b..91256a7 100644 --- a/src/Truck.java +++ b/src/Truck.java @@ -1,15 +1,14 @@ public class Truck extends Vehicle { - public static int crossingTime = 3; + public int crossingTime = 3; public static int priority = 2; - public Truck() {} - - public void run() { - try { - Thread.sleep(crossingTime); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("Truck failed to cross."); - } + public Truck(int id) { + super(id); } + + String getType() { + return "Truck"; + } + + public int getCrossingTime() { return crossingTime; } } diff --git a/src/Vehicle.java b/src/Vehicle.java index c13308d..aa31a5d 100644 --- a/src/Vehicle.java +++ b/src/Vehicle.java @@ -1,4 +1,77 @@ +import java.util.Random; +import java.util.concurrent.Semaphore; + public abstract class Vehicle implements Runnable { - public static int crossingTime; + public int crossingTime; public static int priority; + int direction; + int id; + boolean hasRun = false; + + public Vehicle(int id) { + Random rand = new Random(); + + this.direction = rand.nextInt(2); + this.id = id; + } + + public void arrive(TrafficController trafficController) { + Semaphore queue; + + if (this instanceof EmergencyVehicle) { + queue = trafficController.getEmergencySemaphore(); + } else if (direction == 0) { + queue = trafficController.getNorthSemaphore(); + } else { + queue = trafficController.getSouthSemaphore(); + } + + if (this.direction == 0) + System.out.println(this.getType() + " " + id + " approaches the bridge. Waiting (North): " + (10 - queue.availablePermits())); + else + System.out.println(this.getType() + " " + id + " approaches the bridge. Waiting (South): " + (10 - queue.availablePermits())); + + if (queue.tryAcquire()) + trafficController.queueVehicle(this); + else + System.out.println(this.getType() + " " + id + " saw too many cars and left."); + +// +// try { +// +// +// } catch (InterruptedException e) { +// e.printStackTrace(); +// System.out.println(this.getType() + " " + id + " saw too many cars and left."); +// } + } + + public void leave(TrafficController trafficController) { + Semaphore queue; + + if (this instanceof EmergencyVehicle) { + queue = trafficController.getEmergencySemaphore(); + } else if (direction == 0) { + queue = trafficController.getNorthSemaphore(); + } else { + queue = trafficController.getSouthSemaphore(); + } + + queue.release(); + } + + @Override + public void run() { + try { + Thread.sleep(this.crossingTime); + System.out.println(this.getType() + " " + id + " crosses the bridge."); + hasRun = true; + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println(this.getType() + " " + id + " couldn't cross for some reason."); + } + } + + abstract String getType(); + abstract int getCrossingTime(); }