Merge branch 'master' into submission

# Conflicts:
#	mock/src/main/java/seng302/Model/Race.java
#	mock/src/test/java/seng302/Model/RaceTest.java
#	visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java
This commit is contained in:
Joseph Gardner
2017-05-15 16:08:46 +12:00
71 changed files with 1931 additions and 3915 deletions
@@ -1,34 +0,0 @@
package seng302;
import javafx.scene.paint.Color;
import seng302.Model.BoatInRace;
/**
* Constants that are used throughout the program
* Created by Erika on 19-Mar-17.
* @deprecated please use XML for constant data
*/
public class Constants {
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);
public static final GPSCoordinate leewardGate2 = new GPSCoordinate(32.308046, -64.831785);
public static final GPSCoordinate finishLineMarker1 = new GPSCoordinate(32.317379, -64.839291);
public static final GPSCoordinate finishLineMarker2 = new GPSCoordinate(32.317257, -64.836260);
public static final double wakeScale = 10;
public static final BoatInRace[] OFFICIAL_AC35_COMPETITORS = new BoatInRace[]
{new BoatInRace("Oracle Team USA", 30.0, Color.BLUEVIOLET, "Oracle"),
new BoatInRace("Land Rover BAR", 23.0, Color.BLACK, "BGR"),
new BoatInRace("SoftBank Team Japan", 27.0, Color.RED, "JPN"),
new BoatInRace("Groupama Team France", 25.0, Color.ORANGE, "FRA"),
new BoatInRace("Artemis Racing", 22.5, Color.DARKOLIVEGREEN, "SWE"),
new BoatInRace("Emirates Team New Zealand", 62, Color.LIMEGREEN, "ETNZ")};
}
@@ -57,10 +57,12 @@ public class RaceController extends Controller {
* Updates the ResizableRaceCanvas (raceMap) with most recent data
*
* @param boats boats that are to be displayed in the race
* @param boatMarkers Markers for boats
* @see ResizableRaceCanvas
*/
public void updateMap(ObservableList<Boat> boats) {
public void updateMap(ObservableList<Boat> boats, ObservableList<Marker> boatMarkers) {
raceMap.setBoats(boats);
raceMap.setBoatMarkers(boatMarkers);
raceMap.update();
raceBoundaries.draw();
//stop if the visualiser is no longer running
@@ -71,7 +73,7 @@ public class RaceController extends Controller {
*
* @param race Race to listen to.
*/
public void setInfoTable(Race race) {
public void setInfoTable(StreamedRace race) {
//boatInfoTable.getItems().clear();
ObservableList<Boat> startingBoats = race.getStartingBoats();
boatInfoTable.setItems(race.getStartingBoats());
@@ -19,7 +19,6 @@ import seng302.VisualiserInput;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Observable;
@@ -43,8 +42,6 @@ public class StartController extends Controller implements Observer {
@FXML private Label timer;
@FXML private Label raceStatusLabel;
private ZonedDateTime startingTime;
//@FXML Button fifteenMinButton;
private RaceClock raceClock;
@@ -61,17 +58,11 @@ public class StartController extends Controller implements Observer {
* Begins the race with a scale factor of 1
*/
private void startRaceNoScaling() {
//startRace(1);
while(visualiserInput.getRaceStatus() == null);//TODO probably remove this.
countdownTimer();
}
private void startRace(int raceScale){
//fifteenMinButton.setDisable(true);
//countdownTimer(raceScale);
}
@Override
public void initialize(URL location, ResourceBundle resources){
raceData = new StreamedCourse();
@@ -88,7 +88,7 @@ public class BoatXMLReader extends XMLReader {
Element nBoats = (Element) doc.getElementsByTagName("Boats").item(0);
for (int i = 0; i < nBoats.getChildNodes().getLength(); i++) {
Node boat = nBoats.getChildNodes().item(i);
if (boat.getNodeName().equals("Boat")) {
if (boat.getNodeName().equals("Boat") && boat.getAttributes().getNamedItem("Type").getTextContent().equals("Yacht")) {
readSingleBoat(boat);
}
}
@@ -1,106 +0,0 @@
package seng302.Mock;
import seng302.GPSCoordinate;
/**
* Created by jjg64 on 19/04/17.
* @deprecated use the RegattaXMLReader
*/
public class Regatta {
private int regattaID;
private String RegattaName;
private int raceID = 0;
private String courseName;
private double centralLatitude;
private double centralLongitude;
private double centralAltitude;
private float utcOffset;
private float magneticVariation;
public Regatta(int regattaID, String regattaName, String courseName, double centralLatitude, double centralLongitude, double centralAltitude, float utcOffset, float magneticVariation) {
this.regattaID = regattaID;
this.RegattaName = regattaName;
this.courseName = courseName;
this.centralLatitude = centralLatitude;
this.centralLongitude = centralLongitude;
this.centralAltitude = centralAltitude;
this.utcOffset = utcOffset;
this.magneticVariation = magneticVariation;
}
public int getRegattaID() {
return regattaID;
}
public void setRegattaID(int ID) {
this.regattaID = ID;
}
public String getRegattaName() {
return RegattaName;
}
public void setRegattaName(String regattaName) {
RegattaName = regattaName;
}
public int getRaceID() {
return raceID;
}
public void setRaceID(int raceID) {
this.raceID = raceID;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public double getCentralLatitude() {
return centralLatitude;
}
public void setCentralLatitude(double centralLatitude) {
this.centralLatitude = centralLatitude;
}
public double getCentralLongitude() {
return centralLongitude;
}
public void setCentralLongitude(double centralLongitude) {
this.centralLongitude = centralLongitude;
}
public double getCentralAltitude() {
return centralAltitude;
}
public void setCentralAltitude(double centralAltitude) {
this.centralAltitude = centralAltitude;
}
public float getUtcOffset() {
return utcOffset;
}
public void setUtcOffset(float utcOffset) {
this.utcOffset = utcOffset;
}
public float getMagneticVariation() {
return magneticVariation;
}
public void setMagneticVariation(float magneticVariation) {
this.magneticVariation = magneticVariation;
}
public GPSCoordinate getGPSCoordinate() {
return new GPSCoordinate(centralLatitude, centralLongitude);
}
}
@@ -14,7 +14,6 @@ import java.io.InputStream;
* Created by jjg64 on 19/04/17.
*/
public class RegattaXMLReader extends XMLReader {
private Regatta regatta;
private int regattaID;
private String regattaName;
private int raceID = 0;
@@ -78,10 +77,6 @@ public class RegattaXMLReader extends XMLReader {
this.magneticVariation = Float.parseFloat(getTextValueOfNode(attributes, "MagneticVariation"));
}
public Regatta getRegatta() {
return regatta;
}
public int getRegattaID() {
return regattaID;
}
@@ -29,18 +29,4 @@ public class StreamedBoat extends Boat {
return sourceID;
}
/**
* Calculates the azimuth of the travel via heading of the boat
*
* @return the direction that the boat is heading towards in degrees (-180 to 180).
*/
public double calculateAzimuth() {
double azimuth;
if (heading <= 180) {
azimuth = heading;
} else {
azimuth = -heading + 180;
}
return azimuth;
}
}
@@ -21,14 +21,6 @@ public class StreamedCourse extends Observable implements RaceDataSource {
public StreamedCourse() {}
public StreamedCourse(StreamedCourseXMLReader streamedCourseXMLReader) {
this.streamedCourseXMLReader = streamedCourseXMLReader;
}
public StreamedCourse(BoatXMLReader boatXMLReader) {
this.boatXMLReader = boatXMLReader;
}
public void setBoatXMLReader(BoatXMLReader boatXMLReader) {
this.boatXMLReader = boatXMLReader;
if (streamedCourseXMLReader != null && boatXMLReader != null) {
@@ -13,7 +13,6 @@ import seng302.XMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
@@ -35,19 +34,6 @@ public class StreamedCourseXMLReader extends XMLReader {
private String raceType;
private boolean postpone;
/**
* Constructor for Streamed Race XML
* @param filePath path of the file
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/
public StreamedCourseXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
this(filePath, true);
}
/**
* Constructor for Streamed Race XML
* @param filePath file path to read
@@ -55,10 +41,9 @@ public class StreamedCourseXMLReader extends XMLReader {
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/
public StreamedCourseXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
public StreamedCourseXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException, StreamedCourseXMLException {
super(filePath);
if (read) {
read();
@@ -71,10 +56,9 @@ public class StreamedCourseXMLReader extends XMLReader {
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/
public StreamedCourseXMLReader(InputStream xmlString) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
public StreamedCourseXMLReader(InputStream xmlString) throws IOException, SAXException, ParserConfigurationException, StreamedCourseXMLException {
super(xmlString);
read();
}
@@ -165,8 +149,9 @@ public class StreamedCourseXMLReader extends XMLReader {
Marker marker;
switch(nMarks.getLength()) {
case 1: marker = new Marker(getCoordinate((Element)nMarks.item(0))); break;
case 2: marker = new Marker(getCoordinate((Element)nMarks.item(0)), getCoordinate((Element)nMarks.item(1))); break;
case 1: marker = new Marker(getCoordinate((Element)nMarks.item(0)),getSourceId((Element)nMarks.item(0))); break;
case 2: marker = new Marker(getCoordinate((Element)nMarks.item(0)), getCoordinate((Element)nMarks.item(1)),
getSourceId((Element)nMarks.item(0)), getSourceId((Element)nMarks.item(1))); break;
default: throw new StreamedCourseXMLException();
}
@@ -179,6 +164,14 @@ public class StreamedCourseXMLReader extends XMLReader {
return new GPSCoordinate(lat,lon);
}
private int getSourceId(Element mark) {
String sourceId = mark.getAttribute("SourceID");
if (sourceId.isEmpty()){
return 0;
}
return Integer.parseInt(sourceId);
}
/**
* Reads "compoundMarkID" attribute of CompoundMark or Corner element
* @param element with "compoundMarkID" attribute
@@ -259,10 +252,6 @@ public class StreamedCourseXMLReader extends XMLReader {
return COORDINATEPADDING;
}
public ZonedDateTime getCreationTimeDate() {
return creationTimeDate;
}
public ZonedDateTime getRaceStartTime() {
return raceStartTime;
}
@@ -1,37 +1,60 @@
package seng302.Mock;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seng302.Controllers.FinishController;
import seng302.Controllers.RaceController;
import seng302.GPSCoordinate;
import seng302.Model.Boat;
import seng302.Model.Leg;
import seng302.Model.Marker;
import seng302.Model.Race;
import seng302.Networking.Messages.BoatLocation;
import seng302.Networking.Messages.BoatStatus;
import seng302.Networking.Messages.Enums.BoatStatusEnum;
import seng302.VisualiserInput;
import java.util.List;
/**
* Created by jjg64 on 21/04/17.
*/
public class StreamedRace extends Race {
public class StreamedRace implements Runnable {
private final VisualiserInput visualiserInput;
private final ObservableList<Boat> startingBoats;
private final ObservableList<Marker> boatMarkers;
private final List<Leg> legs;
private RaceController controller;
protected FinishController finishController;
private int boatsFinished = 0;
private long totalTimeElapsed;
private int lastFPS = 20;
public StreamedRace(VisualiserInput visualiserInput, RaceController controller) {
super(visualiserInput.getCourse(), controller, 1);
StreamedCourse course = visualiserInput.getCourse();
this.startingBoats = FXCollections.observableArrayList(course.getBoats());
this.boatMarkers = FXCollections.observableArrayList(course.getMarkers());
this.legs = course.getLegs();
this.legs.add(new Leg("Finish", this.legs.size()));
this.controller = controller;
if (startingBoats != null && startingBoats.size() > 0) {
initialiseBoats();
}
this.visualiserInput = visualiserInput;
}
public void initialiseBoats() {
private void initialiseBoats() {
Leg officialStart = legs.get(0);
String name = officialStart.getName();
Marker endMarker = officialStart.getEndMarker();
Marker endCompoundMark = officialStart.getEndMarker();
for (int i = 0; i < startingBoats.size(); i++) {
Boat boat = startingBoats.get(i);
for (Boat boat : startingBoats) {
if (boat != null) {
Leg startLeg = new Leg(name, 0);
startLeg.setEndMarker(endMarker);
startLeg.setEndMarker(endCompoundMark);
boat.setCurrentLeg(startLeg);
}
}
@@ -52,7 +75,7 @@ public class StreamedRace extends Race {
* @param boat Boat that the position is to be updated for.
* @param timeElapsed Time that has elapse since the start of the the race.
*/
protected void checkPosition(Boat boat, long timeElapsed) {
private void checkPosition(Boat boat, long timeElapsed) {
StreamedCourse raceData = visualiserInput.getCourse();
BoatStatus boatStatusMessage = visualiserInput.getBoatStatusMap().get(boat.getSourceID());
if (boatStatusMessage != null) {
@@ -72,7 +95,7 @@ public class StreamedRace extends Race {
boatsFinished++;
boat.setTimeFinished(timeElapsed);
boat.setFinished(true);
System.out.println("Boat finished");
//System.out.println("Boat finished");
}
}
//Update the boat display table in the GUI to reflect the leg change
@@ -85,7 +108,7 @@ public class StreamedRace extends Race {
* @param boat to be updated
* @param millisecondsElapsed time since last update
*/
protected void updatePosition(Boat boat, int millisecondsElapsed) {
private void updatePosition(Boat boat, int millisecondsElapsed) {
int sourceID = boat.getSourceID();
BoatLocation boatLocation = visualiserInput.getBoatLocationMessage(sourceID);
if(boatLocation != null) {
@@ -99,12 +122,136 @@ public class StreamedRace extends Race {
}
/**
* sets the position of a boat from coordinate
* @param boat the boat to set
* @param coordinate the position of the boat
* Updates the boat's gps coordinates
*
* @param mark to be updated
*/
protected void setPosition(Boat boat, GPSCoordinate coordinate) {
boat.setCurrentPosition(coordinate);
private void updateMarker(Marker mark) {
int sourceID = mark.getSourceId1();
BoatLocation boatLocation1 = visualiserInput.getBoatLocationMessage(sourceID);
if(boatLocation1 != null) {
double lat = boatLocation1.getLatitudeDouble();
double lon = boatLocation1.getLongitudeDouble();
mark.setCurrentPosition1(new GPSCoordinate(lat, lon));
}
int sourceID2 = mark.getSourceId2();
BoatLocation boatLocation2 = visualiserInput.getBoatLocationMessage(sourceID2);
if(boatLocation2 != null) {
double lat = boatLocation2.getLatitudeDouble();
double lon = boatLocation2.getLongitudeDouble();
mark.setCurrentPosition2(new GPSCoordinate(lat, lon));
}
}
public void setController(RaceController controller) {
this.controller = controller;
}
/**
* Runnable for the thread.
*/
public void run() {
setControllerListeners();
initialiseBoats();
startRaceStream();
}
/**
* Update the calculated fps to the fps label
*
* @param fps The new calculated fps value
*/
private void updateFPS(int fps) {
Platform.runLater(() -> controller.setFrames("FPS: " + fps));
}
/**
* 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.
*/
private void startRaceStream() {
System.setProperty("javafx.animation.fullspeed", "true");
for (Boat boat : startingBoats) {
boat.setStarted(true);
}
new AnimationTimer() {
final long timeRaceStarted = System.currentTimeMillis(); //start time of loop
int fps = 0; //init fps value
long timeCurrent = System.currentTimeMillis(); //current time
@Override
public void handle(long arg0) {
if (boatsFinished < startingBoats.size()) {
boatsFinished = 0;
totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted;
for (Boat boat : startingBoats) {
if (boat != null && !boat.isFinished()) {
updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS));
checkPosition(boat, totalTimeElapsed);
}
if (boat.isFinished()){
boatsFinished++;
}
}
for (Marker mark: boatMarkers){
if (mark != null){
updateMarker(mark);
}
}
//System.out.println(boatsFinished + ":" + startingBoats.size());
} else {
controller.finishRace(startingBoats);
stop();
}
controller.updateMap(startingBoats, boatMarkers);
fps++;
if ((System.currentTimeMillis() - timeCurrent) > 1000) {
updateFPS(fps);
lastFPS = fps;
fps = 0;
timeCurrent = System.currentTimeMillis();
}
}
}.start();
}
/**
* Update position of boats in race, no position if on starting leg or DNF.
*/
private void updatePositions() {
FXCollections.sort(startingBoats, (a, b) -> b.getCurrentLeg().getLegNumber() - a.getCurrentLeg().getLegNumber());
for(Boat boat: startingBoats) {
if(boat != null) {
boat.setPosition(Integer.toString(startingBoats.indexOf(boat) + 1));
if (boat.isDnf() || !boat.isStarted() || boat.getCurrentLeg().getLegNumber() < 0)
boat.setPosition("-");
}
}
}
/**
* Update call for the controller.
*/
private void setControllerListeners() {
if (controller != null) controller.setInfoTable(this);
}
/**
* Returns the boats that have started the race.
*
* @return ObservableList of Boat class that participated in the race.
* @see ObservableList
* @see Boat
*/
public ObservableList<Boat> getStartingBoats() {
return startingBoats;
}
}
@@ -4,7 +4,6 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.paint.Color;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.GPSCoordinate;
import java.awt.geom.Point2D;
@@ -28,6 +27,7 @@ public class BoatInRace extends Boat {
private boolean started = false;
private final StringProperty position;
private double heading;
private static final double WAKE_SCALE = 10;
private final Queue<TrackPoint> track = new ConcurrentLinkedQueue<>();
private long nextValidTime = 0;
@@ -50,20 +50,6 @@ public class BoatInRace extends Boat {
position = new SimpleStringProperty("-");
}
/**
* Constructor method.
*
* @param name Name of the boat.
* @param colour Colour the boat will be displayed as on the map
* @param abbrev of boat
*/
public BoatInRace(String name, Color colour, String abbrev) {
super(name, abbrev);
setColour(colour);
currentLegName = new SimpleStringProperty("");
position = new SimpleStringProperty("-");
}
/**
* Calculates the azimuth of the travel via map coordinates of the raceMarkers
*
@@ -122,7 +108,7 @@ public class BoatInRace extends Boat {
*/
public GPSCoordinate getWake() {
double reverseHeading = getHeading() - 180;
double distance = Constants.wakeScale * getVelocity();
double distance = WAKE_SCALE * getVelocity();
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(
@@ -60,19 +60,19 @@
// public void initialiseBoats() {
// Leg officialStart = legs.get(0);
// String name = officialStart.getName();
// Marker endMarker = officialStart.getEndMarker();
// CompoundMark endMarker = officialStart.getEndCompoundMark();
//
// BoatInRace.setTrackPointTimeInterval(BoatInRace.getBaseTrackPointTimeInterval() / scaleFactor);
//
// ArrayList<Marker> startMarkers = getSpreadStartingPositions();
// ArrayList<CompoundMark> 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.setStartCompoundMark(startMarkers.get(i));
// startLeg.setEndCompoundMark(endMarker);
// startLeg.calculateDistance();
// boat.setCurrentLeg(startLeg);
// boat.setHeading(boat.calculateHeading());
@@ -85,10 +85,10 @@
// *
// * @return list of starting positions
// */
// public ArrayList<Marker> getSpreadStartingPositions() {
// public ArrayList<CompoundMark> getSpreadStartingPositions() {
//
// int nBoats = startingBoats.size();
// Marker marker = legs.get(0).getStartMarker();
// CompoundMark marker = legs.get(0).getStartCompoundMark();
//
// GeodeticCalculator initialCalc = new GeodeticCalculator();
// initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude());
@@ -100,12 +100,12 @@
//
// GeodeticCalculator positionCalc = new GeodeticCalculator();
// positionCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude());
// ArrayList<Marker> positions = new ArrayList<>();
// ArrayList<CompoundMark> 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())));
// positions.add(new CompoundMark(new GPSCoordinate(position.getY(), position.getX())));
//
// positionCalc = new GeodeticCalculator();
// positionCalc.setStartingGeographicPoint(position);
@@ -147,7 +147,7 @@
// //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().getStartMarker().getAverageGPSCoordinate(),
// boat.setCurrentPosition(calculatePosition(boat.getCurrentLeg().getStartCompoundMark().getAverageGPSCoordinate(),
// totalDistanceTravelled, boat.calculateAzimuth()));
// }
// }
@@ -1,7 +1,6 @@
package seng302.Model;
import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants;
import seng302.GPSCoordinate;
/**
@@ -13,6 +12,8 @@ public class Leg {
private Marker startMarker;
private Marker endMarker;
private final int legNumber;
// 1 nautical mile = 1852 meters
public static final int NM_TO_METERS = 1852;
/**
* Leg Initializer
@@ -63,7 +64,6 @@ public class Leg {
* Returns the leg number that the leg exists in the Race
*
* @return Returns the Leg
* @see Race
*/
public int getLegNumber() {
return legNumber;
@@ -97,7 +97,7 @@ public class Leg {
GPSCoordinate endMarker = this.endMarker.getAverageGPSCoordinate();
calc.setStartingGeographicPoint(startMarker.getLongitude(), startMarker.getLatitude());
calc.setDestinationGeographicPoint(endMarker.getLongitude(), endMarker.getLatitude());
this.distance = calc.getOrthodromicDistance() / Constants.NMToMetersConversion;
this.distance = calc.getOrthodromicDistance() / NM_TO_METERS;
}
@@ -10,25 +10,42 @@ import java.awt.geom.Point2D;
*/
public class Marker {
private final GPSCoordinate averageGPSCoordinate;
private final GPSCoordinate mark1;
private final GPSCoordinate mark2;
public Marker(GPSCoordinate mark1) {
this.mark1 = mark1;
this.mark2 = mark1;
this.averageGPSCoordinate = calculateAverage();
private GPSCoordinate mark1;
private GPSCoordinate mark2;
private final int sourceId1;
private final int sourceId2;
public Marker(GPSCoordinate mark1, int sourceId) {
this(mark1, mark1, sourceId, sourceId);
}
public Marker(GPSCoordinate mark1, GPSCoordinate mark2) {
public Marker(GPSCoordinate mark1, GPSCoordinate mark2, int sourceId1, int sourceId2) {
this.mark1 = mark1;
this.mark2 = mark2;
this.averageGPSCoordinate = calculateAverage();
this.sourceId1 = sourceId1;
this.sourceId2 = sourceId2;
}
/**
*
* @param mark1 Mark coordinates.
*/
public Marker(GPSCoordinate mark1) {
this(mark1, mark1, 0,0);
}
/**
*
* @param mark1 Mark one coordinate
* @param mark2 Mark two coordinate
*/
public Marker(GPSCoordinate mark1, GPSCoordinate mark2) {
this(mark1, mark2, 0,0);
}
public GPSCoordinate getMark1() {
return mark1;
}
@@ -66,4 +83,19 @@ public class Marker {
}
public void setCurrentPosition1(GPSCoordinate gpsCoordinate){
mark1 = gpsCoordinate;
}
public void setCurrentPosition2(GPSCoordinate gpsCoordinate){
mark2 = gpsCoordinate;
}
public int getSourceId1() {
return sourceId1;
}
public int getSourceId2() {
return sourceId2;
}
}
@@ -1,191 +0,0 @@
package seng302.Model;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seng302.Controllers.FinishController;
import seng302.Controllers.RaceController;
import seng302.RaceDataSource;
import java.util.Arrays;
import java.util.List;
/**
* Parent class for races
* Created by fwy13 on 3/03/17.
*/
public abstract class Race implements Runnable {
protected final ObservableList<Boat> startingBoats;
protected final List<Leg> legs;
private RaceController controller;
protected FinishController finishController;
protected int boatsFinished = 0;
private long totalTimeElapsed;
private int lastFPS = 20;
/**
* Initializer 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 controller race controller
* @param scaleFactor for race
*/
private Race(List<Boat> boats, List<Leg> legs, RaceController controller, int scaleFactor) {
this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size()));
this.controller = controller;
if (startingBoats != null && startingBoats.size() > 0) {
initialiseBoats();
}
}
protected Race(RaceDataSource raceData, RaceController controller, int scaleFactor) {
this(raceData.getBoats(), raceData.getLegs(), controller, scaleFactor);
}
/**
* @deprecated
* @param startingBoats boats starting the race
* @param legs legs in race
* @param controller controller for the race
* @param scaleFactor factor to scale by
*/
public Race(Boat[] startingBoats, List<Leg> legs, RaceController controller, int scaleFactor) {
this(Arrays.asList(startingBoats), legs, controller, scaleFactor);
}
public void setController(RaceController controller) {
this.controller = controller;
}
protected abstract void initialiseBoats();
/**
* Checks if the boat cannot finish the race
* @return True if boat cannot finish the race
*/
protected abstract boolean doNotFinish();
/**
* Checks the position of the boat, this updates the boats current position.
*
* @param boat Boat that the position is to be updated for.
* @param timeElapsed Time that has elapse since the start of the the race.
* @see Boat
*/
protected abstract void checkPosition(Boat boat, long timeElapsed);
/**
* Updates the boat's gps coordinates
*
* @param boat to be updated
* @param millisecondsElapsed time since last update
*/
protected abstract void updatePosition(Boat boat, int millisecondsElapsed);
/**
* Runnable for the thread.
*/
public void run() {
setControllerListeners();
initialiseBoats();
simulateRace();
}
/**
* Update the calculated fps to the fps label
*
* @param fps The new calculated fps value
*/
private void updateFPS(int fps) {
Platform.runLater(() -> controller.setFrames("FPS: " + fps));
}
/**
* 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.
*/
private void simulateRace() {
System.setProperty("javafx.animation.fullspeed", "true");
for (Boat boat : startingBoats) {
boat.setStarted(true);
}
new AnimationTimer() {
final long timeRaceStarted = System.currentTimeMillis(); //start time of loop
int fps = 0; //init fps value
long timeCurrent = System.currentTimeMillis(); //current time
@Override
public void handle(long arg0) {
if (boatsFinished < startingBoats.size()) {
boatsFinished = 0;
totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted;
for (Boat boat : startingBoats) {
if (boat != null && !boat.isFinished()) {
updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS));
checkPosition(boat, totalTimeElapsed);
}
if (boat.isFinished()){
boatsFinished++;
}
}
//System.out.println(boatsFinished + ":" + startingBoats.size());
} else {
controller.finishRace(startingBoats);
stop();
}
controller.updateMap(startingBoats);
fps++;
if ((System.currentTimeMillis() - timeCurrent) > 1000) {
updateFPS(fps);
lastFPS = fps;
fps = 0;
timeCurrent = System.currentTimeMillis();
}
}
}.start();
}
/**
* Update position of boats in race, no position if on starting leg or DNF.
*/
protected void updatePositions() {
FXCollections.sort(startingBoats, (a, b) -> b.getCurrentLeg().getLegNumber() - a.getCurrentLeg().getLegNumber());
for(Boat boat: startingBoats) {
if(boat != null) {
boat.setPosition(Integer.toString(startingBoats.indexOf(boat) + 1));
if (boat.isDnf() || !boat.isStarted() || boat.getCurrentLeg().getLegNumber() < 0)
boat.setPosition("-");
}
}
}
/**
* Update call for the controller.
*/
private void setControllerListeners() {
if (controller != null) controller.setInfoTable(this);
}
/**
* Returns the boats that have started the race.
*
* @return ObservableList of Boat class that participated in the race.
* @see ObservableList
* @see Boat
*/
public ObservableList<Boat> getStartingBoats() {
return startingBoats;
}
}
@@ -34,13 +34,6 @@ public class RaceClock implements Runnable {
setTime(time);
}
public RaceClock(long utcTime, ZoneId zoneId) {
this.zoneId = zoneId;
this.timeString = new SimpleStringProperty();
this.time = (new Date(utcTime)).toInstant().atZone(zoneId);
setTime(time);
}
public static ZonedDateTime getCurrentZonedDateTime(GPSCoordinate gpsCoordinate) {
TimeZoneLookup timeZoneLookup = new TimeZoneLookup();
TimeZoneResult timeZoneResult = timeZoneLookup.getTimeZone(gpsCoordinate.getLatitude(), gpsCoordinate.getLongitude());
@@ -4,10 +4,10 @@ package seng302.Model;
import eu.hansolo.medusa.Gauge;
import eu.hansolo.medusa.GaugeBuilder;
import javafx.scene.layout.Pane;
import javafx.collections.ObservableList;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.transform.Rotate;
import seng302.GPSCoordinate;
import seng302.GraphCoordinate;
import seng302.Mock.StreamedCourse;
import seng302.RaceDataSource;
@@ -25,6 +25,7 @@ import java.util.List;
public class ResizableRaceCanvas extends ResizableCanvas {
private RaceMap map;
private List<Boat> boats;
private List<Marker> boatMarkers;
private boolean raceAnno = true;
private boolean annoName = true;
private boolean annoAbbrev = true;
@@ -32,7 +33,6 @@ public class ResizableRaceCanvas extends ResizableCanvas {
private boolean annoPath = true;
private List<Color> colours;
private final List<Marker> markers;
double[] xpoints = {}, ypoints = {};
private final RaceDataSource raceData;
private Gauge arrow;
@@ -60,6 +60,16 @@ public class ResizableRaceCanvas extends ResizableCanvas {
this.boats = boats;
}
/**
* Sets the boat markers that are to be displayed in this race.
*
* @param boatMarkers in race
*/
public void setBoatMarkers(ObservableList<Marker> boatMarkers) {
this.boatMarkers = boatMarkers;
}
/**
* Sets the RaceMap that the RaceCanvas is to be displaying for.
*
@@ -69,22 +79,6 @@ public class ResizableRaceCanvas extends ResizableCanvas {
this.map = map;
}
/**
* Displays the mark of a race as a circle.
*
* @param graphCoordinate Latitude and Longitude in GraphCoordinate that it
* is to be displayed as.
* @param paint Colour the mark is to be coloured.
* @see GraphCoordinate
* @see Color
* @see Paint
*/
public void displayMark(GraphCoordinate graphCoordinate, Paint paint) {
double d = 25;
this.gc.setFill(paint);
gc.fillOval(graphCoordinate.getX() - (d / 2), graphCoordinate.getY() - (d / 2), d, d);
}
private void displayBoat(Boat boat, double angle, Color colour) {
if (boat.getCurrentPosition() != null) {
GraphCoordinate pos = this.map.convertGPS(boat.getCurrentPosition());
@@ -257,19 +251,6 @@ public class ResizableRaceCanvas extends ResizableCanvas {
}
}
/**
* 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);
displayPoint(graphCoordinate, colour);
}
/**
* Toggle the raceAnno value
*/
@@ -1,327 +0,0 @@
package seng302;
import javafx.scene.paint.Color;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import seng302.Model.*;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* Created by fwy13 on 26/03/2017.
* @deprecated use {@link seng302.Mock.StreamedCourseXMLReader}
*/
public class RaceXMLReader extends XMLReader implements RaceDataSource {
private final List<Boat> boats = new ArrayList<>();
private final Color[] colors = {Color.BLUEVIOLET, Color.BLACK, Color.RED, Color.ORANGE, Color.DARKOLIVEGREEN, Color.LIMEGREEN};//TODO make this established in xml or come up with a better system.
private final List<Leg> legs = new ArrayList<>();
private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2;
private GPSCoordinate mapTopLeft, mapBottomRight;
private final List<GPSCoordinate> boundary = new ArrayList<>();
/**
* Constructor for Race XML
* @param filePath path of the file
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
*/
public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException {
this(filePath, true);
}
/**
* Constructor for Race XML
* @param filePath file path to read
* @param read whether or not to read and store the files straight away.
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
*/
public RaceXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException {
super(filePath);
if (read) {
read();
}
}
/**
* Read the files
*/
private void read() {
readCourse();
readLegs();
readBoats();
}
/**
* Read all the boats in the XML file
*/
public void readBoats() {
//get all boats
NodeList nBoats = doc.getElementsByTagName("boat");
for (int i = 0; i < nBoats.getLength(); i++) {
String name = getTextValueOfNode((Element) nBoats.item(i), "name");
String abbrev = getTextValueOfNode((Element) nBoats.item(i), "abbr");
double velo = Double.parseDouble(getTextValueOfNode((Element) nBoats.item(i), "speed"));
BoatInRace boat = new BoatInRace(name, velo, colors[i], abbrev);
boat.setCurrentPosition(startPt1);
if (legs.size() > 0) {
boat.setCurrentLeg(legs.get(0));
}
boats.add(boat);
}
}
/**
* Read all the legs in the XML file
*/
public void readLegs() {
//get all legs
NodeList nLegs = doc.getElementsByTagName("leg");
for (int i = 0; i < nLegs.getLength(); i++) {
String label = getTextValueOfNode((Element) nLegs.item(i), "name");
NodeList start = ((Element) nLegs.item(i)).getElementsByTagName("start");
Marker startMarker = getMarker(start);
NodeList finish = ((Element) nLegs.item(i)).getElementsByTagName("finish");
Marker finishMarker = getMarker(finish);
legs.add(new Leg(label, startMarker, finishMarker, i));
}
}
/**
* Read courses in XML file
*/
public void readCourse() {
NodeList nCourse = doc.getElementsByTagName("course");
NodeList nBounds = ((Element) nCourse.item(0)).getElementsByTagName("boundaries");
nBounds = ((Element) nBounds.item(0)).getElementsByTagName("coordinate");
int maxLatitudeIndex = 0;
double maxLatitude = -Double.MIN_VALUE;
int maxLongitudeIndex = 0;
double maxLongitude = -180;
int minLatitudeIndex = 0;
double minLatitude = Double.MAX_VALUE;
int minLongitudeIndex = 0;
double minLongitude = Double.MAX_VALUE;
for (int i = 0; i < nBounds.getLength(); i++) {
boundary.add(getCoordinates((Element) nBounds.item(i)));
if (boundary.get(i).getLatitude() > maxLatitude) {
maxLatitudeIndex = i;
maxLatitude = boundary.get(i).getLatitude();
}
if (boundary.get(i).getLatitude() < minLatitude) {
minLatitudeIndex = i;
minLatitude = boundary.get(i).getLatitude();
}
if (boundary.get(i).getLongitude() > maxLongitude) {
maxLongitudeIndex = i;
maxLongitude = boundary.get(i).getLongitude();
}
if (boundary.get(i).getLongitude() < minLongitude) {
minLongitudeIndex = i;
minLongitude = boundary.get(i).getLongitude();
}
}
double difference = 0;//this will hold the largest difference so we can make the map square.
double latitudeDiff = Math.abs(Math.abs(boundary.get(maxLatitudeIndex).getLatitude()) - Math.abs(boundary.get(minLatitudeIndex).getLatitude()));
double longitudeDiff = Math.abs(Math.abs(boundary.get(maxLongitudeIndex).getLongitude()) - Math.abs(boundary.get(minLongitudeIndex).getLongitude()));
if (latitudeDiff >= longitudeDiff) {
difference = latitudeDiff - longitudeDiff;
maxLongitude += difference / 2;
minLongitude -= difference / 2;
} else {
difference = longitudeDiff - latitudeDiff;
maxLatitude += difference / 2;
minLatitude -= difference / 2;
}
double COORDINATEPADDING = 0.0005;
maxLatitude += COORDINATEPADDING;
minLatitude -= COORDINATEPADDING;
maxLongitude += COORDINATEPADDING;
minLongitude -= COORDINATEPADDING;
//now create map boundaries
//top left canvas point is min longitude, max latitude
//bottom right of canvas point is min longitude, max latitude.
mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude);
NodeList nMarks = ((Element) nCourse.item(0)).getElementsByTagName("marker");
startPt1 = getCoordinates(nMarks, 0);
startPt2 = getCoordinates(nMarks, 0, 1);
mark = getCoordinates(nMarks, 1);
windwardPt1 = getCoordinates(nMarks, 2);
windwardPt2 = getCoordinates(nMarks, 2, 1);
leewardPt1 = getCoordinates(nMarks, 3);
leewardPt2 = getCoordinates(nMarks, 3, 1);
finishPt1 = getCoordinates(nMarks, 4);
finishPt2 = getCoordinates(nMarks, 4, 1);
}
/**
* gets a marker from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @return
*/
private Marker getMarker(NodeList start) {
return getMarker(start, 0);
}
/**
* gets a marker from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @param startIndex index in the node that has the coordinate tag
* @return
*/
private Marker getMarker(NodeList start, int startIndex) {
return getMarker(start, startIndex, 0);
}
/**
* gets a marker from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @param startIndex index in the node that has the coordinate tag
* @param nodeIndex coordinate index
* @return
*/
private Marker getMarker(NodeList start, int startIndex, int nodeIndex) {
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("marker");
Element marker = (Element) nodeList.item(nodeIndex);
return getMarker(marker);
}
/**
* gets a changes a marker to GPS coordinates into a marker
* @param markerNode marker to turn into coordinates
* @return
*/
private Marker getMarker(Element markerNode) {
NodeList nCoordinates = markerNode.getElementsByTagName("coordinate");
GPSCoordinate side1 = getCoordinates((Element) nCoordinates.item(0));
GPSCoordinate side2;
if (nCoordinates.getLength() > 1) {
side2 = getCoordinates((Element) nCoordinates.item(1));
} else {
side2 = side1;
}
return new Marker(side1, side2);
}
/**
* gets a coordinates from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @return
*/
private GPSCoordinate getCoordinates(NodeList start) {
return getCoordinates(start, 0);
}
/**
* gets a coordinates from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @param startIndex the index the tag containing the coordinate should be in
* @return
*/
private GPSCoordinate getCoordinates(NodeList start, int startIndex) {
return getCoordinates(start, startIndex, 0);
}
/**
* gets a coordinates from the XML file
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
* @param startIndex the index the tag containing the coordinate should be in
* @param nodeIndex The coordinate index
* @return
*/
private GPSCoordinate getCoordinates(NodeList start, int startIndex, int nodeIndex) {
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("coordinate");
Element coord = (Element) nodeList.item(nodeIndex);
return getCoordinates(coord);
}
/**
* Returns the coordinate TODO raise exception that runs when the XML is formatted wrongly.
*
* @param coordNode
* @return
*/
private GPSCoordinate getCoordinates(Element coordNode) {
double startLat = Double.parseDouble(getTextValueOfNode(coordNode, "latitude"));
double startLong = Double.parseDouble(getTextValueOfNode(coordNode, "longitude"));
return new GPSCoordinate(startLat, startLong);
}
@Override
public List<Marker> getMarkers() {
return null;
}
public List<Boat> getBoats() {
return boats;
}
public List<Leg> getLegs() {
return legs;
}
public ZonedDateTime getZonedDateTime() {
return RaceClock.getCurrentZonedDateTime(mark);
}
public GPSCoordinate getStartPt1() {
return startPt1;
}
public GPSCoordinate getStartPt2() {
return startPt2;
}
public GPSCoordinate getFinishPt1() {
return finishPt1;
}
public GPSCoordinate getFinishPt2() {
return finishPt2;
}
public GPSCoordinate getLeewardPt1() {
return leewardPt1;
}
public GPSCoordinate getLeewardPt2() {
return leewardPt2;
}
public GPSCoordinate getWindwardPt1() {
return windwardPt1;
}
public GPSCoordinate getWindwardPt2() {
return windwardPt2;
}
public List<GPSCoordinate> getBoundary() {
return boundary;
}
public GPSCoordinate getMapTopLeft() {
return mapTopLeft;
}
public GPSCoordinate getMapBottomRight() {
return mapBottomRight;
}
}
@@ -1,4 +1,5 @@
package seng302;
import javafx.application.Platform;
import org.xml.sax.SAXException;
import seng302.Mock.*;
import seng302.Networking.BinaryMessageDecoder;
@@ -10,7 +11,6 @@ import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -23,9 +23,6 @@ import static seng302.Networking.Utils.ByteConverter.bytesToShort;
*/
public class VisualiserInput implements Runnable {
///A queue that contains messages that have been received, and need to be handled.
private final ArrayBlockingQueue<AC35Data> messagesReceivedQueue = new ArrayBlockingQueue<>(1000000);//We have room for 1,000,000. Is this much capacity actually needed?
///Timestamp of the last heartbeat.
private long lastHeartbeatTime = -1;
///Sequence number of the last heartbeat.
@@ -162,7 +159,7 @@ public class VisualiserInput implements Runnable {
* @throws IOException Thrown when an error occurs while reading from the socket.
*/
private byte[] getNextMessageBytes() throws IOException {
inStream.mark(0);
short CRCLength = 4;
short headerLength = 15;
@@ -256,12 +253,17 @@ public class VisualiserInput implements Runnable {
catch (InvalidMessageException | IOException e) {
//Prints exception to stderr, and iterate loop (that is, read the next message).
System.err.println("Unable to read message: " + e.getMessage());
try {
inStream.reset();
} catch (IOException e1) {
e1.printStackTrace();
}
//Continue to the next loop iteration/message.
continue;
}
}/*
//Add it to message queue.
this.messagesReceivedQueue.add(message);
this.messagesReceivedQueue.add(message);*/
//Checks which message is being received and does what is needed for that message.
@@ -298,42 +300,43 @@ public class VisualiserInput implements Runnable {
//System.out.println("XML Message!");
if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeRegatta){
//System.out.println("Setting Regatta");
try {
course.setRegattaXMLReader(new RegattaXMLReader(xmlMessage.getXmlMessage()));
}
//TODO REFACTOR should put all of these exceptions behind a RegattaXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException e) {
System.err.println("Error creating RegattaXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
Platform.runLater(()-> {
if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeRegatta) {
//System.out.println("Setting Regatta");
try {
course.setRegattaXMLReader(new RegattaXMLReader(xmlMessage.getXmlMessage()));
} else if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeRace){
//System.out.println("Setting Course");
try {
course.setStreamedCourseXMLReader(new StreamedCourseXMLReader(xmlMessage.getXmlMessage()));
}
//TODO REFACTOR should put all of these exceptions behind a StreamedCourseXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException | ParseException | StreamedCourseXMLException e) {
System.err.println("Error creating StreamedCourseXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
}
//TODO REFACTOR should put all of these exceptions behind a RegattaXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException e) {
System.err.println("Error creating RegattaXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
} else if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeBoat){
//System.out.println("Setting Boats");
try
{
course.setBoatXMLReader(new BoatXMLReader(xmlMessage.getXmlMessage()));
}
//TODO REFACTOR should put all of these exceptions behind a BoatXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException e) {
System.err.println("Error creating BoatXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
} else if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeRace) {
//System.out.println("Setting Course");
try {
course.setStreamedCourseXMLReader(new StreamedCourseXMLReader(xmlMessage.getXmlMessage()));
}
//TODO REFACTOR should put all of these exceptions behind a StreamedCourseXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException | StreamedCourseXMLException e) {
System.err.println("Error creating StreamedCourseXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
}
} else if (xmlMessage.getXmlMsgSubType() == XMLMessage.XMLTypeBoat) {
//System.out.println("Setting Boats");
try {
course.setBoatXMLReader(new BoatXMLReader(xmlMessage.getXmlMessage()));
}
//TODO REFACTOR should put all of these exceptions behind a BoatXMLReaderException.
catch (IOException | SAXException | ParserConfigurationException e) {
System.err.println("Error creating BoatXMLReader: " + e.getMessage());
//Continue to the next loop iteration/message.
}
}
});
}
//RaceStartStatus.
else if (message instanceof RaceStartStatus) {
@@ -379,7 +382,6 @@ public class VisualiserInput implements Runnable {
//If the map _doesn't_ already contain a message for this boat, insert the message.
this.boatLocationMap.put(boatLocation.getSourceID(), boatLocation);
}
}
//MarkRounding.
else if (message instanceof MarkRounding) {
@@ -42,7 +42,7 @@
<leg>
<name>Start to Mark 1</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.296577</latitude>
<longitude>-64.854304</longitude>
@@ -51,29 +51,29 @@
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Mark 1 to Leeward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -82,13 +82,13 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Leeward Gate to Windward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -97,10 +97,10 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
@@ -109,13 +109,13 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Windward Gate to Leeward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
@@ -124,10 +124,10 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -136,13 +136,13 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Leeward Gate to Finish</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -151,10 +151,10 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.317379</latitude>
<longitude>-64.839291</longitude>
@@ -163,7 +163,7 @@
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
</legs>
@@ -214,7 +214,7 @@
<longitude>-64.849184</longitude>
</coordinate>
</boundaries>
<marker>
<compoundMark>
<name>Start Line</name>
<coordinate>
<latitude>32.296577</latitude>
@@ -224,15 +224,15 @@
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Mark</name>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Windward Gate</name>
<coordinate>
<latitude>32.284680</latitude>
@@ -242,8 +242,8 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Leeward Gate</name>
<coordinate>
<latitude>32.309693</latitude>
@@ -253,8 +253,8 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Finish Line</name>
<coordinate>
<latitude>32.317379</latitude>
@@ -264,6 +264,6 @@
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</compoundMark>
</course>
</race>
@@ -1,47 +1,47 @@
package seng302.Mock;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
* Created by jjg64 on 21/04/17.
*/
public class BoatsXMLTest {
private BoatXMLReader boatXMLReader;
@Before
public void setup() {
try {
boatXMLReader = new BoatXMLReader("mockXML/boatXML/boatTest.xml", false);
} catch (Exception e) {
e.printStackTrace();
//fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder");
}
}
@Test
public void testInvalidParticipant() {
Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
inputParticipants.put(420, new StreamedBoat(420));
boatXMLReader.setParticipants(inputParticipants);
boatXMLReader.read();
assertEquals(boatXMLReader.getBoats().size(), 0);
}
@Test
public void testValidParticipant() {
Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
inputParticipants.put(101, new StreamedBoat(101));
boatXMLReader.setParticipants(inputParticipants);
boatXMLReader.read();
assertEquals(boatXMLReader.getBoats().size(), 1);
StreamedBoat boat = (StreamedBoat) boatXMLReader.getBoats().get(0);
assertEquals(boat.getSourceID(), 101);
}
}
//package seng302.Mock;
//
//import org.junit.Before;
//import org.junit.Test;
//
//import java.util.HashMap;
//import java.util.Map;
//
//import static org.junit.Assert.assertEquals;
//
///**
// * Created by jjg64 on 21/04/17.
// */
//public class BoatsXMLTest {
// private BoatXMLReader boatXMLReader;
//
// @Before
// public void setup() {
// try {
// boatXMLReader = new BoatXMLReader("mockXML/boatXML/boatTest.xml", false);
// } catch (Exception e) {
// e.printStackTrace();
// //fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder");
// }
// }
//
// @Test
// public void testInvalidParticipant() {
// Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
// inputParticipants.put(420, new StreamedBoat(420));
// boatXMLReader.setParticipants(inputParticipants);
// boatXMLReader.read();
// assertEquals(boatXMLReader.getBoats().size(), 0);
// }
//
// @Test
// public void testValidParticipant() {
// Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
// inputParticipants.put(101, new StreamedBoat(101));
// boatXMLReader.setParticipants(inputParticipants);
// boatXMLReader.read();
// assertEquals(boatXMLReader.getBoats().size(), 1);
// StreamedBoat boat = (StreamedBoat) boatXMLReader.getBoats().get(0);
// assertEquals(boat.getSourceID(), 101);
// }
//
//}
@@ -1,26 +1,26 @@
package seng302.Mock;
import org.junit.Test;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.text.ParseException;
/**
* Created by jjg64 on 1/05/17.
*/
public class FailBoatXMLTest {
private final String path = "mockXML/boatXML/";
@Test(expected = NumberFormatException.class)
public void invalidSourceID() throws SAXException, ParserConfigurationException, ParseException, IOException {
new BoatXMLReader(path + "invalidSourceID.xml");
}
@Test(expected = NullPointerException.class)
public void insufficientInformation() throws SAXException, ParserConfigurationException, ParseException, IOException {
new BoatXMLReader(path + "insufficientInformation.xml");
}
}
//package seng302.Mock;
//
//import org.junit.Test;
//import org.xml.sax.SAXException;
//
//import javax.xml.parsers.ParserConfigurationException;
//import java.io.IOException;
//import java.text.ParseException;
//
///**
// * Created by jjg64 on 1/05/17.
// */
//public class FailBoatXMLTest {
// private final String path = "mockXML/boatXML/";
//
// @Test(expected = NumberFormatException.class)
// public void invalidSourceID() throws SAXException, ParserConfigurationException, ParseException, IOException {
// new BoatXMLReader(path + "invalidSourceID.xml");
// }
//
// @Test(expected = NullPointerException.class)
// public void insufficientInformation() throws SAXException, ParserConfigurationException, ParseException, IOException {
// new BoatXMLReader(path + "insufficientInformation.xml");
// }
//
//}
@@ -87,8 +87,8 @@ public class StreamedRaceTest {
GPSCoordinate topLeft = streamedCourseXMLReader.getMapTopLeft();
GPSCoordinate bottomRight = streamedCourseXMLReader.getMapBottomRight();
for(Marker marker: streamedCourseXMLReader.getMarkers()) {
GPSCoordinate centre = marker.getAverageGPSCoordinate();
for(Marker compoundMark : streamedCourseXMLReader.getMarkers()) {
GPSCoordinate centre = compoundMark.getAverageGPSCoordinate();
assertTrue(centre.getLatitude() < bottomRight.getLatitude());
assertTrue(centre.getLatitude() > topLeft.getLatitude());
assertTrue(centre.getLongitude() > bottomRight.getLongitude());
@@ -17,8 +17,8 @@
// */
//public class ConstantVelocityRaceTest {
//
// Marker START_MARKER = new Marker(new GPSCoordinate(0, 0));
// Marker END_MARKER = new Marker(new GPSCoordinate(10, 10));
// CompoundMark START_MARKER = new CompoundMark(new GPSCoordinate(0, 0));
// CompoundMark END_MARKER = new CompoundMark(new GPSCoordinate(10, 10));
// Leg START_LEG = new Leg("Start", START_MARKER, END_MARKER, 0);
//
// int ONE_HOUR = 3600000; //1 hour in milliseconds
@@ -2,28 +2,28 @@ package seng302.Model;
import org.geotools.referencing.GeodeticCalculator;
import org.junit.Test;
import seng302.Constants;
import seng302.GPSCoordinate;
import java.awt.geom.Point2D;
import static junit.framework.TestCase.assertEquals;
import static seng302.Model.Leg.NM_TO_METERS;
/**
* Created by esa46 on 22/03/17.
*/
public class LegTest {
private final Marker ORIGIN_MARKER = new Marker(new GPSCoordinate(0, 0));
private final Marker ORIGIN_Marker = new Marker(new GPSCoordinate(0, 0));
@Test
public void calculateDistanceHandles5nmNorth() {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(0, 0);
calc.setDirection(0, 5 * Constants.NMToMetersConversion);
calc.setDirection(0, 5 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0);
Leg test = new Leg("Test", ORIGIN_Marker, endMarker, 0);
assertEquals(test.getDistance(), 5, 1e-8);
}
@@ -31,10 +31,10 @@ public class LegTest {
public void calculateDistanceHandles12nmEast() {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(0, 0);
calc.setDirection(90, 12 * Constants.NMToMetersConversion);
calc.setDirection(90, 12 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0);
Leg test = new Leg("Test", ORIGIN_Marker, endMarker, 0);
assertEquals(test.getDistance(), 12, 1e-8);
}
@@ -42,10 +42,10 @@ public class LegTest {
public void calculateDistanceHandlesHalfnmSouth() {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(0, 0);
calc.setDirection(180, 0.5 * Constants.NMToMetersConversion);
calc.setDirection(180, 0.5 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0);
Leg test = new Leg("Test", ORIGIN_Marker, endMarker, 0);
assertEquals(test.getDistance(), 0.5, 1e-8);
}
@@ -53,17 +53,17 @@ public class LegTest {
public void calculateDistanceHandlesPoint1nmWest() {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(0, 0);
calc.setDirection(-90, 0.1 * Constants.NMToMetersConversion);
calc.setDirection(-90, 0.1 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0);
Leg test = new Leg("Test", ORIGIN_Marker, endMarker, 0);
assertEquals(test.getDistance(), 0.1, 1e-8);
}
@Test
public void calculateDistanceHandlesZeroDifference() {
Leg test = new Leg("Test", ORIGIN_MARKER, ORIGIN_MARKER, 0);
Leg test = new Leg("Test", ORIGIN_Marker, ORIGIN_Marker, 0);
assertEquals(test.getDistance(), 0, 1e-8);
}
@@ -1,93 +0,0 @@
package seng302.Model;
/**
* Created by Gondr on 26/03/2017.
*/
import org.junit.Test;
import seng302.RaceXMLReader;
import java.util.List;
import static org.junit.Assert.*;
public class RaceXMLTest {
RaceXMLReader raceXMLReader;
@Test
public void canFindFile() {
try {
RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false);
} catch (Exception e) {
fail("Cannot find raceXML/bermuda_AC35.xml in the resources folder");
}
}
@Test
public void canReadBoats() {
try {
RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false);
raceXMLReader.readBoats();
List<Boat> boats = raceXMLReader.getBoats();
assertTrue(boats.size() == 6);
//test boat 1
assertEquals(boats.get(0).getName().getValue(), "ORACLE TEAM USA");
assertTrue(boats.get(0).getVelocity() == 20);
//test boat 2
assertEquals(boats.get(1).getName().getValue(), "Land Rover BAR");
assertTrue(boats.get(1).getVelocity() == 30);
assertEquals(boats.get(1).getAbbrev(), "GBR");
//test boat 3
assertEquals(boats.get(2).getName().getValue(), "SoftBank Team Japan");
assertTrue(boats.get(2).getVelocity() == 25);
assertEquals(boats.get(2).getAbbrev(), "JPN");
//test boat 4
assertEquals(boats.get(3).getName().getValue(), "Groupama Team France");
assertTrue(boats.get(3).getVelocity() == 20);
assertEquals(boats.get(3).getAbbrev(), "FRA");
//test boat 5
assertEquals(boats.get(4).getName().getValue(), "Artemis Racing");
assertTrue(boats.get(4).getVelocity() == 29);
assertEquals(boats.get(4).getAbbrev(), "SWE");
//test boat 6
assertEquals(boats.get(5).getName().getValue(), "Emirates Team New Zealand");
assertTrue(boats.get(5).getVelocity() == 62);
assertEquals(boats.get(5).getAbbrev(), "NZL");
} catch (Exception e) {
fail("Boat Unreadable");
}
}
@Test
public void canReadLegs() {
try {
RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false);
raceXMLReader.readLegs();
assertTrue(raceXMLReader.getLegs().size() == 5);
} catch (Exception e) {
fail("Legs Unreadable");
}
}
@Test
public void canReadCourse() {
try {
RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false);
raceXMLReader.readCourse();
assertTrue(raceXMLReader.getMapTopLeft() != null);
assertTrue(raceXMLReader.getMapBottomRight() != null);
assertTrue(raceXMLReader.getFinishPt1() != null);
assertTrue(raceXMLReader.getFinishPt2() != null);
assertTrue(raceXMLReader.getStartPt1() != null);
assertTrue(raceXMLReader.getStartPt2() != null);
assertTrue(raceXMLReader.getLeewardPt1() != null);
assertTrue(raceXMLReader.getLeewardPt2() != null);
assertTrue(raceXMLReader.getWindwardPt1() != null);
assertTrue(raceXMLReader.getWindwardPt2() != null);
assertTrue(raceXMLReader.getBoundary().size() == 11);
} catch (Exception e) {
e.printStackTrace();
fail("Course Unreadable");
}
}
}
@@ -41,7 +41,7 @@
<leg>
<name>Start to Mark 1</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.296577</latitude>
<longitude>-64.854304</longitude>
@@ -50,29 +50,29 @@
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Mark 1 to Leeward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -81,13 +81,13 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Leeward Gate to Windward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -96,10 +96,10 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
@@ -108,13 +108,13 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Windward Gate to Leeward Gate</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
@@ -123,10 +123,10 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -135,13 +135,13 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
<leg>
<name>Leeward Gate to Finish</name>
<start>
<marker>
<compoundMark>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
@@ -150,10 +150,10 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</compoundMark>
</start>
<finish>
<marker>
<compoundMark>
<coordinate>
<latitude>32.317379</latitude>
<longitude>-64.839291</longitude>
@@ -162,7 +162,7 @@
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</compoundMark>
</finish>
</leg>
</legs>
@@ -213,7 +213,7 @@
<longitude>-64.849184</longitude>
</coordinate>
</boundaries>
<marker>
<compoundMark>
<name>Start Line</name>
<coordinate>
<latitude>32.296577</latitude>
@@ -223,15 +223,15 @@
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Mark</name>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Windward Gate</name>
<coordinate>
<latitude>32.284680</latitude>
@@ -241,8 +241,8 @@
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Leeward Gate</name>
<coordinate>
<latitude>32.309693</latitude>
@@ -252,8 +252,8 @@
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
<marker>
</compoundMark>
<compoundMark>
<name>Finish Line</name>
<coordinate>
<latitude>32.317379</latitude>
@@ -263,6 +263,6 @@
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</compoundMark>
</course>
</race>