diff options
| author | Camil Staps | 2015-05-29 12:06:42 +0200 | 
|---|---|---|
| committer | Camil Staps | 2015-05-29 12:06:42 +0200 | 
| commit | a68fa3c3c96c38b811755022089cb8aee2f5521c (patch) | |
| tree | ef1463ba40bffedfb22aeca5547c7129c2dc3aca /Week14 Route 66 | |
| parent | Overviewer 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')
| -rw-r--r-- | Week14 Route 66/nbproject/project.properties | 6 | ||||
| -rw-r--r-- | Week14 Route 66/src/OO14route66/Car.java | 13 | ||||
| -rw-r--r-- | Week14 Route 66/src/OO14route66/Direction.java | 15 | ||||
| -rw-r--r-- | Week14 Route 66/src/OO14route66/Model.java | 85 | ||||
| -rw-r--r-- | Week14 Route 66/src/OO14route66/RoadView.java | 12 | ||||
| -rw-r--r-- | Week14 Route 66/src/com/camilstaps/route66/Crossing.java | 61 | ||||
| -rw-r--r-- | Week14 Route 66/src/com/camilstaps/route66/Driver.java | 32 | ||||
| -rw-r--r-- | Week14 Route 66/src/com/camilstaps/route66/Overviewer.java | 64 | 
8 files changed, 206 insertions, 82 deletions
| diff --git a/Week14 Route 66/nbproject/project.properties b/Week14 Route 66/nbproject/project.properties index faae679..93592ec 100644 --- a/Week14 Route 66/nbproject/project.properties +++ b/Week14 Route 66/nbproject/project.properties @@ -1,9 +1,10 @@  annotation.processing.enabled=true  annotation.processing.enabled.in.editor=false -annotation.processing.processor.options=  annotation.processing.processors.list=  annotation.processing.run.all.processors=true  annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +application.title=Week14 Route 66 +application.vendor=camilstaps  build.classes.dir=${build.dir}/classes  build.classes.excludes=**/*.java,**/*.form  # This directory is removed when the project is cleaned: @@ -26,6 +27,7 @@ dist.archive.excludes=  dist.dir=dist  dist.jar=${dist.dir}/Week14_Route_66.jar  dist.javadoc.dir=${dist.dir}/javadoc +endorsed.classpath=  excludes=  includes=**  jar.compress=false @@ -53,7 +55,7 @@ javadoc.splitindex=true  javadoc.use=true  javadoc.version=false  javadoc.windowtitle= -main.class=com.camilstaps.route66.Week14Route66 +main.class=OO14route66.Route66  manifest.file=manifest.mf  meta.inf.dir=${src.dir}/META-INF  mkdist.disabled=false 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; -    } - -} | 
