aboutsummaryrefslogtreecommitdiff
path: root/Week14 Route 66/src
diff options
context:
space:
mode:
authorCamil Staps2015-05-29 12:06:42 +0200
committerCamil Staps2015-05-29 12:06:42 +0200
commita68fa3c3c96c38b811755022089cb8aee2f5521c (patch)
treeef1463ba40bffedfb22aeca5547c7129c2dc3aca /Week14 Route 66/src
parentOverviewer without Map (diff)
Intermediate commit: works partially, but sometimes cars go over each other (Crossing.isAllowed() is not synchronized)
Diffstat (limited to 'Week14 Route 66/src')
-rw-r--r--Week14 Route 66/src/OO14route66/Car.java13
-rw-r--r--Week14 Route 66/src/OO14route66/Direction.java15
-rw-r--r--Week14 Route 66/src/OO14route66/Model.java85
-rw-r--r--Week14 Route 66/src/OO14route66/RoadView.java12
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Crossing.java61
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Driver.java32
-rw-r--r--Week14 Route 66/src/com/camilstaps/route66/Overviewer.java64
7 files changed, 202 insertions, 80 deletions
diff --git a/Week14 Route 66/src/OO14route66/Car.java b/Week14 Route 66/src/OO14route66/Car.java
index 97d7b33..c12291a 100644
--- a/Week14 Route 66/src/OO14route66/Car.java
+++ b/Week14 Route 66/src/OO14route66/Car.java
@@ -1,7 +1,6 @@
package OO14route66;
import com.camilstaps.route66.Driver;
-import com.camilstaps.route66.Overviewer;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
@@ -47,9 +46,8 @@ public class Car {
direction = Direction.intToDirection(number);
location = RoadView.WINDOWSIZE - 2 - (number/Model.DIRECTIONS) * (CARLENGTH + MINCARSPACE);
colour = carColours[number % carColours.length];
- driver = new Driver(this);
+ driver = new Driver(this, model);
this.model = model;
- Overviewer.getInstance().hello(this);
}
/**
@@ -97,8 +95,17 @@ public class Car {
*/
public void step() {
location = getNewLocation();
+ //System.err.println("Car ");
model.update();
}
+
+ public boolean isInFrontOfCrossing() {
+ return location < RoadView.getStartCrossing() && getNewLocation() >= RoadView.getStartCrossing();
+ }
+
+ public boolean isOnCrossing() {
+ return location > RoadView.getStartCrossing() && location - CARLENGTH < RoadView.getEndCrossing();
+ }
/**
* Paint this car
diff --git a/Week14 Route 66/src/OO14route66/Direction.java b/Week14 Route 66/src/OO14route66/Direction.java
index b8c1636..14d7110 100644
--- a/Week14 Route 66/src/OO14route66/Direction.java
+++ b/Week14 Route 66/src/OO14route66/Direction.java
@@ -37,6 +37,21 @@ public enum Direction
}
}
}
+
+ /**
+ * 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
diff --git a/Week14 Route 66/src/OO14route66/Model.java b/Week14 Route 66/src/OO14route66/Model.java
index c79aa4e..f4e725f 100644
--- a/Week14 Route 66/src/OO14route66/Model.java
+++ b/Week14 Route 66/src/OO14route66/Model.java
@@ -1,7 +1,10 @@
package OO14route66;
+import com.camilstaps.route66.Crossing;
import java.util.ArrayList;
import java.util.Observable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.swing.JFrame;
/**
@@ -12,13 +15,13 @@ import javax.swing.JFrame;
*/
public class Model extends Observable
{
- private final Car [] cars;
- public static final int
- DIRECTIONS = 2,
+ private final Car [] cars;
+ public static final int
+ DIRECTIONS = 4,
NUMBEROFCARS = 5 * DIRECTIONS; // total number of cars in system
- private final ArrayList<JFrame> views;
-
+ private final ArrayList<JFrame> views;
+ private final Crossing crossing = new Crossing(this, Direction.North);
/**
* Constructor: create all cars
@@ -55,9 +58,79 @@ public class Model extends Observable
/**
* repaint all views
*/
- public void update() {
+ 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) {
+ Car that_car = cars[car.getNumber() < DIRECTIONS ? car.getNumber() + NUMBEROFCARS - DIRECTIONS : car.getNumber() - DIRECTIONS];
+
+ boolean ok;
+
+ System.err.println("Car " + car.getNumber() + " requests safety.");
+
+ do {
+ ok = !(that_car.getLocation() > requested_location &&
+ that_car.getLocation() < requested_location + Car.CARLENGTH + Car.MINCARSPACE);
+
+// if (!ok && that_car.getDriver().getWaitingToCross()) {
+// crossing.doRequest();
+// }
+
+ if (car.isInFrontOfCrossing() && !crossing.isAllowed(car.getDirection())) {
+ System.err.println("Requesting switch for car " + car.getNumber());
+ ok = false;
+ //if (!car.getDriver().getWaitingToCross()) {
+ //car.getDriver().setWaitingToCross(true);
+ ok = crossing.doRequest();
+ //car.getDriver().setWaitingToCross(!ok);
+ //}
+ }
+
+ if (!ok) {
+ System.err.println("Car " + car.getNumber() + " waiting.");
+ try {
+ wait();
+ } catch (InterruptedException ex) {
+ }
+ System.err.println("Car " + car.getNumber() + " acquired lock.");
+ }
+ } while (!ok);
+
+ System.err.println("Car " + car.getNumber() + " has safe location.");
+
+ return ok;
+ }
+
+ public synchronized boolean isNoCarsOnCrossing() {
+ boolean ok = false;
+ while (!ok) {
+ ok = true;
+ for (Car car : cars) {
+ if (car.isOnCrossing()) {
+ System.err.println("Car " + car.getNumber() + " is on crossing.");
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Checking crossing waiting");
+ try {
+ wait();
+ } catch (InterruptedException ex) {
+ }
+ System.err.println("Checking crossing");
+ }
+ }
+ return true;
}
}
diff --git a/Week14 Route 66/src/OO14route66/RoadView.java b/Week14 Route 66/src/OO14route66/RoadView.java
index 1d53269..4495822 100644
--- a/Week14 Route 66/src/OO14route66/RoadView.java
+++ b/Week14 Route 66/src/OO14route66/RoadView.java
@@ -74,8 +74,8 @@ public class RoadView extends JFrame
* @param g graphics to draw on
*/
private void paintRoad (Graphics g) {
- final int left = (WINDOWSIZE / 2) - Car.CARWIDTH - 4;
- final int width = 2 * Car.CARWIDTH + 8;
+ 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
@@ -84,4 +84,12 @@ public class RoadView extends JFrame
g.fillRect(left, 0, width, WINDOWSIZE);
}
}
+
+ public static int getStartCrossing() {
+ return (WINDOWSIZE / 2) - Car.CARWIDTH - 4;
+ }
+
+ public static int getEndCrossing() {
+ return getStartCrossing() + 2 * Car.CARWIDTH + 8;
+ }
}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Crossing.java b/Week14 Route 66/src/com/camilstaps/route66/Crossing.java
new file mode 100644
index 0000000..eba5bfe
--- /dev/null
+++ b/Week14 Route 66/src/com/camilstaps/route66/Crossing.java
@@ -0,0 +1,61 @@
+/*
+ * 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 waiting = 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() {
+ waiting = true;
+ while (!model.isNoCarsOnCrossing());
+ 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);
+ waiting = false;
+ //notifyAll();
+ }
+
+ public boolean isAllowed(Direction direction) {
+ return !waiting && (direction == allowed || Direction.opposite(direction) == allowed);
+ }
+
+ public boolean doRequest() {
+ //if (++requests >= 2) {
+ if (waiting) {
+ return false;
+ }
+ doSwitch();
+ return true;
+ //}
+ //return false;
+ }
+
+}
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Driver.java b/Week14 Route 66/src/com/camilstaps/route66/Driver.java
index e2e5a7d..4a323cd 100644
--- a/Week14 Route 66/src/com/camilstaps/route66/Driver.java
+++ b/Week14 Route 66/src/com/camilstaps/route66/Driver.java
@@ -8,27 +8,46 @@ import OO14route66.Model;
import java.util.Random;
/**
- *
- * @author camilstaps
+ * A Driver takes care its car doesn't collide
+ * @author Camil Staps
*/
public class Driver implements Runnable {
private final Car car;
+ private final Model model;
private final Random r;
- private boolean running;
+ private boolean running, waitingToCross = false;
private int delay;
- public Driver(Car car) {
+ public Driver(Car car, Model model) {
this.car = car;
+ this.model = model;
r = new Random();
}
+ /**
+ * Set running to false to disable driving altogether
+ * @param value
+ */
public void setRunning(boolean value) {
running = value;
}
+ public void setWaitingToCross(boolean value) {
+ waitingToCross = value;
+ }
+
+ public boolean getWaitingToCross() {
+ return waitingToCross;
+ }
+
+ /**
+ * Set some approximate delay for {@link Driver#pause()}. The actual delay
+ * is still pseudorandom.
+ * @param value
+ */
public void setDelay(int value) {
delay = value;
}
@@ -38,7 +57,7 @@ public class Driver implements Runnable {
public void run() {
running = true;
while (true) {
- while (!running || !Overviewer.getInstance().isSafeLocation(car, car.getNewLocation()));
+ while (!running || !model.isSafeLocation(car, car.getNewLocation()));
car.step();
@@ -46,6 +65,9 @@ public class Driver implements Runnable {
}
}
+ /**
+ * Pause for some pseudorandom time
+ */
protected void pause() {
try {
int bonus = 0;
diff --git a/Week14 Route 66/src/com/camilstaps/route66/Overviewer.java b/Week14 Route 66/src/com/camilstaps/route66/Overviewer.java
deleted file mode 100644
index 844f40c..0000000
--- a/Week14 Route 66/src/com/camilstaps/route66/Overviewer.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
-package com.camilstaps.route66;
-
-import OO14route66.Car;
-import OO14route66.Model;
-
-/**
- * The Overviewer (always only one instance) tells Drivers when they can drive
- *
- * @author Camil Staps
- */
-public class Overviewer {
-
- /**
- * This is a singleton
- */
- private static Overviewer instance;
-
- Car[] cars = new Car[Model.NUMBEROFCARS];
-
- /**
- * This is a singleton
- * @return the instance
- */
- public static Overviewer getInstance() {
- if (instance == null) {
- instance = new Overviewer();
- }
- return instance;
- }
-
- /**
- * Add a car to the list of cars
- * @param car
- */
- public synchronized void hello(Car car) {
- cars[car.getNumber()] = car;
- }
-
- /**
- * 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) {
- for (Car that_car : cars) {
- if (that_car != null && that_car != car &&
- that_car.getDirection() == car.getDirection() &&
- that_car.getLocation() > requested_location &&
- that_car.getLocation() < requested_location + Car.CARLENGTH + Car.MINCARSPACE) {
- return false;
- }
- }
- return true;
- }
-
-}