Compare commits
2 commits
16fe398f5f
...
14c72c3f7a
Author | SHA1 | Date | |
---|---|---|---|
|
14c72c3f7a | ||
|
dd474b686a |
7 changed files with 423 additions and 170 deletions
5
README.md
Normal file
5
README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# PROJET IFT630 STS 2
|
||||
Ce projet utilise maven.
|
||||
Un test est utilisé pour voir le projet fonctionner.
|
||||
Pour l'executer, vous pouvez faire `mvn test` dans la racine.
|
||||
Les questions sont répondues avec les commits correspondant.
|
|
@ -1,125 +1,46 @@
|
|||
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;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class App {
|
||||
static private int numBusses = 5;
|
||||
static private int numLines = 3;
|
||||
static private int numBusPerLine = 2;
|
||||
static private int numBusses = numLines * numBusPerLine;
|
||||
static private int numStopPerBus = 8;
|
||||
static private int numStops = numBusses * numStopPerBus;
|
||||
static private int numPassengersPerBus = 10;
|
||||
static private int numPassengersPerStop = 3;
|
||||
static private int numPassengers = numPassengersPerStop * numStops;
|
||||
static private int numPassengersPerBus = 5;
|
||||
static private int numPassengersPerStop = 5;
|
||||
//static private int numPassengers = numPassengersPerStop * numStops;
|
||||
static private int numThreadsBus = 5;
|
||||
static private int numThreadsStop = 2;
|
||||
static private int timeBetweenStops = 5;
|
||||
static private int timeEmbark = 2;
|
||||
static private int socketPort = 8181;
|
||||
|
||||
public static void main(String[] args) {
|
||||
ExecutorService threadsBus = Executors.newFixedThreadPool(numThreadsBus);
|
||||
ExecutorService threadsStop = Executors.newFixedThreadPool(numThreadsStop);
|
||||
ExecutorService threadsPassenger = Executors.newFixedThreadPool(1); // doesnt need more! future balance
|
||||
// themselfes out.
|
||||
ArrayList<Stop> stops = new ArrayList<Stop>();
|
||||
ArrayList<Bus> busses = new ArrayList<Bus>();
|
||||
ArrayList<Passenger> passengers = new ArrayList<Passenger>();
|
||||
BlockingQueue<BusInformationMessage> blockingQueue = new LinkedBlockingQueue<BusInformationMessage>();
|
||||
|
||||
// make stop" + name + " reached stop " + nextStop.getStopName() + "!"s
|
||||
for (int k = 0; k < numStops; k++) {
|
||||
Stop s = new Stop(k, numPassengersPerStop);
|
||||
s.setBlockingQueue(blockingQueue);
|
||||
|
||||
stops.add(s);
|
||||
s.setThreadPool(threadsStop);
|
||||
threadsStop.submit(s);
|
||||
}
|
||||
|
||||
// make busses
|
||||
for (int k = 0; k < numBusses; k++) {
|
||||
try {
|
||||
if (numStopPerBus > numStops) {
|
||||
System.out.println("More stops per bus than stops.");
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<Stop> s_list = new ArrayList<Stop>();
|
||||
Stop s;
|
||||
// add stop. Make a bus doesnt stop multiple time at the same stop
|
||||
while (s_list.size() < numStopPerBus) {
|
||||
do {
|
||||
s = stops.get((int) (Math.random() * numStops));
|
||||
} while (s_list.contains(s));
|
||||
s_list.add(s);
|
||||
}
|
||||
Central central = new Central(numThreadsBus, numThreadsStop, socketPort);
|
||||
// create everything
|
||||
central.createStops(numStops, numPassengersPerStop);
|
||||
central.createLines(numLines, numStopPerBus, numStops);
|
||||
central.createBusses(numBusses, timeBetweenStops, timeEmbark, numPassengersPerBus);
|
||||
central.createPassengers(numPassengersPerStop, numStopPerBus);
|
||||
|
||||
Bus b = new Bus(s_list, k, timeBetweenStops, timeEmbark, numPassengersPerBus);
|
||||
b.setBlockingQueue(blockingQueue);
|
||||
// print start details
|
||||
System.out.println("-----".repeat(5) + " START " + "-----".repeat(5));
|
||||
central.printDetails();
|
||||
System.out.println("-----".repeat(5) + " START " + "-----".repeat(5));
|
||||
|
||||
busses.add(b);
|
||||
// start bus thread
|
||||
central.startBusThreads();
|
||||
|
||||
// shutdown and wait!
|
||||
central.shutdown();
|
||||
} catch (Exception e) {
|
||||
System.out.println("[APP] " + e.toString());
|
||||
}
|
||||
|
||||
// make passenger
|
||||
int idPassenger = 0;
|
||||
for (Bus b : busses) {
|
||||
for (Stop start : b.getStops()) {
|
||||
|
||||
// make sure passenger can leave.
|
||||
if (start == b.getTerminus())
|
||||
continue;
|
||||
|
||||
int idx = b.getStops().indexOf(start);
|
||||
if (idx == -1 || start == b.getTerminus())
|
||||
continue;
|
||||
|
||||
for (int k = 0; k < (int) (Math.random() * numPassengersPerStop); k++) {
|
||||
Stop dest = null;
|
||||
|
||||
dest = b.getStops().get(idx + 1 + (int) Math.round(Math.random() * (numStopPerBus - 2 - idx)));
|
||||
|
||||
Passenger p = new Passenger(idPassenger, start, dest);
|
||||
p.setThreadPool(threadsPassenger);
|
||||
passengers.add(p);
|
||||
start.addPassenger(p);
|
||||
idPassenger++;
|
||||
|
||||
threadsPassenger.submit(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pretty print!
|
||||
for (Bus b : busses) {
|
||||
b.printDetails();
|
||||
}
|
||||
|
||||
System.out.println("-----".repeat(5) + " START " + "-----".repeat(5));
|
||||
|
||||
// start bus thread
|
||||
// (here so init logs are clean)
|
||||
for (Bus b : busses) {
|
||||
threadsBus.submit(b);
|
||||
}
|
||||
|
||||
// block bus pool
|
||||
threadsBus.shutdown();
|
||||
try {
|
||||
threadsBus.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
// block stop and passenger pool once bus have finished
|
||||
threadsStop.shutdown();
|
||||
threadsPassenger.shutdown();
|
||||
try {
|
||||
threadsStop.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
try {
|
||||
threadsPassenger.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package usherbrooke.ift630;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Bus extends Thread {
|
||||
private ArrayList<Passenger> passengers;
|
||||
private ArrayList<Stop> stops;
|
||||
private Line line;
|
||||
private String name;
|
||||
private int id;
|
||||
private int maxCapacity;
|
||||
|
@ -14,8 +18,12 @@ public class Bus extends Thread {
|
|||
private int timeBetweenStops;
|
||||
private int timeToNextStop;
|
||||
private int timeEmbark;
|
||||
private int nextStopIndex = 0;
|
||||
private int socketPort;
|
||||
private Stop nextStop;
|
||||
private BlockingQueue<BusInformationMessage> blockingQueue;
|
||||
private Socket socket;
|
||||
private PrintWriter socketTx;
|
||||
|
||||
// returns time for a single passenger to embark.
|
||||
private int timeEmbark() {
|
||||
|
@ -24,7 +32,7 @@ public class Bus extends Thread {
|
|||
|
||||
// set time between stop.
|
||||
private int calculateTimeBetweenStops() {
|
||||
timeToNextStop = (int) ((timeBetweenStops / 3) + (Math.random() * 2 * timeBetweenStops / 3));
|
||||
timeToNextStop = (int) ((timeBetweenStops / 3f) + (Math.random() * 2f * timeBetweenStops / 3f));
|
||||
return timeToNextStop;
|
||||
}
|
||||
|
||||
|
@ -34,7 +42,6 @@ public class Bus extends Thread {
|
|||
for (Passenger p : passengers) {
|
||||
if (p.getDest() == nextStop) {
|
||||
res = true;
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " stop asked!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -43,11 +50,12 @@ public class Bus extends Thread {
|
|||
}
|
||||
|
||||
// travel to next stop. Waits the travel time.
|
||||
private Stop goToNextStop() throws InterruptedException, IndexOutOfBoundsException {
|
||||
private Stop goToNextStop() throws InterruptedException, IndexOutOfBoundsException, IOException {
|
||||
// if no reason to stop, skip current stop
|
||||
boolean nextStopEmpty, overMaxCapacity;
|
||||
do {
|
||||
nextStop = stops.remove(0);
|
||||
nextStopIndex += 1;
|
||||
nextStop = line.get(nextStopIndex);
|
||||
|
||||
sendNextStopInfo();
|
||||
|
||||
|
@ -56,8 +64,12 @@ public class Bus extends Thread {
|
|||
overMaxCapacity = currentCapacity >= maxCapacity;
|
||||
nextStopEmpty = getNextStopPassengers().isEmpty();
|
||||
|
||||
if (overMaxCapacity)
|
||||
if (stopAsked())
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " stop asked!");
|
||||
if (overMaxCapacity) {
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " im full, sorry!");
|
||||
sendFulLMessage();
|
||||
}
|
||||
if (nextStopEmpty && !stopAsked())
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " next " + nextStop.getStopName() + " is empty!");
|
||||
} while (!stopAsked() && (nextStopEmpty || overMaxCapacity));
|
||||
|
@ -79,28 +91,29 @@ public class Bus extends Thread {
|
|||
ArrayList<Passenger> res = new ArrayList<Passenger>();
|
||||
|
||||
if (nextStop != null)
|
||||
for (Passenger p : passengers) {
|
||||
if (p.getDest() == nextStop) {
|
||||
res.add(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
res = nextStop.getPassengerByDest(line, nextStopIndex);
|
||||
return res;
|
||||
}
|
||||
|
||||
// lock until passenger got in
|
||||
private void waitEmbark() throws InterruptedException {
|
||||
synchronized (this) {
|
||||
sleep(timeEmbark());
|
||||
}
|
||||
sleep(timeEmbark());
|
||||
}
|
||||
|
||||
// lock until passenger got out
|
||||
private void waitStop() throws InterruptedException {
|
||||
synchronized (this) {
|
||||
sleep(timeToNextStop);
|
||||
}
|
||||
sleep(timeToNextStop);
|
||||
}
|
||||
|
||||
private void connectSocket() throws IOException {
|
||||
socket = new Socket("localhost", socketPort);
|
||||
socketTx = new PrintWriter(socket.getOutputStream(), true);
|
||||
}
|
||||
|
||||
private void sendFulLMessage() throws IOException {
|
||||
connectSocket();
|
||||
socketTx.println("FULL:" + id);
|
||||
socket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,8 +122,8 @@ public class Bus extends Thread {
|
|||
// run until terminus
|
||||
while (nextStop != null) {
|
||||
// new stop !
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " reached stop " + nextStop.getStopName() + "!");
|
||||
|
||||
Logger.getInstance().print(id, "[BUS] " + name + " reached stop " + nextStop.getStopName() + "!");
|
||||
disembarkPassengers();
|
||||
embarkPassengers();
|
||||
calculateTimeBetweenStops();
|
||||
|
@ -127,14 +140,14 @@ public class Bus extends Thread {
|
|||
Logger.getInstance().print(id, "[BUS] " + name + " exiting!");
|
||||
}
|
||||
|
||||
Bus(ArrayList<Stop> s, int id, int timeStop, int timeEmbark, int maxCapacity) {
|
||||
Bus(Line line, int id, int timeStop, int timeEmbark, int maxCapacity) {
|
||||
this.timeBetweenStops = timeStop * 1000 + 1;
|
||||
this.timeEmbark = timeEmbark * 1000 + 1;
|
||||
this.name = "Bus n°" + id;
|
||||
this.id = id;
|
||||
this.passengers = new ArrayList<Passenger>();
|
||||
this.stops = s;
|
||||
this.nextStop = stops.get(0);
|
||||
this.line = line;
|
||||
this.nextStop = line.get(0);
|
||||
this.currentCapacity = 0;
|
||||
this.maxCapacity = maxCapacity;
|
||||
}
|
||||
|
@ -144,10 +157,9 @@ public class Bus extends Thread {
|
|||
// lock on next stop
|
||||
synchronized (nextStop) {
|
||||
for (Passenger p : passengers) {
|
||||
waitEmbark();
|
||||
|
||||
if (p.getDest() == nextStop) {
|
||||
synchronized (p) {
|
||||
waitEmbark();
|
||||
p.notify();
|
||||
}
|
||||
// already synced on this, func is synced
|
||||
|
@ -159,14 +171,11 @@ public class Bus extends Thread {
|
|||
|
||||
// embark passenger at a stop. Synchronizes, locks on that stop, and waits.
|
||||
// check for overflow, and if passenger should embark in the first place
|
||||
public synchronized void embarkPassengers() throws InterruptedException {
|
||||
public synchronized void embarkPassengers() throws InterruptedException, IOException {
|
||||
synchronized (nextStop) {
|
||||
try {
|
||||
ArrayList<Passenger> list = nextStop.getPassengerByDest(stops);
|
||||
ArrayList<Passenger> list = nextStop.getPassengerByDest(line, nextStopIndex);
|
||||
for (Passenger p : list) {
|
||||
synchronized (p) {
|
||||
p.notify();
|
||||
}
|
||||
waitEmbark();
|
||||
if (currentCapacity >= maxCapacity)
|
||||
continue;
|
||||
|
@ -189,9 +198,9 @@ public class Bus extends Thread {
|
|||
Logger.getInstance().print(id, "\t".repeat(indent) + "current stop: " + nextStop.getStopName());
|
||||
Logger.getInstance().print(id, "\t".repeat(indent) + "stops: ");
|
||||
|
||||
if (nextStop != stops.get(0))
|
||||
if (nextStop != line.get(0))
|
||||
nextStop.printDetails(id, indent + 1);
|
||||
for (Stop s : stops) {
|
||||
for (Stop s : line.getStops()) {
|
||||
s.printDetails(id, indent + 1);
|
||||
}
|
||||
}
|
||||
|
@ -201,25 +210,29 @@ public class Bus extends Thread {
|
|||
printDetails(0);
|
||||
}
|
||||
|
||||
// return stop list
|
||||
public ArrayList<Stop> getStops() {
|
||||
ArrayList<Stop> res = new ArrayList<Stop>(stops);
|
||||
if (nextStop != stops.get(0))
|
||||
res.add(0, nextStop);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// return last stop
|
||||
public Stop getTerminus() {
|
||||
return stops.get(stops.size() - 1);
|
||||
return line.getTerminus();
|
||||
}
|
||||
|
||||
public String getNameBus() {
|
||||
return name;
|
||||
}
|
||||
|
||||
// still there since i first didnt understand what a trip should have been. See git logs.
|
||||
public List<Stop> getStops() {
|
||||
return line.getStops();
|
||||
}
|
||||
|
||||
public void setBlockingQueue(BlockingQueue<BusInformationMessage> q) {
|
||||
blockingQueue = q;
|
||||
}
|
||||
|
||||
public void setSocketPort(int port) {
|
||||
socketPort = port;
|
||||
}
|
||||
|
||||
public Line getLine() {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
|
242
src/main/java/usherbrooke/ift630/Central.java
Normal file
242
src/main/java/usherbrooke/ift630/Central.java
Normal file
|
@ -0,0 +1,242 @@
|
|||
package usherbrooke.ift630;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
class Central {
|
||||
private ExecutorService threadsBus;
|
||||
private ExecutorService threadsSpareBusses;
|
||||
private ExecutorService threadsStop;
|
||||
private ExecutorService threadsPassenger;
|
||||
private ExecutorService threadsSocket;
|
||||
private ArrayList<Stop> stops;
|
||||
private ArrayList<Bus> busses;
|
||||
private ArrayList<Line> lines;
|
||||
private ArrayList<Passenger> passengers;
|
||||
private BlockingQueue<BusInformationMessage> blockingQueue;
|
||||
private ServerSocket socket;
|
||||
private Future<Void> socketFuture;
|
||||
private int socketPort;
|
||||
private boolean socketStop = false;
|
||||
|
||||
private int timeEmbark;
|
||||
private int timeBetweenStops;
|
||||
private int numPassengersPerBus;
|
||||
|
||||
// idk what to do with those
|
||||
private ArrayList<Integer> spacePerStop;
|
||||
private ArrayList<Integer> spacePerLine;
|
||||
|
||||
private void sendBus(String msg) {
|
||||
Bus reqB = busses.get(Integer.parseInt(msg));
|
||||
Line l = reqB.getLine();
|
||||
// if >= 2 bus are full on that line, reset counter and add a bus
|
||||
if (spacePerLine.get(l.getId()) >= 2) {
|
||||
Bus b = new Bus(l, busses.size(), timeBetweenStops, timeEmbark, numPassengersPerBus);
|
||||
b.setSocketPort(socketPort);
|
||||
b.setBlockingQueue(blockingQueue);
|
||||
|
||||
busses.add(b);
|
||||
|
||||
threadsSpareBusses.submit(b);
|
||||
|
||||
Logger.getInstance().print(0, "\t[CENTRAL] Sent a new bus on line " + l.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// should be used to see what lines need more bus and act accordingly.
|
||||
// This is hard to do w/ our implementation, since we cannot see what passenger
|
||||
// will embark on what line trivialy.
|
||||
// Therefore, when a bus is full, a new one will go get remaining passengers.
|
||||
private void refreshStops(String stop, String number) {
|
||||
int s = Integer.parseInt(stop);
|
||||
int n = Integer.parseInt(number);
|
||||
int l = 0;
|
||||
for (int k = 0 ; k < lines.size() ; k ++) {
|
||||
if (lines.get(k).getStops().contains(stops.get(s))) {
|
||||
l = k;
|
||||
}
|
||||
}
|
||||
|
||||
spacePerStop.set(s, n);
|
||||
spacePerLine.set(l, spacePerLine.get(l) + 1);
|
||||
Logger.getInstance().print(0, "\t[CENTRAL] refreshed stop value for " + stops.get(s).getStopName());
|
||||
}
|
||||
|
||||
// run TCP socket until an exception occurs
|
||||
private void runSocket() {
|
||||
if (socketFuture == null)
|
||||
// use a thread, so we dont block here
|
||||
threadsSocket.submit(() -> {
|
||||
try {
|
||||
while (!socketStop) {
|
||||
// blocks until client connects
|
||||
String txt;
|
||||
Socket s = socket.accept();
|
||||
|
||||
BufferedReader rx = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
txt = rx.readLine();
|
||||
|
||||
// split on ':'
|
||||
// 0 => who
|
||||
// 1 => id
|
||||
// 2 => arg if necessary
|
||||
String[] msg = txt.split(":");
|
||||
|
||||
if (msg[0].startsWith("FULL"))
|
||||
sendBus(msg[1]);
|
||||
else if (msg[0].startsWith("STOP")) {
|
||||
refreshStops(msg[1], msg[2]);
|
||||
}
|
||||
|
||||
// loop back to accept
|
||||
s.close();
|
||||
}
|
||||
} catch (Exception e) {Logger.getInstance().print(1, "[CENTRAL] exc " + e.getMessage()); e.printStackTrace();}
|
||||
});
|
||||
}
|
||||
|
||||
Central (int numThreadsBus, int numThreadsStop, int socketPort) throws IOException{
|
||||
threadsBus = Executors.newFixedThreadPool(numThreadsBus);
|
||||
threadsSpareBusses = Executors.newFixedThreadPool(numThreadsBus);
|
||||
threadsStop = Executors.newFixedThreadPool(numThreadsStop);
|
||||
threadsPassenger = Executors.newSingleThreadExecutor(); // doesnt need more! future balances themselves.
|
||||
threadsSocket = Executors.newSingleThreadExecutor();
|
||||
stops = new ArrayList<Stop>();
|
||||
busses = new ArrayList<Bus>();
|
||||
lines = new ArrayList<Line>();
|
||||
passengers = new ArrayList<Passenger>();
|
||||
spacePerStop = new ArrayList<Integer>();
|
||||
spacePerLine = new ArrayList<Integer>();
|
||||
blockingQueue = new LinkedBlockingQueue<BusInformationMessage>();
|
||||
|
||||
this.socketPort = socketPort;
|
||||
socket = new ServerSocket(socketPort);
|
||||
runSocket();
|
||||
}
|
||||
|
||||
// init stops
|
||||
public void createStops(int numStops, int numPassengersPerStop) {
|
||||
for (int k = 0; k < numStops; k++) {
|
||||
Stop s = new Stop(k, numPassengersPerStop);
|
||||
s.setBlockingQueue(blockingQueue);
|
||||
s.setSocketPort(socketPort);
|
||||
|
||||
stops.add(s);
|
||||
s.setThreadPool(threadsStop);
|
||||
threadsStop.submit(s);
|
||||
}
|
||||
|
||||
for (int k = 0 ; k < stops.size() ; k++)
|
||||
spacePerStop.add(k, 0);
|
||||
}
|
||||
|
||||
// init lines (need stops to be init before)
|
||||
public void createLines(int numLines, int numStopPerBus, int numStops) throws Exception {
|
||||
for (int k = 0 ; k < numLines ; k++) {
|
||||
Stop s;
|
||||
if (numStopPerBus > stops.size())
|
||||
throw new Exception("not enough stops");
|
||||
ArrayList<Stop> s_list = new ArrayList<Stop>();
|
||||
while (s_list.size() < numStopPerBus) {
|
||||
do {
|
||||
s = stops.get((int) (Math.random() * numStops));
|
||||
} while (s_list.contains(s));
|
||||
s_list.add(s);
|
||||
}
|
||||
|
||||
Line l = new Line(k, s_list);
|
||||
lines.add(l);
|
||||
}
|
||||
|
||||
for (int k = 0 ; k < lines.size() ; k++)
|
||||
spacePerLine.add(k, 0);
|
||||
}
|
||||
|
||||
// init busses
|
||||
public void createBusses(int numBusses, int timeBetweenStops, int timeEmbark, int numPassengersPerBus) throws IOException{
|
||||
this.numPassengersPerBus = numPassengersPerBus;
|
||||
this.timeBetweenStops = timeBetweenStops;
|
||||
for (int k = 0; k < numBusses; k++) {
|
||||
Line l = lines.get(k % lines.size());
|
||||
Bus b = new Bus(l, k, timeBetweenStops, timeEmbark, numPassengersPerBus);
|
||||
b.setSocketPort(socketPort);
|
||||
b.setBlockingQueue(blockingQueue);
|
||||
|
||||
busses.add(b);
|
||||
}
|
||||
}
|
||||
|
||||
// init pasengers
|
||||
public void createPassengers(int numPassengersPerStop, int numStopPerBus) {
|
||||
// make passenger
|
||||
int idPassenger = 0;
|
||||
for (Bus b : busses) {
|
||||
for (Stop start : b.getStops()) {
|
||||
// if not found or is terminus, dont use
|
||||
int idx = b.getStops().indexOf(start);
|
||||
if (idx == -1 || start == b.getTerminus())
|
||||
continue;
|
||||
|
||||
// rand number of passenger per stop
|
||||
for (int k = 0; k < (int) (Math.random() * numPassengersPerStop); k++) {
|
||||
Stop dest = null;
|
||||
// dest is random from list of stops of this line
|
||||
|
||||
dest = b.getStops().get(idx + 1 + (int) Math.round(Math.random() * (numStopPerBus - 2 - idx)));
|
||||
|
||||
// create them!
|
||||
Passenger p = new Passenger(idPassenger, start, dest);
|
||||
passengers.add(p);
|
||||
start.addPassenger(p);
|
||||
idPassenger++;
|
||||
|
||||
threadsPassenger.submit(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pretty print!
|
||||
public void printDetails() {
|
||||
for (Bus b : busses) {
|
||||
b.printDetails();
|
||||
}
|
||||
}
|
||||
|
||||
// start bus thread
|
||||
public void startBusThreads() {
|
||||
for (Bus b : busses)
|
||||
threadsBus.submit(b);
|
||||
}
|
||||
|
||||
// shutdowns all threand & return.
|
||||
public void shutdown() {
|
||||
// block stop and passenger pool once bus have finished
|
||||
try {
|
||||
threadsBus.shutdown();
|
||||
threadsBus.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
threadsSpareBusses.shutdown();
|
||||
threadsSpareBusses.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
threadsStop.shutdown();
|
||||
threadsStop.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
threadsPassenger.shutdown();
|
||||
threadsPassenger.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
socketStop = true;
|
||||
//threadsSocket.shutdown();
|
||||
//threadsSocket.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
52
src/main/java/usherbrooke/ift630/Line.java
Normal file
52
src/main/java/usherbrooke/ift630/Line.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
package usherbrooke.ift630;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Line {
|
||||
private List<Stop> stops;
|
||||
private String name;
|
||||
private int id;
|
||||
|
||||
Line(int id, ArrayList<Stop> stops) {
|
||||
this.id = id;
|
||||
this.name = "Line " + this.id;
|
||||
this.stops = stops;
|
||||
}
|
||||
|
||||
// get stops from index
|
||||
public List<Stop> getStops(int index) {
|
||||
return stops.subList(index, stops.size() - 1);
|
||||
}
|
||||
|
||||
public List<Stop> getStops() {
|
||||
return stops;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void printDetails() {
|
||||
printDetails(0);
|
||||
}
|
||||
|
||||
public void printDetails(int indent) {
|
||||
Logger.getInstance().print(id, "\t.".repeat(indent) + "[TRIP] " + name);
|
||||
for (Stop s : stops) {
|
||||
s.printDetails(id, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public Stop get(int idx) {
|
||||
return stops.get(idx);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Stop getTerminus() {
|
||||
return stops.get(stops.size() - 1);
|
||||
}
|
||||
}
|
|
@ -10,16 +10,14 @@ public class Passenger extends Thread {
|
|||
private int id;
|
||||
private Stop dest;
|
||||
private Stop start;
|
||||
private ExecutorService threads;
|
||||
private ExecutorService ex;
|
||||
private Future<Void> future;
|
||||
|
||||
Passenger(int id, Stop start, Stop dest) {
|
||||
this.id = id;
|
||||
this.name = "Passenger " + id;
|
||||
this.dest = dest;
|
||||
this.start = start;
|
||||
this.ex = Executors.newFixedThreadPool(2); // one for each future.
|
||||
this.ex = Executors.newFixedThreadPool(1); // one for each future.
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
@ -32,23 +30,23 @@ public class Passenger extends Thread {
|
|||
}
|
||||
|
||||
// embark people once thread notified
|
||||
private synchronized Future<Void> embark() {
|
||||
private Future<Void> embark() {
|
||||
return ex.submit(() -> {
|
||||
synchronized (this) {
|
||||
wait();
|
||||
}
|
||||
Logger.getInstance().print(id, "\t[PASSENGER] I'm embarking at " + start.getStopName());
|
||||
Logger.getInstance().print(id, "\t[PASSENGER] " + name + " embarking at " + start.getStopName());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
// disembark people once thread notified another time.
|
||||
private synchronized Future<Void> disembark() {
|
||||
private Future<Void> disembark() {
|
||||
return ex.submit(() -> {
|
||||
synchronized (this) {
|
||||
wait();
|
||||
}
|
||||
Logger.getInstance().print(id, "\t[PASSENGER] I'm leaving at " + dest.getStopName());
|
||||
Logger.getInstance().print(id, "\t[PASSENGER] " + name + " leaving at " + dest.getStopName());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
@ -84,8 +82,4 @@ public class Passenger extends Thread {
|
|||
public void printDetails() {
|
||||
printDetails(0);
|
||||
}
|
||||
|
||||
public void setThreadPool(ExecutorService threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package usherbrooke.ift630;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.net.Socket;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.ArrayList;
|
||||
|
@ -10,9 +13,27 @@ public class Stop extends Thread {
|
|||
private int id;
|
||||
private int maxCapacity;
|
||||
private int indent = 0;
|
||||
private int socketPort;
|
||||
private ArrayList<Passenger> passengers;
|
||||
private ExecutorService threads;
|
||||
private BlockingQueue<BusInformationMessage> blockingQueue;
|
||||
private Socket socket;
|
||||
private PrintWriter socketTx;
|
||||
|
||||
|
||||
private void connectSocket() throws IOException {
|
||||
socket = new Socket("localhost", socketPort);
|
||||
socketTx = new PrintWriter(socket.getOutputStream(), true);
|
||||
}
|
||||
|
||||
//
|
||||
private void sendCurrentCapacity() throws IOException {
|
||||
connectSocket();
|
||||
// prone to over estimation. Some passenger will take other lines.
|
||||
// One again, i did not understand lines before last question. see git logs.
|
||||
socketTx.println("STOP:" + id + ":" + passengers.size());
|
||||
socket.close();
|
||||
}
|
||||
|
||||
// print bus info times.
|
||||
private void displayInfos(int indent) throws InterruptedException, ExitException {
|
||||
|
@ -30,8 +51,7 @@ public class Stop extends Thread {
|
|||
Logger.getInstance().print(id,
|
||||
"\t".repeat(indent) + "[STOP] " + info.getBus(this).getNameBus() + " arrives in " + time + "s");
|
||||
// else, catch
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
} catch (NullPointerException e) {}
|
||||
|
||||
} catch (UnauthorizedException e) {
|
||||
// if unauth, requeue message.
|
||||
|
@ -56,10 +76,11 @@ public class Stop extends Thread {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (;;) {
|
||||
for (;;)
|
||||
displayInfos(indent);
|
||||
}
|
||||
} catch (InterruptedException | ExitException e) {
|
||||
if (e.getClass() != ExitException.class)
|
||||
Logger.getInstance().print(id, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,10 +96,10 @@ public class Stop extends Thread {
|
|||
}
|
||||
|
||||
// return all passenger that stops at a stop in the list
|
||||
public ArrayList<Passenger> getPassengerByDest(ArrayList<Stop> list) {
|
||||
public ArrayList<Passenger> getPassengerByDest(Line l, int indexStart) {
|
||||
ArrayList<Passenger> res = new ArrayList<Passenger>();
|
||||
// for all given stop
|
||||
for (Stop s : list) {
|
||||
for (Stop s : l.getStops(indexStart)) {
|
||||
// for all passenger at this stop
|
||||
for (Passenger p : passengers) {
|
||||
// if they stop at this stop, add to res
|
||||
|
@ -125,12 +146,13 @@ public class Stop extends Thread {
|
|||
printDetails(0);
|
||||
}
|
||||
|
||||
public synchronized void removePassenger(Passenger p) {
|
||||
try {
|
||||
passengers.remove(p);
|
||||
} catch (Exception e) {
|
||||
System.out.println("exception" + e.getMessage());
|
||||
public void removePassenger(Passenger p) throws IOException {
|
||||
if(passengers.remove(p)) {
|
||||
synchronized (p) {
|
||||
p.notify();
|
||||
}
|
||||
}
|
||||
sendCurrentCapacity();
|
||||
}
|
||||
|
||||
public void setIndent(int indent) {
|
||||
|
@ -144,4 +166,8 @@ public class Stop extends Thread {
|
|||
public void setThreadPool(ExecutorService threads) {
|
||||
this.threads = threads;
|
||||
}
|
||||
|
||||
public void setSocketPort(int port) {
|
||||
socketPort = port;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue