commit f59aeac67b6c5dcacebd47db0398fb620738fd48 Author: violette Date: Thu Mar 14 16:11:56 2024 -0400 Baseline. Q1 is about to be done. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed5eff7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target/ +.vim/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0a68b42 --- /dev/null +++ b/pom.xml @@ -0,0 +1,30 @@ + + 4.0.0 + usherbrooke.ift630 + proj2 + jar + 1.0-SNAPSHOT + proj2 + http://maven.apache.org + + + junit + junit + 3.8.1 + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + diff --git a/src/main/java/usherbrooke/ift630/App.java b/src/main/java/usherbrooke/ift630/App.java new file mode 100644 index 0000000..e532f49 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/App.java @@ -0,0 +1,81 @@ +package usherbrooke.ift630; + +import java.lang.Long; +import java.util.ArrayList; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +/** + * Hello world! + * + */ +public class App +{ + static private int numStops = 10; + static private int numBusses = 10; + static private int numStopPerBus = 2; + static private int numPassengersPerBus = 2; + static private int numPassengers = 20; + static private int numPassengersPerStop = 2; + static private int numThreads = 5; + static private int timeBetweenStops = 5; + + public static void main(String[] args) { + ExecutorService threads = Executors.newFixedThreadPool(numThreads); + ArrayList stops = new ArrayList(); + ArrayList busses = new ArrayList(); + ArrayList passengers = new ArrayList(); + + for (int k = 0; k < numStops; k++) { + Stop s = new Stop(k, numPassengersPerStop); + stops.add(s); + + threads.submit(s); + } + + for (int k = 0; k < numPassengers; k++) { + Stop start, dest; + + // select start where there is some room left + do { + start = stops.get(((int) (Math.random() * numStops))); + } while (start.getCurrentCapacity() >= start.getMaxCapacity()); + + dest = stops.get((int) (Math.random() * numStops)); + + Passenger p = new Passenger(k, dest, start); + passengers.add(p); + start.addPassenger(p); + } + + for (int k = 0; k < numBusses; k++) { + ArrayList s_list = new ArrayList(); + Stop s; + while (s_list.size() < numStopPerBus) { + do { + s = stops.get((int) (Math.random() * numStops)); + } while (s_list.contains(s)); + s_list.add(s); + } + Bus b = new Bus(s_list, k, timeBetweenStops, numPassengersPerBus); + + b.printDetails(); + + busses.add(b); + + synchronized (b) { + b.notify(); + } + } + + // start bus thread + // (here so init logs are clean) + for (Bus b : busses) { + threads.submit(b); + } + try { + threads.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); + } catch (InterruptedException e) { + } + } +} diff --git a/src/main/java/usherbrooke/ift630/Bus.java b/src/main/java/usherbrooke/ift630/Bus.java new file mode 100644 index 0000000..80a32fe --- /dev/null +++ b/src/main/java/usherbrooke/ift630/Bus.java @@ -0,0 +1,110 @@ +package usherbrooke.ift630; + +import java.util.ArrayList; + +public class Bus extends Thread { + private ArrayList passengers; + private ArrayList stops; + private String name; + private int id; + private int maxCapacity; + private int currentCapacity; + private int timeBetweenStops; + private Stop currentStop; + + private int timeBetweenStops() { + return (int) (Math.random() * timeBetweenStops * timeBetweenStops); + } + + private Stop goToNextStop() { + currentStop = stops.remove(0); + try { + Thread.sleep(timeBetweenStops() * 1000); + } catch (InterruptedException e) { + System.out.println(e.getMessage()); + } + return currentStop; + } + + // TODO ?? + private ArrayList getNextStopPassengers() { + ArrayList res = new ArrayList(); + + for (Passenger p : passengers) { + Stop next = stops.get(1); + next.getPassengerByDest(stops); + } + + return res; + } + + @Override + public void run() { + while (currentStop != null) { + embarkPassengers(); + disembarkPassengers(); + + currentStop = goToNextStop(); + } + } + + Bus(ArrayList s, int id, int time, int maxCapacity) { + this.timeBetweenStops = time; + this.name = "Bus n°" + id; + this.id = id; + this.passengers = new ArrayList(); + this.stops = s; + this.currentStop = stops.get(0); + this.currentCapacity = 0; + this.maxCapacity = maxCapacity; + } + + public synchronized void disembarkPassengers() { + for (Passenger p : passengers) { + Logger.getInstance().print(id, "[BUS] " + p.getName() + " got out of " + name); + + if (p.getDest() == currentStop) { + p.disembark(); + currentCapacity--; + } + } + } + + public synchronized void embarkPassengers() { + try { + ArrayList list = currentStop.getPassengerByDest(stops); + Logger.getInstance().print(id, "[BUS] hop into " + name + "!"); + if (currentCapacity >= maxCapacity) + throw new OverCapacityException("Over bus capacity."); + for (Passenger p : list) { + passengers.add(p); + currentStop.removePassenger(p); + currentCapacity++; + + Logger.getInstance().print(id, + "[BUS] " + p.getName() + " embarked in " + name + " at " + currentStop.getName()); + } + } catch (IndexOutOfBoundsException | OverCapacityException e) { + Logger.getInstance().print(id, "ERROR " + e.getMessage()); + } + } + + public void printDetails(int indent) { + Logger.getInstance().print(id, "\t".repeat(indent) + "---".repeat(3) + " Bus details " + "---".repeat(3)); + Logger.getInstance().print(id, "\t".repeat(indent) + name); + Logger.getInstance().print(id, "\t".repeat(indent) + "time between stops: " + timeBetweenStops); + Logger.getInstance().print(id, "\t".repeat(indent) + "max capacity: " + maxCapacity); + Logger.getInstance().print(id, "\t".repeat(indent) + "current stop: " + currentStop.getName()); + Logger.getInstance().print(id, "\t".repeat(indent) + "stops: " ); + + + for (Stop s : stops) { + s.printDetails(indent + 1); + } + } + + public void printDetails() { + printDetails(0); + } + +} diff --git a/src/main/java/usherbrooke/ift630/Logger.java b/src/main/java/usherbrooke/ift630/Logger.java new file mode 100644 index 0000000..f4812e8 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/Logger.java @@ -0,0 +1,51 @@ +package usherbrooke.ift630; + +public class Logger { + private static Logger logger; + + private static final String RED = "\u001B[31m"; + private static final String GREEN = "\u001B[32m"; + private static final String YELLOW = "\u001B[33m"; + private static final String BLUE = "\u001B[34m"; + private static final String PURPLE = "\u001B[35m"; + private static final String CYAN = "\u001B[36m"; + private static final String RESET = "\u001B[0m" ; + private static final String WHITE = "\u001B[0m"; + + private String[] cols = { + WHITE, + RED, + GREEN, + YELLOW, + BLUE, + PURPLE, + CYAN, + }; + + private Logger() {} + + public void printTime() { + System.out.println(System.currentTimeMillis()); + } + + public void printTime(String s) { + System.out.println(System.currentTimeMillis() + s); + } + + public void printTime(int c, String s) { + System.out.println(cols[c % cols.length] +System.currentTimeMillis() + s + RESET); + } + + + public void print(int c, String s) { + System.out.println(cols[c % cols.length] + s + RESET); + } + + public static Logger getInstance() { + if(logger == null) { + logger = new Logger(); + } + + return logger; + } +} diff --git a/src/main/java/usherbrooke/ift630/NotFoundException.java b/src/main/java/usherbrooke/ift630/NotFoundException.java new file mode 100644 index 0000000..5e53278 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/NotFoundException.java @@ -0,0 +1,10 @@ +package usherbrooke.ift630; + +public class NotFoundException extends Exception { + NotFoundException() {} + + public NotFoundException(String message) + { + super(message); + } +} diff --git a/src/main/java/usherbrooke/ift630/OverCapacityException.java b/src/main/java/usherbrooke/ift630/OverCapacityException.java new file mode 100644 index 0000000..5388909 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/OverCapacityException.java @@ -0,0 +1,10 @@ +package usherbrooke.ift630; + +public class OverCapacityException extends Exception { + OverCapacityException() {} + + public OverCapacityException(String message) + { + super(message); + } +} diff --git a/src/main/java/usherbrooke/ift630/Passenger.java b/src/main/java/usherbrooke/ift630/Passenger.java new file mode 100644 index 0000000..19d5e43 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/Passenger.java @@ -0,0 +1,41 @@ +package usherbrooke.ift630; + +public class Passenger { + + private String name; + private int id; + private Stop dest; + private Stop start; + + Passenger(int id, Stop dest, Stop start) { + this.id = id; + this.name = "Passenger " + id; + this.dest = dest; + this.start = start; + } + + public synchronized void embark() {} + + public synchronized void disembark() {} + + public Stop getStart() { + return start; + } + + public Stop getDest() { + return dest; + } + + public String getName() { + return name; + } + + public void printDetails(int indent) { + Logger.getInstance().print(id, "\t".repeat(indent) + "---".repeat(3) + " Passenger details " + "---".repeat(3)); + Logger.getInstance().print(id, "\t".repeat(indent) + name + " start: " + start.getName() + " dest: " + dest.getName()); + } + + public void printDetails() { + printDetails(0); + } +} diff --git a/src/main/java/usherbrooke/ift630/Stop.java b/src/main/java/usherbrooke/ift630/Stop.java new file mode 100644 index 0000000..6baf8b1 --- /dev/null +++ b/src/main/java/usherbrooke/ift630/Stop.java @@ -0,0 +1,84 @@ +package usherbrooke.ift630; + +import java.util.ArrayList; + +public class Stop implements Runnable { + private String name; + private int id; + private int maxCapacity; + private ArrayList passengers; + + @Override + public void run() { + // xd do nothing for now + //for (Passenger p : passengers) { + // // + //} + } + + // run once. Then, queue the same thread, and exit. + // Message a bus their current number of passenger ; and the + // number of passenger willing to take this bus. + Stop(int id, int maxCapacity) { + this.id = id; + this.name = "Stop " + id; + this.passengers = new ArrayList(); + this.maxCapacity = maxCapacity; + } + + public Passenger getPassenger() { + return passengers.get(0); + } + + public void addPassenger(Passenger p) { + passengers.add(p); + } + + // return all passenger that stops at a stop in the list + public ArrayList getPassengerByDest(ArrayList list) { + // res for a little cleaner code + ArrayList res = new ArrayList(); + for (Stop s : list) { + for (Passenger p : passengers) { + if (p.getDest() == s) { + // if we got one, return & abort loop + res.add(p); + break; + } + } + } + + return res; + } + + public String getName() { + return name; + } + + public int getCurrentCapacity() { + return passengers.size(); + } + + public int getMaxCapacity() { + return maxCapacity; + } + + + public void printDetails(int indent) { + Logger.getInstance().print(id, "\t".repeat(indent) + "---".repeat(3) + " Stop details " + "---".repeat(3)); + Logger.getInstance().print(id, "\t".repeat(indent) + name); + + for (Passenger p : passengers) { + p.printDetails(indent + 1); + } + } + + public void printDetails() { + printDetails(0); + } + + public void removePassenger(Passenger p) { + // Logger.getInstance().print(id, "Passenger " + p.getName() + " left " + name); + passengers.remove(p); + } +} diff --git a/src/test/java/usherbrooke/ift630/AppTest.java b/src/test/java/usherbrooke/ift630/AppTest.java new file mode 100644 index 0000000..0ae2142 --- /dev/null +++ b/src/test/java/usherbrooke/ift630/AppTest.java @@ -0,0 +1,40 @@ +package usherbrooke.ift630; +import usherbrooke.ift630.App; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + String args[] = null; + App.main(args); + } +}