Merge branch 'master' of https://eng-git.canterbury.ac.nz/seng302-2017/team-7 into heading-visualisation

main
Erika Savell 9 years ago
commit 306e98172b

@ -11,18 +11,24 @@ import seng302.Controllers.MainController;
import java.io.InputStream;
public class App extends Application
{
public class App extends Application {
Stage primaryStage;
BorderPane mainContainer;
Scene mainScene;
public static void main( String[] args )
{
/**
* Entry point for running the programme
* @param args
*/
public static void main(String[] args) {
launch(args);
}
/**
* Loads and sets up the GUI elements
* @param primaryStage
* @throws Exception
*/
@Override
public void start(Stage primaryStage) throws Exception {
this.primaryStage = primaryStage;
@ -32,7 +38,7 @@ public class App extends Application
FXMLLoader loader = new FXMLLoader();
InputStream in = getClass().getClassLoader().getResourceAsStream("scenes//mainpane.fxml");
mainContainer = (BorderPane) loader.load(in);
mainScene = new Scene(mainContainer, 800, 600);
mainScene = new Scene(mainContainer, 1200, 800);
primaryStage.setScene(mainScene);
primaryStage.sizeToScene();
MainController mainController = (MainController) loader.getController();
@ -46,9 +52,14 @@ public class App extends Application
primaryStage.show();
}
public void loadPane(String fxmlName) throws Exception{
/**
* Loads panes for use in the GUI
* @param fxmlName
* @throws Exception
*/
public void loadPane(String fxmlName) throws Exception {
FXMLLoader loader = new FXMLLoader();
InputStream in = getClass().getClassLoader().getResourceAsStream("scenes//"+fxmlName);
InputStream in = getClass().getClassLoader().getResourceAsStream("scenes//" + fxmlName);
Parent page;
try {
page = (Parent) loader.load(in);

@ -2,7 +2,6 @@ package seng302;
import javafx.scene.paint.Color;
import seng302.Model.BoatInRace;
import seng302.Model.Leg;
/**
* Constants that are used throughout the program
@ -10,13 +9,11 @@ import seng302.Model.Leg;
*/
public class Constants {
public static final int NMToMetersConversion = 1852; //nautical miles
public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters
public static final GPSCoordinate startLineMarker1 = new GPSCoordinate(32.296577, -64.854304);
public static final GPSCoordinate startLineMarker2 = new GPSCoordinate(32.293771, -64.855242);
public static final GPSCoordinate mark1 = new GPSCoordinate(32.293039, -64.843983);
public static final GPSCoordinate windwardGate1 = new GPSCoordinate(32.284680, -64.850045);
public static final GPSCoordinate windwardGate2 = new GPSCoordinate(32.280164, -64.847591);
public static final GPSCoordinate leewardGate1 = new GPSCoordinate(32.309693, -64.835249);
@ -25,12 +22,11 @@ public class Constants {
public static final GPSCoordinate finishLineMarker2 = new GPSCoordinate(32.317257, -64.836260);
public static final BoatInRace[] OFFICIAL_AC35_COMPETITORS = new BoatInRace[]
{new BoatInRace("Oracle Team USA", 300.0, Color.BLUEVIOLET, "USA"),
new BoatInRace("Land Rover BAR", 500.0, Color.BLACK, "BAR"),
new BoatInRace("SoftBank Team Japan", 400.0, Color.RED, "JAP"),
new BoatInRace("Groupama Team France", 350.0, Color.ORANGE, "FRN"),
new BoatInRace("Artemis Racing", 440.0, Color.DARKOLIVEGREEN, "ART"),
new BoatInRace("Emirates Team New Zealand", 620, Color.LIMEGREEN, "ENZ")};
{new BoatInRace("Oracle Team USA", 30.0, Color.BLUEVIOLET, "USA"),
new BoatInRace("Land Rover BAR", 23.0, Color.BLACK, "BAR"),
new BoatInRace("SoftBank Team Japan", 27.0, Color.RED, "JAP"),
new BoatInRace("Groupama Team France", 25.0, Color.ORANGE, "FRN"),
new BoatInRace("Artemis Racing", 22.5, Color.DARKOLIVEGREEN, "ART"),
new BoatInRace("Emirates Team New Zealand", 62, Color.LIMEGREEN, "ENZ")};
//public static final Leg bermudaCourseStartToMark1 = new Leg(0, , new )
}

@ -10,19 +10,21 @@ import java.util.ResourceBundle;
* Controller parent for app controllers.
* Created by fwy13 on 15/03/2017.
*/
public abstract class Controller implements Initializable{
public abstract class Controller implements Initializable {
protected App parent;
/**
* Sets the parent of the application
*
* @param parent
*/
public void setParent(App parent){
public void setParent(App parent) {
this.parent = parent;
}
/**
* Sets the loads a pane into the parent.
*
* @param fxmlName
* @throws Exception
*/
@ -32,6 +34,7 @@ public abstract class Controller implements Initializable{
/**
* Initialisation class that is run on start up.
*
* @param location
* @param resources
*/

@ -1,7 +1,5 @@
package seng302.Controllers;
import javafx.fxml.Initializable;
import java.net.URL;
import java.util.ResourceBundle;
@ -12,6 +10,7 @@ public class MainController extends Controller {
/**
* Main Controller for the applications will house the menu and the displayed pane.
*
* @param location
* @param resources
*/

@ -3,12 +3,11 @@ package seng302.Controllers;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TitledPane;
@ -17,15 +16,11 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.layout.GridPane;
import javafx.util.Callback;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.GPSCoordinate;
import seng302.Model.ResizableRaceCanvas;
import seng302.Model.*;
import seng302.RaceMap;
import java.awt.geom.Point2D;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
@ -33,11 +28,17 @@ import java.util.ResourceBundle;
/**
* Created by fwy13 on 15/03/2017.
*/
public class RaceController extends Controller{
public class RaceController extends Controller {
ResizableRaceCanvas raceMap;
@FXML
AnchorPane canvasBase;
ResizableRaceCanvas raceMap;
@FXML
GridPane startScreen;
@FXML
SplitPane ongoingRacePane;
@FXML
Label timer;
@ -58,7 +59,8 @@ public class RaceController extends Controller{
TableColumn<BoatInRace, String> boatSpeedColumn;
/**
* updates the ResizableRaceCanvas (raceMap) with most recent data
* Updates the ResizableRaceCanvas (raceMap) with most recent data
*
* @param boats boats that are to be displayed in the race
* @see ResizableRaceCanvas
*/
@ -71,6 +73,7 @@ public class RaceController extends Controller{
/**
* Updates the array listened by the TableView (boatInfoTable) that displays the boat information.
*
* @param race Race to listen to.
*/
public void setInfoTable(Race race) {
@ -88,28 +91,62 @@ public class RaceController extends Controller{
});
}
/**
* Begins the race with a scale factor of 15
*/
public void startRace1Min() {
startRace(15);
}
/**
* Begins the race with a scale factor of 3
*/
public void startRace5Min() {
startRace(3);
}
/**
* Begins the race with a scale factor of 1
*/
public void startRaceNoScaling() {
startRace(1);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
BoatInRace[] boats = generateAC35Competitors();
}
/**
* Initializes and runs the race, based on the user's chosen scale factor
* Currently uses an example racecourse
*
* @param scaleFactor
*/
private void startRace(int scaleFactor) {
BoatInRace[] boats = generateAC35Competitors();
raceMap = new ResizableRaceCanvas();
raceMap.widthProperty().bind(canvasBase.widthProperty());
raceMap.heightProperty().bind(canvasBase.heightProperty());
raceMap.setBoats(boats);
raceMap.drawRaceMap();
raceMap.setVisible(true);
canvasBase.getChildren().add(raceMap);
startScreen.setVisible(false);
ongoingRacePane.setVisible(true);
ArrayList<Leg> legs = generateBermudaCourseLegs();
ConstantVelocityRace race = new ConstantVelocityRace(boats, legs, this);
ConstantVelocityRace race = new ConstantVelocityRace(boats, legs, this, scaleFactor);
new Thread((race)).start();
}
/**
* Function for the Bermuda Race.
* Generates an example race course (Bermuda 2017)
*
* @return legs in the Bermuda Race.
*/
private ArrayList<Leg> generateBermudaCourseLegs() {
@ -119,27 +156,32 @@ public class RaceController extends Controller{
Leg leg3 = new Leg("Leeward Gate to Windward Gate", Constants.leewardGate1, Constants.windwardGate1, 2);
Leg leg4 = new Leg("Windward Gate to Leeward Gate", Constants.windwardGate1, Constants.leewardGate1, 3);
Leg leg5 = new Leg("Leeward Gate to Finish", Constants.leewardGate1, Constants.finishLineMarker1, 4);
legs.add(leg1); legs.add(leg2); legs.add(leg3); legs.add(leg4); legs.add(leg5);
legs.add(leg1);
legs.add(leg2);
legs.add(leg3);
legs.add(leg4);
legs.add(leg5);
return legs;
}
/**
* Generates an example list of competitors (Official AC35 competitors)
* @return List of official AC35 competing boats
*/
private BoatInRace[] generateAC35Competitors() {
BoatInRace[] boats = new BoatInRace[6];
int i = 0;
for (BoatInRace boat : Constants.OFFICIAL_AC35_COMPETITORS) {
boat.setCurrentPosition(Constants.startLineMarker1);
boats[i] = boat;
i++;
}
return boats;
}
public void setTimer(String time){
public void setTimer(String time) {
timer.setText(time);
}

@ -11,13 +11,18 @@ public class GPSCoordinate {
/**
* Constructor Method
* @param latitude latitude the coordinate is located at.
*
* @param latitude latitude the coordinate is located at.
* @param longitude Longitude that the coordinate is located at.
*/
public GPSCoordinate(double latitude, double longitude) { this.latitude = latitude; this.longitude = longitude; }
public GPSCoordinate(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
/**
* Gets the Latitude that the Coordinate is at.
*
* @return Returns the latitude of the Coordinate.
*/
public double getLatitude() {
@ -26,12 +31,16 @@ public class GPSCoordinate {
/**
* Gets the Longitude that the Coordinate is at.
*
* @return Returns the longitude of the Coordinate.
*/
public double getLongitude() { return longitude; }
public double getLongitude() {
return longitude;
}
/**
* To String method of the Coordinate in the form Latitude: $f, Longitude: $f.
*
* @return A String representation of the GPSCoordinate Class.
*/
public String toString() {

@ -10,13 +10,18 @@ public class GraphCoordinate {
/**
* Constructor method.
*
* @param x X coordinate.
* @param y Y coordinate.
*/
public GraphCoordinate(int x, int y) { this.x = x; this.y = y; }
public GraphCoordinate(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Returns the X coordinate.
*
* @return x axis Coordinate.
*/
public int getX() {
@ -25,6 +30,7 @@ public class GraphCoordinate {
/**
* Returns the Y coordinate.
*
* @return y axis Coordinate.
*/
public int getY() {

@ -1,16 +1,13 @@
package seng302.Model;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import java.util.ArrayList;
/**
* Created by fwy13 on 3/03/17.
*/
public class Boat {
private StringProperty name;
private double velocity;
private StringProperty velocityProp;
@ -18,10 +15,11 @@ public class Boat {
/**
* Boat initialiser which keeps all of the information of the boat.
* @param name Name of the Boat.
*
* @param name Name of the Boat.
* @param velocity Speed in m/s that the boat travels at.
*/
public Boat(String name, double velocity, String abbrev){
public Boat(String name, double velocity, String abbrev) {
this.velocity = velocity;
this.velocityProp = new SimpleStringProperty(String.valueOf(velocity* 1.94384));
this.abbrev = abbrev;
@ -29,20 +27,22 @@ public class Boat {
}
/**
*
* @return The name of the boat
* @return Name of the boat
*/
public StringProperty getName() {
return name;
}
/**
* Sets the boat name
* @param name
*/
public void setName(String name) {
this.name.setValue(name);
}
/**
*
* @return returns the speed of the boat.
* @return Speed of the boat.
*/
public double getVelocity() {
return velocity;
@ -53,17 +53,25 @@ public class Boat {
}
/**
*
* @return The Name of the boat.
* Print method prints the name of the boat
* @return Name of the boat.
*/
public String toString(){
public String toString() {
return getName().toString();
}
/**
* @return Velocity String Property of the boat
*/
public StringProperty getVelocityProp() {
return velocityProp;
}
public String getAbbrev() { return abbrev; }
/**
* @return Abbreviation of the boat
*/
public String getAbbrev() {
return abbrev;
}
}

@ -8,7 +8,6 @@ import seng302.GPSCoordinate;
import java.awt.geom.Point2D;
/**
* Boat in the Race extends Boat.
* Created by esa46 on 15/03/17.
@ -16,6 +15,7 @@ import java.awt.geom.Point2D;
public class BoatInRace extends Boat {
private Leg currentLeg;
private double scaledVelocity;
private double distanceTravelledInLeg;
private GPSCoordinate currentPosition;
private long timeFinished;
@ -25,9 +25,10 @@ public class BoatInRace extends Boat {
/**
* Constructor method.
* @param name Name of the boat.
*
* @param name Name of the boat.
* @param velocity Speed that the boat travels.
* @param colour Colour the boat will be displayed as on the map
* @param colour Colour the boat will be displayed as on the map
*/
public BoatInRace(String name, double velocity, Color colour, String abbrev) {
super(name, velocity, abbrev);
@ -36,7 +37,72 @@ public class BoatInRace extends Boat {
}
/**
* Calculates the azimuth of the travel via map coordinates of the raceMarkers
*
* @return the direction that the boat is heading towards in degrees (-180 to 180).
*/
public double calculateAzimuth() {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(currentLeg.getStartGraphCoordinate().getLongitude(), currentLeg.getStartGraphCoordinate().getLatitude());
calc.setDestinationGeographicPoint(currentLeg.getEndGraphCoordinate().getLongitude(), currentLeg.getEndGraphCoordinate().getLatitude());
return calc.getAzimuth();
}
/**
* Converts an azimuth to a bearing
*
* @param azimuth azimuth value to be converted
* @return the bearings in degrees (0 to 360).
*/
public static double calculateHeading(double azimuth) {
if (azimuth >= 0) {
return azimuth;
} else {
return azimuth + 360;
}
}
/**
* Calculates the bearing of the travel via map coordinates of the raceMarkers
*
* @return the direction that the boat is heading towards in degrees (0 to 360).
*/
public double calculateHeading() {
double azimuth = this.calculateAzimuth();
return calculateHeading(azimuth);
}
public GPSCoordinate getWake() {
double reverseHeading = calculateHeading() - 180;
double distance = getVelocity();
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(
new Point2D.Double(getCurrentPosition().getLongitude(), getCurrentPosition().getLatitude())
);
calc.setDirection(reverseHeading, distance);
Point2D endpoint = calc.getDestinationGeographicPoint();
return new GPSCoordinate(endpoint.getY(), endpoint.getX());
}
/**
* @return Scaled velocity of the boat
*/
public double getScaledVelocity() {
return scaledVelocity;
}
/**
* Sets the boat's scaled velocity
* @param velocity
*/
public void setScaledVelocity(double velocity) {
this.scaledVelocity = velocity;
}
/**
* @return Returns the current position of the boat in a GPSCoordinate Class.
* @see GPSCoordinate
*/
@ -45,7 +111,16 @@ public class BoatInRace extends Boat {
}
/**
* Sets the current position on the GPS that the boat.
*
* @param position GPSCoordinate of the position that the boat is currently on.
* @see GPSCoordinate
*/
public void setCurrentPosition(GPSCoordinate position) {
this.currentPosition = position;
}
/**
* @return Returns the time that the boat finished the race.
*/
public long getTimeFinished() {
@ -53,7 +128,15 @@ public class BoatInRace extends Boat {
}
/**
* Sets the time that the boat finished the race.
*
* @param timeFinished Time the boat finished the race.
*/
public void setTimeFinished(long timeFinished) {
this.timeFinished = timeFinished;
}
/**
* @return Returns the colour of the boat.
*/
public Color getColour() {
@ -62,6 +145,7 @@ public class BoatInRace extends Boat {
/**
* Sets the colour that boat will be shown as when drawn on the ResizableRaceCanvas.
*
* @param colour Colour that the boat is to be set to.
* @see ResizableRaceCanvas
*/
@ -69,16 +153,9 @@ public class BoatInRace extends Boat {
this.colour = colour;
}
/**
* Sets the time that the boat finished the race.
* @param timeFinished Time the boat finished the race.
*/
public void setTimeFinished(long timeFinished) {
this.timeFinished = timeFinished;
}
/**
* Gets the current leg that the boat is on.
*
* @return returns the leg the boat is on in a Leg class
* @see Leg
*/
@ -87,7 +164,8 @@ public class BoatInRace extends Boat {
}
/**
* Sets the current Leg of that the boat is on.
* Sets the boat's current leg.
*
* @param currentLeg Leg class that the boat is currently on.
* @see Leg
*/
@ -96,89 +174,44 @@ public class BoatInRace extends Boat {
this.currentLegName.setValue(currentLeg.getName());
}
public StringProperty getCurrentLegName(){
/**
* @return Name of boat's current leg
*/
public StringProperty getCurrentLegName() {
return currentLegName;
}
/**
* Gets the distance travelled by the boat in the leg.
*
* @return Returns the value in nautical miles (1.852km) that the boat has traversed.
*/
public double getDistanceTravelledInLeg() {
return distanceTravelledInLeg;
}
/**
* Sets the current position on the GPS that the boat.
* @param position GPSCoordinate of the position that the boat is currently on.
* @see GPSCoordinate
*/
public void setCurrentPosition(GPSCoordinate position) {
this.currentPosition = position;
}
/**
* Sets the distance travelled by the boat in the leg in nautical miles (1.852km)
*
* @param distanceTravelledInLeg Distance travelled by the boat in nautical miles.
*/
public void setDistanceTravelledInLeg(double distanceTravelledInLeg) {
this.distanceTravelledInLeg = distanceTravelledInLeg;
}
public boolean isFinished() {
return this.finished;
}
public void setFinished(boolean bool) {
this.finished = bool;
}
/**
* Calculates the azimuth of the travel via map coordinates of the raceMarkers
* @return the direction that the boat is heading towards in degrees (-180 to 180).
* @return true if boat has finished, fals eif not
*/
public double calculateAzimuth(){
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(currentLeg.getStartGraphCoordinate().getLongitude(), currentLeg.getStartGraphCoordinate().getLatitude());
calc.setDestinationGeographicPoint(currentLeg.getEndGraphCoordinate().getLongitude(), currentLeg.getEndGraphCoordinate().getLatitude());
return calc.getAzimuth();
}
/**
* Converts an azimuth to a bearing
* @param azimuth azimuth value to be converted
* @return the bearings in degrees (0 to 360).
*/
public static double calculateHeading(double azimuth) {
if (azimuth >= 0) {
return azimuth;
}
else {
return azimuth + 360;
}
public boolean isFinished() {
return this.finished;
}
/**
* Calculates the bearing of the travel via map coordinates of the raceMarkers
* @return the direction that the boat is heading towards in degrees (0 to 360).
* Sets whether boat is finished or not
* @param bool
*/
public double calculateHeading(){
double azimuth = this.calculateAzimuth();
return calculateHeading(azimuth);
public void setFinished(boolean bool) {
this.finished = bool;
}
public GPSCoordinate getWake() {
double reverseHeading = calculateHeading() - 180;
double distance = getVelocity();
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(
new Point2D.Double(getCurrentPosition().getLongitude(), getCurrentPosition().getLatitude())
);
calc.setDirection(reverseHeading, distance);
Point2D endpoint = calc.getDestinationGeographicPoint();
return new GPSCoordinate(endpoint.getY(), endpoint.getX());
}
}

@ -1,12 +1,11 @@
package seng302.Model;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.Controllers.RaceController;
import java.awt.geom.Point2D;
import org.geotools.referencing.GeodeticCalculator;
import seng302.GPSCoordinate;
import java.awt.geom.Point2D;
import java.util.ArrayList;
/**
@ -15,54 +14,57 @@ import java.util.ArrayList;
public class ConstantVelocityRace extends Race {
/**
* Initialiser for a Race with constant velocity.
* @param startingBoats array of boats
* @param marks array of RaceMarkers that the boats need to pass in order to finish the course.
* @see Boat
* @see Leg
* Initialiser for a constant velocity race
*
* @param startingBoats
* @param legs
* @param controller
* @param scaleFactor
*/
public ConstantVelocityRace(BoatInRace[] startingBoats, ArrayList<Leg> marks, RaceController controller) {
super(startingBoats, marks, controller);
public ConstantVelocityRace(BoatInRace[] startingBoats, ArrayList<Leg> legs, RaceController controller, int scaleFactor) {
super(startingBoats, legs, controller, scaleFactor);
}
public ConstantVelocityRace(BoatInRace[] startingBoats, ArrayList<Leg> marks) {
super(startingBoats, marks);
}
/**
* Calculates the distance a boat has travelled and updates its current position according to this value.
* @param boat
* @param millisecondsElapsed
*/
protected void updatePosition(BoatInRace boat, int millisecondsElapsed) {
//distanceTravelled = velocity (nm p hr) * time taken to update loop
double distanceTravelled = boat.getVelocity() * millisecondsElapsed/3600000;
double distanceTravelled = boat.getScaledVelocity() * millisecondsElapsed / 3600000;
double totalDistanceTravelled = distanceTravelled + boat.getDistanceTravelledInLeg();
boolean finish = boat.getCurrentLeg().getName().equals("Finish");
if (!finish) {
//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
boat.setCurrentPosition(calculatePosition(boat.getCurrentLeg().getStartGraphCoordinate(),
totalDistanceTravelled, boat.calculateAzimuth()));
totalDistanceTravelled, boat.calculateAzimuth()));
}
}
/**
*
* @param oldCoordinates GPS coordinates of the boat's starting position
* Calculates the boats next GPS position based on its distance travelled and heading
* @param oldCoordinates GPS coordinates of the boat's starting position
* @param distanceTravelled distance in nautical miles
* @param azimuth boat's current direction. Value between -180 and 180
* @return
* @param azimuth boat's current direction. Value between -180 and 180
* @return The boat's new coordinate
*/
public static GPSCoordinate calculatePosition(GPSCoordinate oldCoordinates, double distanceTravelled, double azimuth) {
//Find new coordinate using current heading and distance
GeodeticCalculator geodeticCalculator = new GeodeticCalculator();
//Load start point into calculator
Point2D startPoint = new Point2D.Double(oldCoordinates.getLongitude(), oldCoordinates.getLatitude());
geodeticCalculator.setStartingGeographicPoint(startPoint);
geodeticCalculator.setDirection(azimuth,distanceTravelled * Constants.NMToMetersConversion);
//load direction and distance tranvelled into calculator
geodeticCalculator.setDirection(azimuth, distanceTravelled * Constants.NMToMetersConversion);
//get new point
Point2D endPoint = geodeticCalculator.getDestinationGeographicPoint();
return new GPSCoordinate(endPoint.getY(), endPoint.getX());

@ -1,10 +1,8 @@
package seng302.Model;
import org.geotools.referencing.Console;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.GPSCoordinate;
import seng302.GraphCoordinate;
/**
* Created by cbt24 on 6/03/17.
@ -20,9 +18,10 @@ public class Leg {
/**
* Leg Initialiser
*
* @param name Name of the Leg
*/
public Leg(String name, GPSCoordinate start, GPSCoordinate end, int number) {
public Leg(String name, GPSCoordinate start, GPSCoordinate end, int number) {
this.name = name;
this.startGPSCoordinate = start;
this.endGPSCoordinate = end;
@ -32,6 +31,7 @@ public class Leg {
/**
* Construction Method
*
* @param name Name of the Leg
*/
public Leg(String name, int number) {
@ -41,6 +41,7 @@ public class Leg {
/**
* Returns the name of the Leg
*
* @return Returns the name of the Leg
*/
public String getName() {
@ -49,6 +50,7 @@ public class Leg {
/**
* Get the distance in nautical miles
*
* @return Returns the total distance of the leg.
*/
public double getDistance() {
@ -57,6 +59,7 @@ public class Leg {
/**
* Returns the coordinates in GPSCoordinate class of the boats starting coordinate.
*
* @return Returns the coordinate of the start of the leg.
* @see GPSCoordinate
*/
@ -66,6 +69,7 @@ public class Leg {
/**
* Returns the coordinates in a GPSCoordinate class that the boat ends on.
*
* @return Returns the coordinate of the end of the leg.
* @see GPSCoordinate
*/
@ -75,6 +79,7 @@ public class Leg {
/**
* Returns the leg number that the leg exists in the Race
*
* @return Returns the Leg
* @see Race
*/
@ -84,11 +89,13 @@ public class Leg {
/**
* Calculates the distance that the legs are in nautical miles (1.852 km).
*
* @return Returns the leg distance.
*/
private double calculateDistance() {
GeodeticCalculator calc = new GeodeticCalculator();
//Load start and end of leg
calc.setStartingGeographicPoint(startGPSCoordinate.getLongitude(), startGPSCoordinate.getLatitude());
calc.setDestinationGeographicPoint(endGPSCoordinate.getLongitude(), endGPSCoordinate.getLatitude());
return calc.getOrthodromicDistance() / Constants.NMToMetersConversion;

@ -3,14 +3,11 @@ package seng302.Model;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableArray;
import javafx.collections.ObservableList;
import seng302.Controllers.RaceController;
import seng302.GPSCoordinate;
import java.util.*;
import java.util.ArrayList;
/**
* Parent class for races
@ -24,39 +21,62 @@ public abstract class Race implements Runnable {
protected int boatsFinished = 0;
protected long totalTimeElapsed;
protected int scaleFactor;
private int SLEEP_TIME = 100; //time in milliseconds to pause in a paced loop
protected int PRERACE_TIME = 10000;//Integer.MAX_VALUE; //time in milliseconds to pause during pre-race
protected int PRERACE_TIME = 100;//Integer.MAX_VALUE; //time in milliseconds to pause during pre-race
private boolean timerEnabled = true;
/**
* Initailiser for Race
*
* @param boats Takes in an array of boats that are participating in the race.
* @param legs Number of marks in order that the boats pass in order to complete the race.
* @param legs Number of marks in order that the boats pass in order to complete the race.
*/
public Race(BoatInRace[] boats, ArrayList<Leg> legs, RaceController controller) {
public Race(BoatInRace[] boats, ArrayList<Leg> legs, RaceController controller, int scaleFactor) {
if (boats.length > 0) {
for (BoatInRace boat : boats) {
if (boat != null) {
boat.setScaledVelocity(boat.getVelocity() * scaleFactor);
}
}
}
this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size()));
this.controller = controller;
this.scaleFactor = scaleFactor;
}
/**
* Constructor for Race class
*
* @param boats boats participating in the race.
* @param marks legs that there are in the race.
* @param legs legs that there are in the race.
*/
public Race(BoatInRace[] boats, ArrayList<Leg> marks) {
this(boats, marks, null);
public Race(BoatInRace[] boats, ArrayList<Leg> legs, int scaleFactor) {
if (boats.length > 0) {
for (BoatInRace boat : boats) {
if (boat != null) {
boat.setScaledVelocity(boat.getVelocity() * scaleFactor);
}
}
}
this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size()));
this.scaleFactor = scaleFactor;
}
/**
* Runnable for the thread.
*/
public void run() {
setControllerListeners();
preRace();
if(timerEnabled) countdownTimer();
if (timerEnabled) countdownTimer();
simulateRace();
}
@ -68,16 +88,13 @@ public abstract class Race implements Runnable {
}
/**
* Set up the state in waiting for the race starts.
* Initialises the boats,
* Sets the boats' current to the first leg in the race
*/
private void preRace() {
//show the boats participating.
System.out.println("Boats Participating:");
System.out.println("====================");
for (int i = 0; i < startingBoats.size(); i++) {
if (startingBoats.get(i) != null) {
System.out.println(i + 1 + ". " + startingBoats.get(i).toString() + ", Speed: "
+ Math.round(startingBoats.get(i).getVelocity() * 1.94384) + "kn");
startingBoats.get(i).setCurrentLeg(legs.get(0));
}
}
@ -98,13 +115,17 @@ public abstract class Race implements Runnable {
while (currentTime <= startTime) {
timeLeft = startTime - currentTime;
currentTimeInSeconds = timeLeft / 1000;
minutes = currentTimeInSeconds / 60;
remainingSeconds = currentTimeInSeconds % 60;
hours = minutes / 60;
minutes = minutes % 60;
if (controller != null) {
updateTime(String.format("Time until race starts: %02d:%02d:%02d", hours, minutes, remainingSeconds));
if (timeLeft == 0 && controller != null) {
updateTime("Race is starting...");
} else {
currentTimeInSeconds = timeLeft / 1000;
minutes = currentTimeInSeconds / 60;
remainingSeconds = currentTimeInSeconds % 60;
hours = minutes / 60;
minutes = minutes % 60;
if (controller != null) {
updateTime(String.format("Race clock: -%02d:%02d:%02d", hours, minutes, remainingSeconds));
}
}
try {
timeLoopEnded = System.currentTimeMillis();
@ -127,8 +148,9 @@ public abstract class Race implements Runnable {
long hours;
currentTimeInSeconds = totalTimeElapsed / 1000;
minutes = currentTimeInSeconds / 60;
remainingSeconds = currentTimeInSeconds % 60;
long scaledTimeInSeconds = currentTimeInSeconds * scaleFactor;
minutes = scaledTimeInSeconds / 60;
remainingSeconds = scaledTimeInSeconds % 60;
hours = minutes / 60;
minutes = minutes % 60;
return String.format("Race clock: %02d:%02d:%02d", hours, minutes, remainingSeconds);
@ -205,13 +227,13 @@ public abstract class Race implements Runnable {
/**
* Checks the position of the boat, this updates the boats current position.
* @param boat Boat that the postion is to be updated for.
*
* @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()){
// updateController();
if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()) {
//boat has passed onto new leg
if (boat.getCurrentLeg().getName().equals("Finish")) {
//boat has finished
@ -219,13 +241,16 @@ public abstract class Race implements Runnable {
boat.setFinished(true);
boat.setTimeFinished(timeElapsed);
} 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());
}
FXCollections.sort(startingBoats, (a,b) -> b.getCurrentLeg().getLegNumber() - a.getCurrentLeg().getLegNumber());
//Update the boat display table in the GUI to reflect the leg change
FXCollections.sort(startingBoats, (a, b) -> b.getCurrentLeg().getLegNumber() - a.getCurrentLeg().getLegNumber());
}
}
@ -233,11 +258,12 @@ public abstract class Race implements Runnable {
* Update call for the controller.
*/
protected void setControllerListeners() {
if(controller != null) controller.setInfoTable(this);
if (controller != null) controller.setInfoTable(this);
}
/**
* Returns the boats that have started the race.
*
* @return ObservableList of BoatInRace class that participated in the race.
* @see ObservableList
* @see BoatInRace
@ -246,12 +272,12 @@ public abstract class Race implements Runnable {
return startingBoats;
}
/**
* This function is a function that generates the Race and populates the events list.
* Is automatically called by the initialiser function, so that simulateRace() does not return an empty race.
* @see Race#simulateRace()
* Updates the boat's gps coordinates depending on time elapsed
* @param boat
* @param millisecondsElapsed
*/
protected abstract void updatePosition(BoatInRace boat, int millisecondsElapsed);
}

@ -28,6 +28,7 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Sets the boats that are to be displayed in this race.
*
* @param boats
*/
public void setBoats(BoatInRace[] boats) {
@ -45,22 +46,24 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Constructor
*/
public ResizableRaceCanvas(){
public ResizableRaceCanvas() {
this(null);
}
/**
* Sets the RaceMap that the RaceCanvas is to be displaying for.
*
* @param map
*/
public void setMap (RaceMap map) {
public void setMap(RaceMap map) {
this.map = map;
}
/**
* Displays the mark of a race as a circle.
*
* @param graphCoordinate Latitude and Logintude in GraphCoordinate that it is to be displayed as.
* @param paint Colour the mark is to be coloured.
* @param paint Colour the mark is to be coloured.
* @see GraphCoordinate
* @see Color
* @see Paint
@ -73,14 +76,15 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Displays a line on the map with rectangles on the starting and ending point of the line.
*
* @param graphCoordinateA Starting Point of the line in GraphCoordinate.
* @param graphCoordinateB End Point of the line in GraphCoordinate.
* @param paint Colour the line is to coloured.
* @param paint Colour the line is to coloured.
* @see GraphCoordinate
* @see Color
* @see Paint
*/
public void displayLine(GraphCoordinate graphCoordinateA, GraphCoordinate graphCoordinateB, Paint paint){
public void displayLine(GraphCoordinate graphCoordinateA, GraphCoordinate graphCoordinateB, Paint paint) {
gc.setStroke(paint);
gc.setFill(paint);
gc.fillOval(graphCoordinateA.getX() - 3, graphCoordinateA.getY() - 3, 6, 6);
@ -90,38 +94,41 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Display a point on the Canvas
*
* @param graphCoordinate Coordinate that the point is to be displayed at.
* @param paint Colour that the boat is to be coloured.
* @param paint Colour that the boat is to be coloured.
* @see GraphCoordinate
* @see Paint
* @see Color
*/
public void displayPoint(GraphCoordinate graphCoordinate, Paint paint){
public void displayPoint(GraphCoordinate graphCoordinate, Paint paint) {
gc.setFill(paint);
gc.fillOval(graphCoordinate.getX(), graphCoordinate.getY(), 10, 10);
}
/**
* Displays an arrow on the Canvas
*
* @param coordinate Coordinate that the arrow is to be displayed at.
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North (Up).
* @param angle Angle that the arrow is to be facing in degrees 0 degrees = North (Up).
* @see GraphCoordinate
*/
public void displayArrow(GraphCoordinate coordinate, int angle){
public void displayArrow(GraphCoordinate coordinate, int angle) {
gc.save();
rotate(angle, coordinate.getX(),coordinate.getY());
rotate(angle, coordinate.getX(), coordinate.getY());
gc.setFill(Color.BLACK);
gc.fillPolygon(new double[]{coordinate.getX()-12, coordinate.getX()-6, coordinate.getX(), coordinate.getX()-4, coordinate.getX()-4, coordinate.getX()-8, coordinate.getX()-8},
new double[]{coordinate.getY()-5, coordinate.getY()-20, coordinate.getY()-5, coordinate.getY()-5, coordinate.getY()+20, coordinate.getY()+20, coordinate.getY()-5},
gc.fillPolygon(new double[]{coordinate.getX() - 12, coordinate.getX() - 6, coordinate.getX(), coordinate.getX() - 4, coordinate.getX() - 4, coordinate.getX() - 8, coordinate.getX() - 8},
new double[]{coordinate.getY() - 5, coordinate.getY() - 20, coordinate.getY() - 5, coordinate.getY() - 5, coordinate.getY() + 20, coordinate.getY() + 20, coordinate.getY() - 5},
7);
gc.restore();
}
/**
* Rotates things on the canvas Note: this must be called in between gc.save() and gc.restore() else they will rotate everything
*
* @param angle Bearing angle to rotate at in degrees
* @param px Pivot point x of rotation.
* @param py Pivot point y of rotation.
* @param px Pivot point x of rotation.
* @param py Pivot point y of rotation.
*/
private void rotate(double angle, double px, double py) {
Rotate r = new Rotate(angle, px, py);
@ -130,8 +137,9 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Display given name and speed of boat at a graph coordinate
* @param name name of the boat
* @param speed speed of the boat
*
* @param name name of the boat
* @param speed speed of the boat
* @param coordinate coordinate the text appears
*/
public void displayText(String name, double speed, GraphCoordinate coordinate){
@ -158,9 +166,9 @@ public class ResizableRaceCanvas extends Canvas {
gc.clearRect(0, 0, width, height);
//System.out.println("Race Map Canvas Width: "+ width + ", Height:" + height);
this.map = new RaceMap(32.278, -64.863, 32.320989, -64.821, (int)width, (int)height);
this.map = new RaceMap(32.278, -64.863, 32.320989, -64.821, (int) width, (int) height);
if (map == null){
if (map == null) {
return;
}
@ -209,9 +217,23 @@ public class ResizableRaceCanvas extends Canvas {
}
}
}
/**
* Draws a boat at a certain GPSCoordinate
*
* @param colour Colour to colour boat.
* @param gpsCoordinates GPScoordinate that the boat is to be drawn at.
* @see GPSCoordinate
* @see Color
*/
public void drawBoat(Color colour, GPSCoordinate gpsCoordinates) {
GraphCoordinate graphCoordinate = this.map.convertGPS(gpsCoordinates);
//System.out.println("DrawingBoat" + gpsCoordinates.getLongitude());
displayPoint(graphCoordinate, colour);
}
/**
* Set the Canvas to resizable.
*
* @return That the Canvas is resizable.
*/
@Override
@ -221,6 +243,7 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Returns the preferred width of the Canvas
*
* @param width
* @return Returns the width of the Canvas
*/
@ -231,6 +254,7 @@ public class ResizableRaceCanvas extends Canvas {
/**
* Returns the preferred height of the Canvas
*
* @param height
* @return Returns the height of the Canvas
*/

@ -8,20 +8,27 @@ public class RaceMap {
private int width, height;
/**
* Contructor Method.
* @param x1 Longitude of the top left point.
* @param y1 Latitude of the top left point.
* @param x2 Longitude of the top right point.
* @param y2 Latitude of the top right point.
* @param width width that the Canvas the race is to be drawn on is.
* Constructor Method.
*
* @param x1 Longitude of the top left point.
* @param y1 Latitude of the top left point.
* @param x2 Longitude of the top right point.
* @param y2 Latitude of the top right point.
* @param width width that the Canvas the race is to be drawn on is.
* @param height height that the Canvas the race is to be drawn on is.
*/
public RaceMap(double y1, double x1, double y2, double x2, int height, int width) {
this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2; this.width = width; this.height = height;
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.width = width;
this.height = height;
}
/**
* Converts GPS coordinates to coordinates for container
*
* @param lat GPS latitude
* @param lon GPS longitude
* @return GraphCoordinate (pair of doubles)
@ -29,11 +36,12 @@ public class RaceMap {
*/
public GraphCoordinate convertGPS(double lat, double lon) {
return new GraphCoordinate((int) (width * (lon - x1) / (x2 - x1)), (int) (height - (height * (lat - y1) / (y2 - y1))));
return new GraphCoordinate((int) (width * (lon - x1) / (x2 - x1)), (int) (height - (height * (lat - y1) / (y2 - y1))));
}
/**
* Converts the GPS Coordinate to GraphCoordinates
*
* @param coordinate GPSCoordinate representation of Latitude and Longitude.
* @return GraphCoordinate that the GPS is coordinates are to be displayed on the map.
* @see GraphCoordinate

@ -87,10 +87,10 @@
<name>Windward Gate to Leeward Gate</name>
<start>
<coordinate>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
</coordinate>
</start>
<finish>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="mainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.Controllers.MainController" />
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:id="mainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.Controllers.MainController"/>

@ -1,33 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.canvas.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.Controllers.RaceController">
<children>
<SplitPane dividerPositions="0.75" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane fx:id="canvasBase">
<children>
<Label fx:id="timer" layoutX="45.0" layoutY="146.0" text="0:0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0" />
<Label fx:id="FPS" layoutX="-20.0" layoutY="153.0" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-0.0" />
</children></AnchorPane>
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" GridPane.columnIndex="1">
<children>
<TableView fx:id="boatInfoTable" prefHeight="400.0" prefWidth="146.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columns>
<TableColumn fx:id="boatPlacingColumn" prefWidth="50.0" text="Place" />
<TableColumn fx:id="boatTeamColumn" prefWidth="50.0" text="Team" />
<TableColumn fx:id="boatMarkColumn" prefWidth="50.0" text="Mark" />
<TableColumn fx:id="boatSpeedColumn" prefWidth="75.0" text="Speed" />
</columns>
</TableView>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
<?import javafx.scene.text.*?>
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.Controllers.RaceController">
<children>
<GridPane fx:id="startScreen" prefHeight="600.0" prefWidth="780.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="189.0" minWidth="10.0" prefWidth="93.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="372.0" minWidth="10.0" prefWidth="184.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="394.0" minWidth="10.0" prefWidth="192.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="416.0" minWidth="10.0" prefWidth="273.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="416.0" minWidth="10.0" prefWidth="57.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="241.0" minHeight="10.0" prefHeight="102.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="383.0" minHeight="10.0" prefHeight="227.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="369.0" minHeight="10.0" prefHeight="59.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="369.0" minHeight="10.0" prefHeight="38.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="178.0" minHeight="10.0" prefHeight="178.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Select Your Race Scaling:" GridPane.columnIndex="1"
GridPane.rowIndex="1">
<font>
<Font size="23.0"/>
</font>
</Text>
<Button mnemonicParsing="false" onAction="#startRace1Min" text="15x faster" GridPane.columnIndex="1"
GridPane.rowIndex="2"/>
<Button mnemonicParsing="false" onAction="#startRaceNoScaling" text="No scaling"
GridPane.columnIndex="3" GridPane.rowIndex="2"/>
<Button mnemonicParsing="false" onAction="#startRace5Min" text="3x faster" GridPane.columnIndex="2"
GridPane.rowIndex="2"/>
<Label alignment="CENTER" text="Race will take ~1 minute" GridPane.columnIndex="1"
GridPane.rowIndex="3">
<opaqueInsets>
<Insets/>
</opaqueInsets>
<font>
<Font size="10.0"/>
</font>
</Label>
<Label alignment="CENTER" layoutX="99.0" layoutY="407.0" text="Race will take ~5 minutes"
GridPane.columnIndex="2" GridPane.rowIndex="3">
<font>
<Font size="10.0"/>
</font>
<opaqueInsets>
<Insets/>
</opaqueInsets>
</Label>
<Label alignment="CENTER" layoutX="279.0" layoutY="407.0" text="Race will take ~15 minutes"
GridPane.columnIndex="3" GridPane.rowIndex="3">
<font>
<Font size="10.0"/>
</font>
<opaqueInsets>
<Insets/>
</opaqueInsets>
</Label>
</children>
</GridPane>
<SplitPane fx:id="ongoingRacePane" dividerPositions="0.70" visible="false" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane fx:id="canvasBase" prefHeight="581.0" prefWidth="537.0">
<children>
<Label fx:id="timer" layoutX="45.0" layoutY="146.0" text="0:0" AnchorPane.bottomAnchor="0.0"
AnchorPane.rightAnchor="0.0"/>
<Label fx:id="FPS" layoutX="-20.0" layoutY="153.0" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-0.0" />
</children>
</AnchorPane>
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0"
GridPane.columnIndex="1">
<children>
<TableView fx:id="boatInfoTable" layoutX="-2.0" prefHeight="600.0" prefWidth="264.0"
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-2.0"
AnchorPane.rightAnchor="-62.0" AnchorPane.topAnchor="0.0">
<columns>
<TableColumn fx:id="boatPlacingColumn" prefWidth="50.0" text="Place"/>
<TableColumn fx:id="boatTeamColumn" prefWidth="100.0" text="Team"/>
<TableColumn fx:id="boatMarkColumn" prefWidth="130.0" text="Mark"/>
<TableColumn fx:id="boatSpeedColumn" prefWidth="75.0" text="Speed"/>
</columns>
</TableView>
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>

@ -1,16 +0,0 @@
package seng302;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
/**
* Unit test for simple App.
*/
public class AppTest
{
@Test
public void testApp()
{
assertTrue( true );
}
}

@ -15,7 +15,6 @@ import static junit.framework.TestCase.assertTrue;
public class BoatInRaceTest {
@Test
public void calculateDueNorthAzimuthReturns0() {
BoatInRace boat = new BoatInRace("Test", 1, Color.ALICEBLUE, "tt");

@ -4,11 +4,9 @@ package seng302.Model;
import javafx.scene.paint.Color;
import org.geotools.referencing.GeodeticCalculator;
import org.junit.Test;
import org.opengis.geometry.coordinate.Geodesic;
import seng302.Constants;
import seng302.GPSCoordinate;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
@ -18,49 +16,49 @@ import static org.junit.Assert.assertEquals;
*/
public class ConstantVelocityRaceTest {
Leg START_LEG = new Leg("Start", new GPSCoordinate(0, 0), new GPSCoordinate(50, 50), 0);
int ONE_HOUR = 3600000; //1 hour in milliseconds
@Test
public void updatePositionChangesDistanceTravelled() {
BoatInRace boat = new BoatInRace("Test", 1, Color.ALICEBLUE, "tt");
Leg start = new Leg("Start", new GPSCoordinate(0, 0), new GPSCoordinate(50, 50), 0);
boat.setCurrentLeg(start);
boat.setCurrentLeg(START_LEG);
boat.setDistanceTravelledInLeg(0);
int timeElapsed = 3600000; //1 hr
BoatInRace[] boats = new BoatInRace[]{boat};
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>());
ConstantVelocityRace race = new ConstantVelocityRace(boats, new ArrayList<Leg>(), null, 1);
race.updatePosition(boat, timeElapsed);
assertEquals(boat.getDistanceTravelledInLeg(), boat.getVelocity() * timeElapsed / 3600000, 1e-8);
race.updatePosition(boat, ONE_HOUR);
assertEquals(boat.getDistanceTravelledInLeg(), boat.getVelocity(), 1e-8);
}
@Test
public void updatePositionHandlesNoChangeToDistanceTravelled() {
BoatInRace boat = new BoatInRace("Test", 0, Color.ALICEBLUE, "tt");
Leg start = new Leg("Start", new GPSCoordinate(0, 0), new GPSCoordinate(50, 50), 0);
boat.setCurrentLeg(start);
boat.setCurrentLeg(START_LEG);
boat.setDistanceTravelledInLeg(0);
int timeElapsed = 3600000; //1 hr
BoatInRace[] boats = new BoatInRace[]{boat};
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>());
ConstantVelocityRace race = new ConstantVelocityRace(boats, new ArrayList<Leg>(), null, 1);
race.updatePosition(boat, timeElapsed);
race.updatePosition(boat, ONE_HOUR);
assertEquals(boat.getDistanceTravelledInLeg(), 0, 1e-8);
}
@Test
public void changesToDistanceTravelledAreAdditive() {
BoatInRace boat = new BoatInRace("Test", 5, Color.ALICEBLUE, "tt");
Leg start = new Leg("Start", new GPSCoordinate(0, 0), new GPSCoordinate(50, 50), 0);
boat.setCurrentLeg(start);
boat.setCurrentLeg(START_LEG);
boat.setDistanceTravelledInLeg(50);
int timeElapsed = 3600000; //1 hr
BoatInRace[] boats = new BoatInRace[]{boat};
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>());
ConstantVelocityRace race = new ConstantVelocityRace(boats, new ArrayList<Leg>(), null, 1);
race.updatePosition(boat, timeElapsed);
assertEquals(boat.getDistanceTravelledInLeg(), boat.getVelocity() * timeElapsed / 3600000 + 50, 1e-8);
race.updatePosition(boat, ONE_HOUR);
assertEquals(boat.getDistanceTravelledInLeg(), boat.getVelocity() + 50, 1e-8);
}
@Test
@ -72,7 +70,6 @@ public class ConstantVelocityRaceTest {
calc.setStartingGeographicPoint(0, 0);
calc.setDirection(0, 10 * Constants.NMToMetersConversion);
assertEquals(newPos.getLongitude(), 0, 1e-8);
assertEquals(newPos.getLatitude(), calc.getDestinationGeographicPoint().getY(), 1e-8);
assertEquals(newPos.getLongitude(), calc.getDestinationGeographicPoint().getX(), 1e-8);

@ -20,7 +20,7 @@ public class LegTest {
GPSCoordinate startPoint = new GPSCoordinate(0, 0);
GPSCoordinate endPoint = new GPSCoordinate(calc.getDestinationGeographicPoint().getY(), calc.getDestinationGeographicPoint().getX());
Leg test= new Leg("Test", startPoint, endPoint, 0);
Leg test = new Leg("Test", startPoint, endPoint, 0);
assertEquals(test.getDistance(), 5, 1e-8);
}
@ -32,7 +32,7 @@ public class LegTest {
GPSCoordinate startPoint = new GPSCoordinate(0, 0);
GPSCoordinate endPoint = new GPSCoordinate(calc.getDestinationGeographicPoint().getY(), calc.getDestinationGeographicPoint().getX());
Leg test= new Leg("Test", startPoint, endPoint, 0);
Leg test = new Leg("Test", startPoint, endPoint, 0);
assertEquals(test.getDistance(), 12, 1e-8);
}
@ -44,7 +44,7 @@ public class LegTest {
GPSCoordinate startPoint = new GPSCoordinate(0, 0);
GPSCoordinate endPoint = new GPSCoordinate(calc.getDestinationGeographicPoint().getY(), calc.getDestinationGeographicPoint().getX());
Leg test= new Leg("Test", startPoint, endPoint, 0);
Leg test = new Leg("Test", startPoint, endPoint, 0);
assertEquals(test.getDistance(), 0.5, 1e-8);
}
@ -56,7 +56,7 @@ public class LegTest {
GPSCoordinate startPoint = new GPSCoordinate(0, 0);
GPSCoordinate endPoint = new GPSCoordinate(calc.getDestinationGeographicPoint().getY(), calc.getDestinationGeographicPoint().getX());
Leg test= new Leg("Test", startPoint, endPoint, 0);
Leg test = new Leg("Test", startPoint, endPoint, 0);
assertEquals(test.getDistance(), 0.1, 1e-8);
}
@ -64,7 +64,7 @@ public class LegTest {
public void calculateDistanceHandlesZeroDifference() {
GPSCoordinate startPoint = new GPSCoordinate(0, 0);
GPSCoordinate endPoint = new GPSCoordinate(0, 0);
Leg test= new Leg("Test", startPoint, endPoint, 0);
Leg test = new Leg("Test", startPoint, endPoint, 0);
assertEquals(test.getDistance(), 0, 1e-8);
}

@ -1,18 +1,11 @@
package seng302.Model;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;
import org.junit.Ignore;
import org.junit.Test;
import seng302.GPSCoordinate;
import seng302.Model.BoatInRace;
import seng302.Model.ConstantVelocityRace;
import seng302.Model.Leg;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Observable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -30,16 +23,16 @@ public class RaceTest {
new BoatInRace("AU", 2800, Color.BEIGE, "AU")
};
ArrayList<Leg> legs = new ArrayList<>();
legs.add(new Leg("Start", new GPSCoordinate(32.296577, -64.854304),new GPSCoordinate(32.293039, -64.843983),0));
legs.add(new Leg("Start", new GPSCoordinate(32.293039, -64.843983),new GPSCoordinate(32.284680, -64.850045),1));
Race race = new ConstantVelocityRace(boats, legs);
legs.add(new Leg("Start", new GPSCoordinate(32.296577, -64.854304), new GPSCoordinate(32.293039, -64.843983), 0));
legs.add(new Leg("Start", new GPSCoordinate(32.293039, -64.843983), new GPSCoordinate(32.284680, -64.850045), 1));
Race race = new ConstantVelocityRace(boats, legs, null, 1);
race.disableTimer();
// Boats should finish in an order determined by their velocity
Arrays.sort(boats, (a,b) -> (int)(b.getVelocity()-a.getVelocity()));
Arrays.sort(boats, (a, b) -> (int) (b.getVelocity() - a.getVelocity()));
race.run();
for(int i = 0; i < boats.length; i++)
for (int i = 0; i < boats.length; i++)
assertTrue(boats[i].equals(race.getStartingBoats().get(i)));
}
@ -52,7 +45,7 @@ public class RaceTest {
Leg leg = new Leg("Finish", new GPSCoordinate(0, 0), new GPSCoordinate(1, 1), 0);
finishedBoat.setCurrentLeg(leg);
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>());
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>(), null, 1);
assertEquals(race.boatsFinished, 0);
race.checkPosition(finishedBoat, 100);
@ -68,7 +61,7 @@ public class RaceTest {
Leg leg = new Leg("Finish", new GPSCoordinate(0, 0), new GPSCoordinate(1, 1), 0);
unFinishedBoat.setCurrentLeg(leg);
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>());
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<Leg>(), null, 1);
assertEquals(race.boatsFinished, 0);
race.checkPosition(unFinishedBoat, 100);
@ -84,9 +77,10 @@ public class RaceTest {
Leg leg1 = new Leg("1", new GPSCoordinate(0, 0), new GPSCoordinate(1, 1), 0);
Leg leg2 = new Leg("2", new GPSCoordinate(0, 0), new GPSCoordinate(1, 1), 1);
legs.add(leg2); legs.add(leg2);
legs.add(leg2);
legs.add(leg2);
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], legs);
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], legs, null, 1);
BoatInRace unFinishedBoat = new BoatInRace("Test", 10, Color.ALICEBLUE, "tt");
unFinishedBoat.setDistanceTravelledInLeg(100);
@ -101,7 +95,7 @@ public class RaceTest {
@Test
public void timerDelaysByHalfSecond() {
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<>());
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[1], new ArrayList<>(), null, 1);
race.PRERACE_TIME = 500;
long timeStarted = System.currentTimeMillis();
@ -110,4 +104,42 @@ public class RaceTest {
assertTrue(System.currentTimeMillis() - timeStarted > 500);
}
@Test
public void scalerScalesVelocityCorrectly() {
int scaleFactor = 3;
float vel1 = 0;
float vel2 = (float) 1.999;
float vel3 = (float) 32.5;
float vel4 = 500;
BoatInRace boat1 = new BoatInRace("test", vel1, Color.ALICEBLUE, "tt");
BoatInRace boat2 = new BoatInRace("test", vel2, Color.ALICEBLUE, "tt");
BoatInRace boat3 = new BoatInRace("test", vel3, Color.ALICEBLUE, "tt");
BoatInRace boat4 = new BoatInRace("test", vel4, Color.ALICEBLUE, "tt");
BoatInRace[] boats = new BoatInRace[]{boat1, boat2, boat3, boat4};
ConstantVelocityRace race = new ConstantVelocityRace(boats, new ArrayList<Leg>(), null, scaleFactor);
assertEquals(race.getStartingBoats().get(0).getScaledVelocity(), vel1 * scaleFactor, 1e-6);
assertEquals(race.getStartingBoats().get(1).getScaledVelocity(), vel2 * scaleFactor, 1e-6);
assertEquals(race.getStartingBoats().get(2).getScaledVelocity(), vel3 * scaleFactor, 1e-6);
assertEquals(race.getStartingBoats().get(3).getScaledVelocity(), vel4 * scaleFactor, 1e-6);
}
@Test
public void scalerScalesRaceClockTo1MinCorrectly() {
int scaleFactor = 10;
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[5], new ArrayList<Leg>(), null, scaleFactor);
race.totalTimeElapsed = 6000; //6 seconds
assertTrue(race.calcTimer().equals("Race clock: 00:01:00"));
}
@Test
public void scalerScalesRaceClockHoursMinutesAndSecondsCorrectly() {
int scaleFactor = 3;
ConstantVelocityRace race = new ConstantVelocityRace(new BoatInRace[5], new ArrayList<Leg>(), null, scaleFactor);
race.totalTimeElapsed = 3213000;
assertTrue(race.calcTimer().equals("Race clock: 02:40:39"));
}
}

Loading…
Cancel
Save