diff --git a/src/main/java/seng302/Model/BoatInRace.java b/src/main/java/seng302/Model/BoatInRace.java index ac877240..520e7b06 100644 --- a/src/main/java/seng302/Model/BoatInRace.java +++ b/src/main/java/seng302/Model/BoatInRace.java @@ -27,6 +27,7 @@ public class BoatInRace extends Boat { private StringProperty currentLegName; private boolean started = false; private StringProperty position; + private double heading; private Queue track = new ConcurrentLinkedQueue<>(); private long nextValidTime = 0; @@ -82,6 +83,14 @@ public class BoatInRace extends Boat { } } + public double getHeading() { + return heading; + } + + public void setHeading(double heading) { + this.heading = heading; + } + /** * Calculates the bearing of the travel via map coordinates of the raceMarkers * @@ -100,7 +109,7 @@ public class BoatInRace extends Boat { * @return GPSCoordinate of wake endpoint. */ public GPSCoordinate getWake() { - double reverseHeading = calculateHeading() - 180; + double reverseHeading = getHeading() - 180; double distance = Constants.wakeScale * getVelocity(); GeodeticCalculator calc = new GeodeticCalculator(); diff --git a/src/main/java/seng302/Model/ConstantVelocityRace.java b/src/main/java/seng302/Model/ConstantVelocityRace.java index cacdb10f..84fdab19 100644 --- a/src/main/java/seng302/Model/ConstantVelocityRace.java +++ b/src/main/java/seng302/Model/ConstantVelocityRace.java @@ -10,12 +10,17 @@ import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Random; /** * Created by cbt24 on 6/03/17. + * + * @deprecated */ public class ConstantVelocityRace extends Race { + private int dnfChance = 0; //%percentage chance a boat fails at each checkpoint + /** * Initialiser for a constant velocity race without standard data source * @@ -52,6 +57,76 @@ public class ConstantVelocityRace extends Race { super(raceData, controller, scaleFactor); } + public void initialiseBoats() { + Leg officialStart = legs.get(0); + String name = officialStart.getName(); + Marker endMarker = officialStart.getEndMarker(); + + BoatInRace.setTrackPointTimeInterval(BoatInRace.getBaseTrackPointTimeInterval() / scaleFactor); + + ArrayList startMarkers = getSpreadStartingPositions(); + for (int i = 0; i < startingBoats.size(); i++) { + BoatInRace boat = startingBoats.get(i); + if (boat != null) { + boat.setScaledVelocity(boat.getVelocity() * scaleFactor); + Leg startLeg = new Leg(name, 0); + boat.setCurrentPosition(startMarkers.get(i).getAverageGPSCoordinate()); + startLeg.setStartMarker(startMarkers.get(i)); + startLeg.setEndMarker(endMarker); + startLeg.calculateDistance(); + boat.setCurrentLeg(startLeg); + boat.setHeading(boat.calculateHeading()); + } + } + } + + /** + * Creates a list of starting positions for the different boats, so they do not appear cramped at the start line + * + * @return list of starting positions + */ + public ArrayList getSpreadStartingPositions() { + + int nBoats = startingBoats.size(); + Marker marker = legs.get(0).getStartMarker(); + + GeodeticCalculator initialCalc = new GeodeticCalculator(); + initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); + initialCalc.setDestinationGeographicPoint(marker.getMark2().getLongitude(), marker.getMark2().getLatitude()); + + double azimuth = initialCalc.getAzimuth(); + double distanceBetweenMarkers = initialCalc.getOrthodromicDistance(); + double distanceBetweenBoats = distanceBetweenMarkers / (nBoats + 1); + + GeodeticCalculator positionCalc = new GeodeticCalculator(); + positionCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); + ArrayList positions = new ArrayList<>(); + + for (int i = 0; i < nBoats; i++) { + positionCalc.setDirection(azimuth, distanceBetweenBoats); + Point2D position = positionCalc.getDestinationGeographicPoint(); + positions.add(new Marker(new GPSCoordinate(position.getY(), position.getX()))); + + positionCalc = new GeodeticCalculator(); + positionCalc.setStartingGeographicPoint(position); + } + return positions; + } + + /** + * Sets the chance each boat has of failing at a gate or marker + * @param chance percentage chance a boat has of failing per checkpoint. + */ + protected void setDnfChance(int chance) { + if (chance >= 0 && chance <= 100) { + dnfChance = chance; + } + } + + protected boolean doNotFinish() { + Random rand = new Random(); + return rand.nextInt(100) < dnfChance; + } /** * Calculates the distance a boat has travelled and updates its current position according to this value. @@ -68,6 +143,7 @@ public class ConstantVelocityRace extends Race { boolean finish = boat.getCurrentLeg().getName().equals("Finish"); if (!finish) { + boat.setHeading(boat.calculateHeading()); //update boat's distance travelled boat.setDistanceTravelledInLeg(totalDistanceTravelled); //Calculate boat's new position by adding the distance travelled onto the start point of the leg @@ -76,6 +152,35 @@ public class ConstantVelocityRace extends Race { } } + protected void checkPosition(BoatInRace boat, long timeElapsed) { + if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()) { + //boat has passed onto new leg + if (boat.getCurrentLeg().getName().equals("Finish")) { + //boat has finished + boatsFinished++; + boat.setFinished(true); + boat.setTimeFinished(timeElapsed); + } else if (doNotFinish()) { + boatsFinished++; + boat.setFinished(true); + boat.setCurrentLeg(new Leg("DNF", -1)); + boat.setVelocity(0); + boat.setScaledVelocity(0); + } else { + //Calculate how much the boat overshot the marker by + boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance()); + //Move boat on to next leg + Leg nextLeg = legs.get(boat.getCurrentLeg().getLegNumber() + 1); + + boat.setCurrentLeg(nextLeg); + //Add overshoot distance into the distance travelled for the next leg + boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg()); + } + //Update the boat display table in the GUI to reflect the leg change + updatePositions(); + } + } + /** * Calculates the boats next GPS position based on its distance travelled and heading * diff --git a/src/main/java/seng302/Model/Race.java b/src/main/java/seng302/Model/Race.java index fa2a045c..bfc1d518 100644 --- a/src/main/java/seng302/Model/Race.java +++ b/src/main/java/seng302/Model/Race.java @@ -27,12 +27,10 @@ public abstract class Race implements Runnable { protected RaceController controller; protected int boatsFinished = 0; protected long totalTimeElapsed; - private int dnfChance = 1; //%percentage chance a boat fails at each checkpoint private int lastFPS = 20; protected int scaleFactor; - private int SLEEP_TIME = 100; //time in milliseconds to pause in a paced loop protected int PRERACE_TIME = 120000; //time in milliseconds to pause during pre-race private boolean timerEnabled = true; //boolean to determine if timer is ran @@ -64,40 +62,30 @@ public abstract class Race implements Runnable { this(raceData.getBoats(), raceData.getLegs(), controller, scaleFactor); } + public abstract void initialiseBoats(); + /** - * Sets the chance each boat has of failing at a gate or marker - * @param chance percentage chance a boat has of failing per checkpoint. + * Randomly generate number to see if boat fails + * @return True if number lower than dnfChance else false */ - protected void setDnfChance(int chance) { - if (chance >= 0 && chance <= 100) { - dnfChance = chance; - } - } - - - public void initialiseBoats() { - - Leg officialStart = legs.get(0); - String name = officialStart.getName(); - Marker endMarker = officialStart.getEndMarker(); + protected abstract boolean doNotFinish(); - BoatInRace.setTrackPointTimeInterval(BoatInRace.getBaseTrackPointTimeInterval() / scaleFactor); - - ArrayList startMarkers = getSpreadStartingPositions(); - for (int i = 0; i < startingBoats.size(); i++) { - BoatInRace boat = startingBoats.get(i); - if (boat != null) { - boat.setScaledVelocity(boat.getVelocity() * scaleFactor); - Leg startLeg = new Leg(name, 0); - boat.setCurrentPosition(startMarkers.get(i).getAverageGPSCoordinate()); - startLeg.setStartMarker(startMarkers.get(i)); - startLeg.setEndMarker(endMarker); - startLeg.calculateDistance(); - boat.setCurrentLeg(startLeg); + /** + * Checks the position of the boat, this updates the boats current position. + * + * @param boat Boat that the postion is to be updated for. + * @param timeElapsed Time that has elapse since the start of the the race. + * @see BoatInRace + */ + protected abstract void checkPosition(BoatInRace boat, long timeElapsed); - } - } - } + /** + * Updates the boat's gps coordinates depending on time elapsed + * + * @param boat to be updated + * @param millisecondsElapsed time since last update + */ + protected abstract void updatePosition(BoatInRace boat, int millisecondsElapsed); /** * Runnable for the thread. @@ -193,15 +181,6 @@ public abstract class Race implements Runnable { }); } - /** - * Randomly generate number to see if boat fails - * @return True if number lower than dnfChance else false - */ - private boolean doNotFinish() { - Random rand = new Random(); - return rand.nextInt(100) < dnfChance; - } - /** * Starts the Race Simulation, playing the race start to finish with the timescale. * This prints the boats participating, the order that the events occur in time order, and the respective information of the events. @@ -233,18 +212,10 @@ public abstract class Race implements Runnable { checkPosition(boat, totalTimeElapsed); } } - -// if (controller != null) controller.updateMap(startingBoats); if (timerEnabled) updateTime(calcTimer()); } controller.updateMap(startingBoats); -// } else { -// //Exit animation timer -// updateTime(calcTimer()); -// updateFPS(0); //race ended so fps = 0 -// stop(); //exit animation timer -// } fps++; if ((System.currentTimeMillis() - timeCurrent) > 1000) { updateFPS(fps); @@ -258,46 +229,10 @@ public abstract class Race implements Runnable { }.start(); } - /** - * Checks the position of the boat, this updates the boats current position. - * - * @param boat Boat that the postion is to be updated for. - * @param timeElapsed Time that has elapse since the start of the the race. - * @see BoatInRace - */ - protected void checkPosition(BoatInRace boat, long timeElapsed) { - if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()) { - //boat has passed onto new leg - if (boat.getCurrentLeg().getName().equals("Finish")) { - //boat has finished - boatsFinished++; - boat.setFinished(true); - boat.setTimeFinished(timeElapsed); - } else if (doNotFinish()) { - boatsFinished++; - boat.setFinished(true); - boat.setCurrentLeg(new Leg("DNF", -1)); - boat.setVelocity(0); - boat.setScaledVelocity(0); - } else { - //Calculate how much the boat overshot the marker by - boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance()); - //Move boat on to next leg - Leg nextLeg = legs.get(boat.getCurrentLeg().getLegNumber() + 1); - - boat.setCurrentLeg(nextLeg); - //Add overshoot distance into the distance travelled for the next leg - boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg()); - } - //Update the boat display table in the GUI to reflect the leg change - updatePositions(); - } - } - /** * Update position of boats in race, no position if on starting leg or DNF. */ - private void updatePositions() { + protected void updatePositions() { FXCollections.sort(startingBoats, (a, b) -> b.getCurrentLeg().getLegNumber() - a.getCurrentLeg().getLegNumber()); for(BoatInRace boat: startingBoats) { if(boat != null) { @@ -325,45 +260,4 @@ public abstract class Race implements Runnable { public ObservableList getStartingBoats() { return startingBoats; } - - /** - * Updates the boat's gps coordinates depending on time elapsed - * - * @param boat to be updated - * @param millisecondsElapsed time since last update - */ - protected abstract void updatePosition(BoatInRace boat, int millisecondsElapsed); - - /** - * Creates a list of starting positions for the different boats, so they do not appear cramped at the start line - * - * @return list of starting positions - */ - public ArrayList getSpreadStartingPositions() { - - int nBoats = startingBoats.size(); - Marker marker = legs.get(0).getStartMarker(); - - GeodeticCalculator initialCalc = new GeodeticCalculator(); - initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); - initialCalc.setDestinationGeographicPoint(marker.getMark2().getLongitude(), marker.getMark2().getLatitude()); - - double azimuth = initialCalc.getAzimuth(); - double distanceBetweenMarkers = initialCalc.getOrthodromicDistance(); - double distanceBetweenBoats = distanceBetweenMarkers / (nBoats + 1); - - GeodeticCalculator positionCalc = new GeodeticCalculator(); - positionCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); - ArrayList positions = new ArrayList<>(); - - for (int i = 0; i < nBoats; i++) { - positionCalc.setDirection(azimuth, distanceBetweenBoats); - Point2D position = positionCalc.getDestinationGeographicPoint(); - positions.add(new Marker(new GPSCoordinate(position.getY(), position.getX()))); - - positionCalc = new GeodeticCalculator(); - positionCalc.setStartingGeographicPoint(position); - } - return positions; - } } diff --git a/src/main/java/seng302/Model/ResizableRaceCanvas.java b/src/main/java/seng302/Model/ResizableRaceCanvas.java index 95747d0d..da83b5f1 100644 --- a/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -323,12 +323,12 @@ public class ResizableRaceCanvas extends Canvas { boolean finished = boat.getCurrentLeg().getName().equals("Finish") || boat.getCurrentLeg().getName().equals("DNF"); boolean isStart = boat.isStarted(); if (!finished && isStart) { - displayBoat(boat, boat.calculateHeading()); + displayBoat(boat, boat.getHeading()); GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition()); GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake()); displayLine(wakeFrom, wakeTo, boat.getColour()); } else if (!isStart) { - displayBoat(boat, boat.calculateHeading()); + displayBoat(boat, boat.getHeading()); } else { displayBoat(boat, 0); } diff --git a/src/test/java/seng302/Model/RaceTest.java b/src/test/java/seng302/Model/RaceTest.java index 25b12ded..859e74e6 100644 --- a/src/test/java/seng302/Model/RaceTest.java +++ b/src/test/java/seng302/Model/RaceTest.java @@ -29,7 +29,7 @@ public class RaceTest { ArrayList legs = new ArrayList<>(); legs.add(START_LEG); legs.add(FINISH_LEG); - Race race = new ConstantVelocityRace(boats, legs, null, 5); + ConstantVelocityRace race = new ConstantVelocityRace(boats, legs, null, 5); race.disableTimer(); race.setDnfChance(0); long timeStarted = System.currentTimeMillis();