aboutsummaryrefslogtreecommitdiff
path: root/Week14 Route 66/src/com/camilstaps
diff options
context:
space:
mode:
Diffstat (limited to 'Week14 Route 66/src/com/camilstaps')
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Car.java179
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Controller.java95
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Crossing.java61
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Direction.java89
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Driver.java67
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/KeyHandler.java39
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Model.java189
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/RoadView.java127
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Route66.java44
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/TableView.java65
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Week14Route66.java19
11 files changed, 876 insertions, 98 deletions
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Car.java b/Week14 Route 66/src/com/camilstaps/route66/Car.java
new file mode 100644
index 0000000..b118a3c
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Car.java
@@ -0,0 +1,179 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.camilstaps.route66;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.util.Random;
+
+/**
+ * Class for an individual car
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public class Car {
+ public static final int
+ CARWIDTH = 20,
+ CARLENGTH = 40,
+ MINCARSPACE = 5,
+ MINCARSPEED = 2,
+ MAXCARSPEED = 4;
+
+ public static final Color[] carColours = {Color.red, Color.blue, Color.black, Color.gray, Color.green,
+ Color.pink, Color.orange, Color.magenta, Color.lightGray};
+
+ private final int speed, number; // speed and car-number
+ private final Direction direction; // driving direction, used by paint
+ private int location; // current location on the road
+ private final Color colour; // colour of this car
+ private final Random random; // here to ensure that every car gets a new
+ private final Driver driver; // this car's driver
+ private final Model model; // the model the car is in
+
+ /**
+ * The constructor:
+ * - choose a random speed
+ * - set right location, direction and colour
+ * - create new Driver object
+ *
+ * @param number of the car
+ * @param model the model the car is in
+ */
+ public Car(int number, Model model) {
+ this.number = number;
+ random = new Random();
+ speed = MINCARSPEED + random.nextInt(MAXCARSPEED - MINCARSPEED + 1);
+ direction = Direction.intToDirection(number);
+ location = RoadView.WINDOWSIZE - 2 - (number/Model.DIRECTIONS) * (CARLENGTH + MINCARSPACE);
+ colour = carColours[number % carColours.length];
+ this.model = model;
+ driver = new Driver(this, model);
+ }
+
+ /**
+ * Get the driver
+ * @return
+ */
+ public Driver getDriver() {
+ return driver;
+ }
+
+ /**
+ * Get the direction
+ * @return
+ */
+ public Direction getDirection() {
+ return direction;
+ }
+
+ /**
+ * Get the number of this car
+ * @return
+ */
+ public int getNumber() {
+ return number;
+ }
+
+ /**
+ * Get the current location of this car
+ * @return
+ */
+ public int getLocation() {
+ return location;
+ }
+
+ /**
+ * Get the location the car would move to if it would move
+ * @return
+ */
+ public int getNewLocation() {
+ return (location + speed) % RoadView.WINDOWSIZE;
+ }
+
+ /**
+ * Move the car one step
+ */
+ public void step() {
+ location = getNewLocation();
+ //System.err.println("Car ");
+ model.update();
+ }
+
+ /**
+ * Is the car in front of the crossing? That is, is the car now not on the
+ * crossing but would it be there after the next step?
+ * @return
+ */
+ public boolean isInFrontOfCrossing() {
+ return location < RoadView.getStartCrossing() && getNewLocation() >= RoadView.getStartCrossing();
+ }
+
+ /**
+ * Is the car on the crossing?
+ * @return
+ */
+ public boolean isOnCrossing() {
+ return location > RoadView.getStartCrossing() && location - CARLENGTH < RoadView.getEndCrossing();
+ }
+
+ /**
+ * Paint this car
+ * @param g
+ */
+ public void paint(Graphics g) {
+ int x, y, w, h;
+ switch (direction) {
+ case North:
+ x = RoadView.WINDOWSIZE / 2 + 1;
+ y = RoadView.WINDOWSIZE - location;
+ w = Car.CARWIDTH;
+ h = Car.CARLENGTH;
+ break;
+ case East:
+ x = location - Car.CARLENGTH;
+ y = RoadView.WINDOWSIZE / 2 + 1;
+ w = Car.CARLENGTH;
+ h = Car.CARWIDTH;
+ break;
+ case South:
+ x = RoadView.WINDOWSIZE / 2 - Car.CARWIDTH - 1;
+ y = location - Car.CARLENGTH;
+ w = Car.CARWIDTH;
+ h = Car.CARLENGTH;
+ break;
+ case West:
+ x = RoadView.WINDOWSIZE - location - 1;
+ y = RoadView.WINDOWSIZE / 2 - Car.CARWIDTH - 1;
+ w = Car.CARLENGTH;
+ h = Car.CARWIDTH;
+ break;
+ default:
+ x = y = w = h = 10;
+ }
+ g.setColor(colour);
+ g.fillRect(x, y, w, h);
+ g.setColor(Color.WHITE);
+ g.drawString(String.valueOf(number), x + w / 6, y + h / 2 + 4);
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Controller.java b/Week14 Route 66/src/com/camilstaps/route66/Controller.java
new file mode 100644
index 0000000..e0eff83
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Controller.java
@@ -0,0 +1,95 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.camilstaps.route66;
+
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Route66 Controller
+ *
+ * Use different threads for every driver
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public class Controller {
+ private int delay = 120; // average sleep time
+ private final Model model; // the model
+ private final Random random; // a random generator
+
+ /**
+ * The constructor of the controller
+ * @param model holds the cars
+ */
+ public Controller(Model model) {
+ this.model = model;
+ random = new Random();
+ }
+
+ /**
+ * Tell the drivers of all cars in the model to start driving
+ */
+ public void run() {
+ ExecutorService service = Executors.newCachedThreadPool();
+ for (Car car : model.getCars()) {
+ Driver d = car.getDriver();
+ d.setDelay(delay);
+ service.execute(d);
+ }
+ }
+
+ /**
+ * Stop all cars
+ */
+ public void stopCars() {
+ for (Car car : model.getCars()) {
+ car.getDriver().stopRunning();
+ }
+ }
+
+ /**
+ * Resume all cars
+ */
+ public void resumeCars() {
+ for (Car car : model.getCars()) {
+ car.getDriver().resumeRunning();
+ }
+ }
+
+ public int getDelay() {
+ return delay;
+ }
+
+ /**
+ * Set delay between maximum and minimum bounds
+ * @param d
+ */
+ public void setDelay(int d) {
+ delay = Math.max(20, Math.min (2000, d));
+ for (Car car : model.getCars()) {
+ car.getDriver().setDelay(delay);
+ }
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Crossing.java b/Week14 Route 66/src/com/camilstaps/route66/Crossing.java
deleted file mode 100644
index 65e2527..0000000
--- a/Week14 Route 66/src/com/camilstaps/route66/Crossing.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2015 Camil Staps
- */
-package com.camilstaps.route66;
-
-import OO14route66.Direction;
-import OO14route66.Model;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- * @author camilstaps
- */
-public class Crossing {
-
- private final Model model;
- private Direction allowed;
- private boolean crossingWaiting = false;
- private int requests = 0;
-
- public Crossing(Model model, Direction allowed) {
- this.model = model;
- this.allowed = allowed;
- }
-
- public Direction getAllowed() {
- return allowed;
- }
-
- public synchronized void doSwitch() {
- crossingWaiting = true;
- while (!model.isCarsOnCrossing());
- System.err.println("Switching");
- if (allowed == Direction.East || allowed == Direction.West) {
- allowed = Direction.North;
- } else {
- allowed = Direction.East;
- }
- requests = 0;
- System.err.println("Switched to " + allowed);
- crossingWaiting = false;
- //notifyAll();
- }
-
- public boolean isAllowed(Direction direction) {
- return !crossingWaiting && (direction == allowed || Direction.opposite(direction) == allowed);
- }
-
- public boolean doRequest() {
- //if (++requests >= 2) {
- if (crossingWaiting) {
- return false;
- }
- doSwitch();
- return true;
- //}
- //return false;
- }
-
-}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Direction.java b/Week14 Route 66/src/com/camilstaps/route66/Direction.java
new file mode 100644
index 0000000..ef69caa
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Direction.java
@@ -0,0 +1,89 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.camilstaps.route66;
+
+/**
+ * OO1route66 initial class
+ *
+ * Enumeration class for driving directions
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public enum Direction
+{
+ North, East, South, West;
+
+ /**
+ * convert integer to direction
+ * if number of directions is 2 only East and West are used,
+ * otherwise all 4 directions are used
+ * @param i the integer
+ * @return the direction
+ */
+ public static Direction intToDirection(int i) {
+ if (Model.DIRECTIONS == 2) {
+ switch (i % 2) {
+ case 0: return East;
+ default: return West;
+ }
+ } else {
+ switch (i % 4) {
+ case 0: return North;
+ case 1: return East;
+ case 2: return South;
+ default: return West;
+ }
+ }
+ }
+
+ /**
+ * Get the opposite of a direction
+ * @param direction
+ * @return
+ */
+ public static Direction opposite(Direction direction) {
+ switch (direction) {
+ case North: return South;
+ case South: return North;
+ case East: return West;
+ case West: return East;
+ default: return direction;
+ }
+ }
+
+ /**
+ * override standard toString
+ * @return string representation of this value
+ */
+ @Override
+ public String toString() {
+ switch (this) {
+ case North: return "North";
+ case East: return "East";
+ case South: return "South";
+ case West: return "West";
+ default: return "Unknown direction";
+ }
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Driver.java b/Week14 Route 66/src/com/camilstaps/route66/Driver.java
index 4a323cd..ff603c8 100644
--- a/Week14 Route 66/src/com/camilstaps/route66/Driver.java
+++ b/Week14 Route 66/src/com/camilstaps/route66/Driver.java
@@ -1,14 +1,33 @@
/*
- * Copyright (c) 2015 Camil Staps
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*/
package com.camilstaps.route66;
-import OO14route66.Car;
-import OO14route66.Model;
import java.util.Random;
/**
* A Driver takes care its car doesn't collide
+ *
* @author Camil Staps
*/
public class Driver implements Runnable {
@@ -18,7 +37,7 @@ public class Driver implements Runnable {
private final Random r;
- private boolean running, waitingToCross = false;
+ private boolean running = false;
private int delay;
public Driver(Car car, Model model) {
@@ -28,19 +47,22 @@ public class Driver implements Runnable {
}
/**
- * Set running to false to disable driving altogether
- * @param value
+ * Stop running
*/
- public void setRunning(boolean value) {
- running = value;
- }
-
- public void setWaitingToCross(boolean value) {
- waitingToCross = value;
+ public void stopRunning() {
+ running = false;
}
- public boolean getWaitingToCross() {
- return waitingToCross;
+ /**
+ * Resume running
+ */
+ public void resumeRunning() {
+ if (running == false) {
+ synchronized (this) {
+ running = true;
+ notifyAll();
+ }
+ }
}
/**
@@ -53,11 +75,20 @@ public class Driver implements Runnable {
}
@Override
- @SuppressWarnings("empty-statement")
- public void run() {
+ /**
+ * Forever wait for safety, step and pause for a pseudorandom time.
+ */
+ public synchronized void run() {
running = true;
while (true) {
- while (!running || !model.isSafeLocation(car, car.getNewLocation()));
+ do {
+ while (!running) {
+ try {
+ wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+ } while (!model.isSafeLocation(car, car.getNewLocation()));
car.step();
@@ -74,7 +105,7 @@ public class Driver implements Runnable {
if (Math.abs((System.currentTimeMillis() / 1000) % Model.NUMBEROFCARS - car.getNumber()) < 2) {
bonus = -50;
}
- Thread.sleep(Math.abs(r.nextInt(50) + delay + bonus));
+ Thread.sleep(Math.abs(r.nextInt(100) + delay + bonus));
} catch (InterruptedException ex) {}
}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/KeyHandler.java b/Week14 Route 66/src/com/camilstaps/route66/KeyHandler.java
new file mode 100644
index 0000000..eb84b6f
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/KeyHandler.java
@@ -0,0 +1,39 @@
+package com.camilstaps.route66;
+
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+/**
+ * Keyboard handler of views for controller.
+ *
+ * Pressing keys changes the controller.
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public class KeyHandler extends KeyAdapter {
+
+ private final Controller controller;
+
+ public KeyHandler (Controller c) {
+ controller = c;
+ }
+
+ /**
+ * on key down 'q' stop program
+ * on key down 's' stop the cars
+ * on key down '<' decrease delay
+ * on key down '>' increase delay
+ * on any other key activate the cars
+ * @param e the key event
+ */
+ @Override
+ public void keyPressed(KeyEvent e) {
+ switch (e.getKeyChar()) {
+ case 'q': System.exit(0);
+ case 's': controller.stopCars(); break;
+ case '<': controller.setDelay(controller.getDelay() - 50); break;
+ case '>': controller.setDelay(controller.getDelay() + 50); break;
+ default : controller.resumeCars();
+ }
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Model.java b/Week14 Route 66/src/com/camilstaps/route66/Model.java
new file mode 100644
index 0000000..6e43e29
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Model.java
@@ -0,0 +1,189 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.camilstaps.route66;
+
+import java.util.ArrayList;
+import java.util.Observable;
+import javax.swing.JFrame;
+
+/**
+ * Route 66 model with crossing
+ *
+ * The class model holds all cars in the simulation.
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public class Model extends Observable {
+
+ private final Car [] cars;
+ public static final int
+ DIRECTIONS = 4,
+ NUMBEROFCARS = 5 * DIRECTIONS; // total number of cars in system
+
+ private final ArrayList<JFrame> views;
+
+ /**
+ * Crossing attributes:
+ *
+ * allowed - which direction is currently allowed; if East is allowed, West
+ * is also allowed, etc.
+ * crossingWaiting - whether or not the crossing is waiting for cars to
+ * leave the crossing to switch (i.e. orange)
+ * lastCrossingChange - when the crossing switched the last time
+ * MIN_CROSS_TIME - the minimum time the crossing should wait before
+ * switching again after the last switch
+ */
+ private Direction allowed = Direction.East;
+ private boolean crossingWaiting = false;
+ private long lastCrossingChange = 0;
+ private static final int MIN_CROSS_TIME = 1000;
+
+ /**
+ * Constructor: create all cars
+ */
+ public Model() {
+ views = new ArrayList<>();
+ cars = new Car [NUMBEROFCARS];
+ for (int c = 0; c < NUMBEROFCARS; c += 1) {
+ cars[c] = new Car(c, this);
+ }
+ }
+
+ /**
+ * add the view to this model. It will be repainted upon an update
+ * @param view
+ */
+ public void addView(JFrame view) {
+ views.add(view);
+ }
+
+ public Car[] getCars() {
+ return cars;
+ }
+
+ /**
+ * Get a car from the model
+ * @param i numbers of required car
+ * @return the car itself (not a copy)
+ */
+ public Car getCar(int i) {
+ return cars[i];
+ }
+
+ /**
+ * Repaint all views, and notify all drivers to reconsider driving
+ */
+ public synchronized void update() {
+ for (JFrame view: views) {
+ view.repaint();
+ }
+ notifyAll();
+ }
+
+ /**
+ * Check if a location is safe for a car to go to. This should always be
+ * checked by a driver before actually driving.
+ * @param car
+ * @param requested_location
+ * @return
+ */
+ public synchronized boolean isSafeLocation(Car car, int requested_location) {
+ // Check that we don't collide with the car in front of us
+ Car that_car = cars[car.getNumber() < DIRECTIONS ? car.getNumber() + NUMBEROFCARS - DIRECTIONS : car.getNumber() - DIRECTIONS];
+ boolean ok = !(that_car.getLocation() > requested_location &&
+ that_car.getLocation() < requested_location + Car.CARLENGTH + Car.MINCARSPACE);
+
+ // If we have to wait for the crossing... well, do that.
+ if (car.isInFrontOfCrossing() && !isCrossingAllowed(car.getDirection())) {
+ ok = doCrossingRequest();
+ }
+
+ if (!ok) {
+ try {
+ wait();
+ } catch (InterruptedException ex) {}
+ }
+
+ return ok;
+ }
+
+ /**
+ * Check if there are any cars on the crossing
+ * @return
+ */
+ public synchronized boolean isCarsOnCrossing() {
+ for (Car car : cars) {
+ if (car.isOnCrossing()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Switch the crossing
+ */
+ public synchronized void doSwitchCrossing() {
+ crossingWaiting = true;
+
+ while (isCarsOnCrossing()) {
+ try {
+ wait();
+ } catch (InterruptedException ex) {
+ }
+ }
+
+ if (allowed == Direction.East || allowed == Direction.West) {
+ allowed = Direction.North;
+ } else {
+ allowed = Direction.East;
+ }
+
+ crossingWaiting = false;
+ lastCrossingChange = System.currentTimeMillis();
+ }
+
+ /**
+ * Check if crossing in some direction is allowed
+ * @param direction
+ * @return
+ */
+ public synchronized boolean isCrossingAllowed(Direction direction) {
+ return !crossingWaiting && (direction == allowed || Direction.opposite(direction) == allowed);
+ }
+
+ /**
+ * Try to switch the crossing
+ * This may return false without even trying to switch, if it's too early to
+ * ask (see {@link Model#MIN_CROSS_TIME}) or if a request has been made already.
+ * @return
+ */
+ public synchronized boolean doCrossingRequest() {
+ if (crossingWaiting || System.currentTimeMillis() - lastCrossingChange < MIN_CROSS_TIME) {
+ return false;
+ }
+ doSwitchCrossing();
+ return true;
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/RoadView.java b/Week14 Route 66/src/com/camilstaps/route66/RoadView.java
new file mode 100644
index 0000000..660d44e
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/RoadView.java
@@ -0,0 +1,127 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Camil Staps <info@camilstaps.nl>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.camilstaps.route66;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+/**
+ * OO13route66 animation
+ *
+ * Yields a graphical view on all cars
+ *
+ * @author Pieter Koopman, Camil Staps
+ */
+public class RoadView extends JFrame
+{
+ JPanel panel; // the panel to draw the cars
+ public static final int WINDOWSIZE = 600; // the window size
+ private final Model model; // the model knows the position of cars
+
+ /**
+ * A subclass of JPanel to draw the cars.
+ * This is a bit of a hack to ensure that this panel is painted correctly.
+ */
+ private class CarPanel extends JPanel {
+ /**
+ * Constructor: just call the constructor of the base class
+ */
+ public CarPanel() {
+ super();
+ }
+ /**
+ * paint the roads and cars
+ * @param g Graphics to paint on
+ */
+ @Override
+ public void paint (Graphics g) {
+ paintRoad(g);
+ paintCars(g);
+ }
+ }
+ /**
+ * The constructor of RoadView
+ * @param model
+ */
+ RoadView(Model model) {
+ super("Route66 traffic simulator");
+ this.model = model;
+ setSize(WINDOWSIZE, WINDOWSIZE);
+ setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
+ panel = new CarPanel();
+ add(panel);
+ }
+ /**
+ * Paint the view of the model graphically
+ * @param g
+ */
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ panel.repaint();
+ }
+ /**
+ * Paint all cars
+ * @param g graphics to draw on
+ */
+ private void paintCars (Graphics g) {
+ for (int i = 0; i < Model.NUMBEROFCARS; i += 1) {
+ model.getCar(i).paint(g);
+ }
+ }
+
+ /**
+ * Paint the roads
+ * @param g graphics to draw on
+ */
+ private void paintRoad (Graphics g) {
+ final int left = getStartCrossing();
+ final int width = getEndCrossing() - left;
+ g.setColor(Color.white); // background
+ g.fillRect(0, 0, WINDOWSIZE, WINDOWSIZE);
+ g.setColor(Color.darkGray); // streets
+ g.fillRect(0, left, WINDOWSIZE, width);
+ if (Model.DIRECTIONS > 2) { // paint a crossing if there are 4 directions
+ g.fillRect(left, 0, width, WINDOWSIZE);
+ }
+ }
+
+ /**
+ * Get the relevant half of the coordinate where the crossing starts
+ * @return
+ */
+ public static int getStartCrossing() {
+ return (WINDOWSIZE / 2) - Car.CARWIDTH - 4;
+ }
+
+ /**
+ * Get the relevant half of the coordinate where the crossing ends
+ * @return
+ */
+ public static int getEndCrossing() {
+ return getStartCrossing() + 2 * Car.CARWIDTH + 8;
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Route66.java b/Week14 Route 66/src/com/camilstaps/route66/Route66.java
new file mode 100644
index 0000000..8f9a2e9
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Route66.java
@@ -0,0 +1,44 @@
+package com.camilstaps.route66;
+
+/**
+ * OO1route66 initial class
+ *
+ * Route66 class constructs model, view and controller
+ *
+ * @author Pieter Koopman
+ */
+public class Route66
+{
+ Controller controller;
+ /**
+ * the main method for OO13route66
+ * @param args the command line arguments
+ */
+ public static void main(String[] args) {
+ Route66 r66 = new Route66();
+ }
+
+ /**
+ * the main constructor:
+ * - creates model, controller and views
+ */
+ public Route66() {
+ Model model = new Model();
+
+ RoadView rview = new RoadView(model);
+ TableView tview = new TableView(model);
+ model.addView(tview);
+ model.addView(rview);
+
+ controller = new Controller(model);
+
+ KeyHandler keyHandler = new KeyHandler(controller);
+ rview.addKeyListener(keyHandler);
+ tview.addKeyListener(keyHandler);
+
+ tview.setVisible(true);
+ rview.setVisible(true);
+
+ controller.run();
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/TableView.java b/Week14 Route 66/src/com/camilstaps/route66/TableView.java
new file mode 100644
index 0000000..1aa38f7
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/TableView.java
@@ -0,0 +1,65 @@
+package com.camilstaps.route66;
+
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * OO14route66 initial class
+ * @author Pieter Koopman
+ */
+public class TableView extends JFrame
+{
+ JPanel panel;
+ public static final int WINDOWWITDH = 100 * Model.DIRECTIONS, WINDOWHEIGTH = 200;
+ JLabel [] textLabels;
+ private final Model model; // for the positions of the cars
+
+ /**
+ * The constructor of TableView
+ * @param model containing the position of the cars to display
+ * makes a panel with a gridLayout and a JLabel for each car in this panel
+ */
+ TableView(Model model) {
+ super("Route66 table view");
+ this.model = model;
+ setSize(WINDOWWITDH, WINDOWHEIGTH);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ panel = new JPanel();
+ panel.setLayout(new GridLayout(Model.NUMBEROFCARS / Model.DIRECTIONS + 1, Model.DIRECTIONS));
+
+ for (int i = 0; i < Model.DIRECTIONS; i += 1) { // make table headings
+ panel.add(new JLabel(Direction.intToDirection(i).toString()));
+ }
+
+ textLabels = new JLabel[Model.NUMBEROFCARS]; // make car info
+ for (int c = 0; c < Model.NUMBEROFCARS; c += 1) {
+ textLabels[c] = new JLabel(label(c));
+ panel.add(textLabels[c]);
+ }
+ add(panel);
+ }
+
+ /**
+ * update the JLabel for each car
+ * @param g
+ */
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+ for (int c = 0; c < Model.NUMBEROFCARS; c += 1) {
+ textLabels[c].setText(label(c));
+ }
+ }
+
+ /**
+ * create a label for the given car number
+ * @param c: car number
+ * @return string representing the car information
+ */
+ private String label(int c) {
+ return c + ": " + model.getCar(c).getLocation();
+ }
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Week14Route66.java b/Week14 Route 66/src/com/camilstaps/route66/Week14Route66.java
deleted file mode 100644
index 30b7bd2..0000000
--- a/Week14 Route 66/src/com/camilstaps/route66/Week14Route66.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2015 Camil Staps
- */
-package com.camilstaps.route66;
-
-/**
- *
- * @author camilstaps
- */
-public class Week14Route66 {
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- // TODO code application logic here
- }
-
-}