Merge remote-tracking branch 'origin/49Mock' into Story49Vis

# Conflicts:
#	visualiser/src/test/java/seng302/Model/RaceXMLTest.java
main
Fan-Wu Yang 9 years ago
commit 7bfb6bb968

@ -1,7 +1,7 @@
junit: junit:
stage: test stage: test
script: script:
- mvn -B clean test - mvn -B -Dprism.verbose=true clean test
generate_artifacts: generate_artifacts:
stage: deploy stage: deploy

@ -3,16 +3,14 @@ package seng302;
import javafx.application.Application; import javafx.application.Application;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.xml.sax.SAXException;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RaceXMLReader;
import seng302.DataInput.RegattaDataSource;
import seng302.DataInput.RegattaXMLReader;
import seng302.Model.Event;
import seng302.Model.Event;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App extends Application { public class App extends Application {
@ -28,16 +26,22 @@ public class App extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
try { try {
RaceDataSource raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml");
RegattaDataSource regattaData = new RegattaXMLReader("mockXML/regattaTest.xml"); String regattaXML = readFile("mock/src/main/resources/mockXML/regattaTest.xml", StandardCharsets.UTF_8);
Event raceEvent = new Event(raceData, regattaData); String raceXML = readFile("mock/src/main/resources/mockXML/raceTest.xml", StandardCharsets.UTF_8);
String boatXML = readFile("mock/src/main/resources/mockXML/boatTest.xml", StandardCharsets.UTF_8);
Event raceEvent = new Event(raceXML, regattaXML, boatXML);
raceEvent.start(); raceEvent.start();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} }
} }
static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
} }

@ -8,5 +8,7 @@ public class Constants {
public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters
public static final int PRE_RACE_WAIT_TIME = 18000;
public static final int TEST_VELOCITIES[] = new int[] { 30, 15, 64, 52, 25, 24 };
} }

@ -1,220 +0,0 @@
package seng302.Data;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import seng302.Exceptions.InvalidBoatDataException;
import seng302.Model.Boat;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.util.List;
/**
* Created by esa46 on 25/04/17.
*/
public class BoatData {
Document doc;
private List<Boat> boatData;
public BoatData(List<Boat> boatData) {
this.boatData = boatData;
}
/**
* Creates an AC35 officially formatted xml description of boats competing in a race
*
* @return String containing xml-formatted boats description
*/
public String createXML() {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//root element
doc = docBuilder.newDocument();
Element rootElement = doc.createElement("BoatConfig");
doc.appendChild(rootElement);
//Boats element
Element boats = doc.createElement("Boats");
rootElement.appendChild(boats);
appendIndividualBoats(boats);
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
//Serialize document.
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result);
System.out.println(stringWriter.toString());
return stringWriter.toString();
} catch (ParserConfigurationException pce) {
throw new InvalidBoatDataException();
} catch (TransformerException tfe) {
throw new InvalidBoatDataException();
}
}
/**
* Runs through competing boats, creating an element for each
*
* @param boatsElement boats element to be added to
*/
private void appendIndividualBoats(Element boatsElement) {
for (int i = 0; i < boatData.size(); i++) {
Element boat = doc.createElement("Boat");
appendType(boat);
appendSourceID(boat, i);
appendShapeID(boat);
appendHullNum(boat);
appendStoweName(boat, i);
appendShortName(boat, i);
appendBoatName(boat, i);
appendGPSCoords(boat, i);
//Write boat to boats
boatsElement.appendChild(boat);
}
}
/**
* Creates and appends type attribute of a boat
*
* @param boat element being added to
*/
private void appendType(Element boat) {
//Type attribute
Attr attrType = doc.createAttribute("Type");
attrType.setValue("Yacht");
boat.setAttributeNode(attrType);
}
/**
* Creates and appends sourceID attribute of a boat
*
* @param boat element being added to
* @param i boat number
*/
private void appendSourceID(Element boat, int i) {
//SourceID attribute
Attr attrSourceID = doc.createAttribute("SourceID");
attrSourceID.setValue(Integer.toString(boatData.get(i).getSourceID()));
boat.setAttributeNode(attrSourceID);
}
/**
* Creates and appends shapeID attribute of a boat
*
* @param boat element being added to
*/
private void appendShapeID(Element boat) {
//ShapeID attribute
Attr attrShapeID = doc.createAttribute("ShapeID");
attrShapeID.setValue("0");
boat.setAttributeNode(attrShapeID);
}
/**
* Creates and appends hull name attribute of a boat
*
* @param boat element being added to
*/
private void appendHullNum(Element boat) {
//HullNum attribute
Attr attrHullNum = doc.createAttribute("HullNum");
attrHullNum.setValue("RG01");
boat.setAttributeNode(attrHullNum);
}
/**
* Creates and appends stow name attribute of a boat
*
* @param boat element being added to
* @param i boat number
*/
private void appendStoweName(Element boat, int i) {
//StoweName attribute
Attr attrStoweName = doc.createAttribute("StoweName");
attrStoweName.setValue(boatData.get(i).getAbbrev());
boat.setAttributeNode(attrStoweName);
}
/**
* Creates and appends short name attribute of a boat
*
* @param boat element being added to
* @param i boat number
*/
private void appendShortName(Element boat, int i) {
//ShortName attribute
Attr attrShortName = doc.createAttribute("ShortName");
attrShortName.setValue(boatData.get(i).getAbbrev());
boat.setAttributeNode(attrShortName);
}
/**
* Creates and appends boat name attribute of a boat
*
* @param boat element being added to
* @param i boat number
*/
private void appendBoatName(Element boat, int i) {
//BoatName attribute
Attr attrBoatName = doc.createAttribute("BoatName");
attrBoatName.setValue(boatData.get(i).getName());
boat.setAttributeNode(attrBoatName);
}
/**
* Creates and appends gps attributes of a boat
*
* @param boat element being added to
* @param i boat number
*/
private void appendGPSCoords(Element boat, int i) {
//GPSCoord for element
Element GPSCoord = doc.createElement("GPSposition");
//Z axis attribute
Attr attrZCoord = doc.createAttribute("Z");
attrZCoord.setValue("0");
GPSCoord.setAttributeNode(attrZCoord);
//Y axis attribute
Attr attrYCoord = doc.createAttribute("Y");
attrYCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLatitude()));
GPSCoord.setAttributeNode(attrYCoord);
//X axis attribute
Attr attrXCoord = doc.createAttribute("X");
attrXCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLongitude()));
GPSCoord.setAttributeNode(attrXCoord);
//Write GPSCoord to boat
boat.appendChild(GPSCoord);
}
}

@ -1,250 +0,0 @@
package seng302.Data;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import seng302.DataInput.RaceDataSource;
import seng302.Exceptions.InvalidRaceDataException;
import seng302.Model.Boat;
import seng302.Model.GPSCoordinate;
import seng302.Model.Marker;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/**
* Created by esa46 on 21/04/17.
*/
public class RaceData {
private RaceDataSource dataSource;
private Document doc;
private Element rootElement;
private ZonedDateTime creationTimeDate;
public RaceData(RaceDataSource dataSource) {
this.dataSource = dataSource;
creationTimeDate = ZonedDateTime.now();
}
/**
* Creates an AC35 officially formatted xml description of a race.
*
* @return String containing xml-formatted race description
*/
public String createXML() {
try {
//create base xml document
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.newDocument();
//create root element (In this case, "Race")
rootElement = doc.createElement("Race");
doc.appendChild(rootElement);
appendChildElements();
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
//Serialize document.
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result);
return stringWriter.toString();
} catch (ParserConfigurationException pce) {
throw new InvalidRaceDataException();
} catch (TransformerException tfe) {
throw new InvalidRaceDataException();
}
}
/**
* Creates all necessary child elements and appends them to the xml doc
*/
private void appendChildElements() {
appendRaceId();
appendRaceType();
appendCreationTimeDate();
appendRaceStartTime();
appendParticipants();
appendCourse();
appendCourseLimit();
}
/**
* Creates and appends race id element
*/
private void appendRaceId() {
Element raceIdElement = doc.createElement("RaceID");
raceIdElement.appendChild(doc.createTextNode(Integer.toString(dataSource.getRaceId())));
rootElement.appendChild(raceIdElement);
}
/**
* Creates and appends race type element
*/
private void appendRaceType() {
Element raceTypeElement = doc.createElement("RaceType");
raceTypeElement.appendChild(doc.createTextNode(dataSource.getRaceType()));
rootElement.appendChild(raceTypeElement);
}
/**
* Creates and appends creation time date element
*/
private void appendCreationTimeDate() {
Element creationTimeElement = doc.createElement("CreationTimeDate");
creationTimeElement.appendChild(doc.createTextNode(toTruncatedString(creationTimeDate)));
rootElement.appendChild(creationTimeElement);
}
/**
* Creates and appends race start time element, which is 3 minutes after the race was created by default
*/
private void appendRaceStartTime() {
Element startTimeElement = doc.createElement("RaceStartTime");
startTimeElement.setAttribute("Time", (toTruncatedString(creationTimeDate.plusMinutes(0))));
startTimeElement.setAttribute("Postpone", "false");
rootElement.appendChild(startTimeElement);
}
/**
* Creates and appends participants element
*/
private void appendParticipants() {
Element participantsElement = doc.createElement("Participants");
for (Boat boat : dataSource.getBoats()) {
Element yachtElement = doc.createElement("Yacht");
yachtElement.setAttribute("SourceID", boat.getSourceID() + "");
participantsElement.appendChild(yachtElement);
}
rootElement.appendChild(participantsElement);
}
/**
* Creates and appends course elements
*/
private void appendCourse() {
Element courseElement = doc.createElement("Course");
Element compoundMarkSeqElement = doc.createElement("CompoundMarkSequence");
int i = 1;
for (Marker marker : dataSource.getMarkers()) {
courseElement.appendChild(createCompoundMarker(marker, i));
compoundMarkSeqElement.appendChild(createCornerElement(i));
i++;
}
rootElement.appendChild(compoundMarkSeqElement);
rootElement.appendChild(courseElement);
}
/**
* Creates a mark element for insertion in a coumpound mark element
*
* @param marker GPS coordinates of the mark
* @return Element mark element
*/
private Element createMark(GPSCoordinate marker) {
Element mark = doc.createElement("Mark");
mark.setAttribute("TargetLat", marker.getLatitude() + "");
mark.setAttribute("TargetLng", marker.getLongitude() + "");
return mark;
}
/**
* Creates a compound marker holding one or two marks,and a sequence number
*
* @param marker marker
* @param i sequence number
* @return Element compound mark element
*/
private Element createCompoundMarker(Marker marker, int i) {
Element compoundMarkElement = doc.createElement("CompoundMark");
compoundMarkElement.setAttribute("CompoundMarkID", i + "");
compoundMarkElement.setAttribute("Name", marker.getName());
compoundMarkElement.appendChild(createMark(marker.getMark1()));
if (!(marker.getMark1().equals(marker.getMark2()))) {
compoundMarkElement.appendChild(createMark(marker.getMark2()));
}
return compoundMarkElement;
}
/**
* Creates a corner element
*
* @param i sequence number
* @return Element corner element
*/
private Element createCornerElement(int i) {
Element cornerElement = doc.createElement("Corner");
cornerElement.setAttribute("SeqID", i + "");
cornerElement.setAttribute("CompoundMarkID", i + "");
return cornerElement;
}
/**
* Creates and appends course limits element (boundaries)
*/
private void appendCourseLimit() {
int j = 1;
Element courseLimitElement = doc.createElement("CourseLimit");
for (GPSCoordinate coordinate : dataSource.getBoundary()) {
Element limitElement = doc.createElement("Limit");
limitElement.setAttribute("SeqID", j + "");
limitElement.setAttribute("Lat", coordinate.getLatitude() + "");
limitElement.setAttribute("Lon", coordinate.getLongitude() + "");
courseLimitElement.appendChild(limitElement);
j++;
}
rootElement.appendChild(courseLimitElement);
}
/**
* Format time data and return it.
* @param time time data.
* @return formatted time data.
*/
private String toTruncatedString(ZonedDateTime time) {
DateTimeFormatter dateFormat = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
String text = dateFormat.format(time);
return text;
}
}

@ -1,169 +0,0 @@
package seng302.Data;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import seng302.DataInput.RegattaDataSource;
import seng302.Exceptions.InvalidRegattaDataException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
/**
* Created by esa46 on 25/04/17.
*/
public class RegattaData {
private RegattaDataSource regattaDataSource;
private Document doc;
private Element rootElement;
public RegattaData(RegattaDataSource regattaDataSource) {
this.regattaDataSource = regattaDataSource;
}
/**
* Creates an AC35 officially formatted xml description of a regatta
*
* @return String containing xml-formatted regatta description
*/
public String createXML() {
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//root element
doc = docBuilder.newDocument();
rootElement = doc.createElement("RegattaConfig");
doc.appendChild(rootElement);
appendChildElements();
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
DOMSource source = new DOMSource(doc);
//Serialize document.
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result);
return stringWriter.toString();
} catch (ParserConfigurationException pce) {
throw new InvalidRegattaDataException();
} catch (TransformerException tfe) {
throw new InvalidRegattaDataException();
}
}
/**
* Creates all necessary child elements and appends them to the xml doc
*/
private void appendChildElements() {
appendRegattaID();
appendRegattaName();
appendCourseName();
appendCentralLatitude();
appendCentralLongitude();
appendCentralAltitude();
appedUtcOffset();
appendMagneticVariation();
}
/**
* Creates and appends regatta id element
*/
private void appendRegattaID() {
//regattaID element
Element regattaID = doc.createElement("RegattaID");
regattaID.appendChild(doc.createTextNode(Integer.toString(regattaDataSource.getRegatta().getRegattaID())));
rootElement.appendChild(regattaID);
}
/**
* Creates and appends regatta name element
*/
private void appendRegattaName() {
//regattaName element
Element regattaName = doc.createElement("RegattaName");
regattaName.appendChild(doc.createTextNode(regattaDataSource.getRegatta().getRegattaName()));
rootElement.appendChild(regattaName);
}
/**
* Creates and appends course name element
*/
private void appendCourseName() {
//courseName element
Element courseName = doc.createElement("CourseName");
courseName.appendChild(doc.createTextNode(regattaDataSource.getRegatta().getCourseName()));
rootElement.appendChild(courseName);
}
/**
* Creates and appends central latitude element
*/
private void appendCentralLatitude() {
//centralLatitude element
Element centralLat = doc.createElement("CentralLatitude");
centralLat.appendChild(doc.createTextNode(Double.toString(regattaDataSource.getRegatta().getCentralLatitude())));
rootElement.appendChild(centralLat);
}
/**
* Creates and appends central longitude element
*/
private void appendCentralLongitude() {
//centralLongitude element
Element centralLong = doc.createElement("CentralLongitude");
centralLong.appendChild(doc.createTextNode(Double.toString(regattaDataSource.getRegatta().getCentralLongitude())));
rootElement.appendChild(centralLong);
}
/**
* Creates and appends central altitude element
*/
private void appendCentralAltitude() {
//centralAltitude element
Element centralAlt = doc.createElement("CentralAltitude");
centralAlt.appendChild(doc.createTextNode(Double.toString(regattaDataSource.getRegatta().getCentralAltitude())));
rootElement.appendChild(centralAlt);
}
/**
* Creates and appends utc offset element
*/
private void appedUtcOffset() {
//utcOffset element
Element utcOffset = doc.createElement("UtcOffset");
utcOffset.appendChild(doc.createTextNode(Double.toString(regattaDataSource.getRegatta().getUtcOffset())));
rootElement.appendChild(utcOffset);
}
/**
* Creates and appends magnetic variation element
*/
private void appendMagneticVariation() {
//magneticVariation element
Element magneticVariation = doc.createElement("MagneticVariation");
magneticVariation.appendChild(doc.createTextNode(Double.toString(regattaDataSource.getRegatta().getMagneticVariation())));
rootElement.appendChild(magneticVariation);
}
}

@ -0,0 +1,14 @@
package seng302.DataInput;
import seng302.Model.Boat;
import seng302.Model.Mark;
import java.util.Map;
/**
* Created by cbt24 on 10/05/17.
*/
public interface BoatDataSource {
Map<Integer, Boat> getBoats();
Map<Integer, Mark> getMarkerBoats();
}

@ -0,0 +1,115 @@
package seng302.DataInput;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import seng302.Model.Boat;
import seng302.Model.GPSCoordinate;
import seng302.Model.Mark;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Created by cbt24 on 10/05/17.
*/
public class BoatXMLReader extends XMLReader implements BoatDataSource {
private final Map<Integer, Boat> boatMap = new HashMap<>();
private final Map<Integer, Mark> markerMap = new HashMap<>();
public BoatXMLReader(String filePath) throws ParserConfigurationException, SAXException, IOException {
this(filePath, true);
}
/**
* COnstructor for Boat 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 BoatXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException {
super(filePath);
if (read) {
read();
}
}
public void read() {
readSettings();
readShapes();
readBoats();
}
private void readBoats() {
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")) {
readBoatNode(boat);
}
}
}
/**
* Ignored data
*/
private void readShapes() {
}
/**
* Ignored data
*/
private void readSettings() {
}
private boolean isYachtNode(Node boatNode) {
return boatNode.getAttributes().getNamedItem("Type").getTextContent().toLowerCase().equals("yacht");
}
/**
* Reads the information about one boat
* Ignored values: ShapeID, StoweName, HullNum, Skipper, Type
*/
private void readBoatNode(Node boatNode) {
int sourceID = Integer.parseInt(boatNode.getAttributes().getNamedItem("SourceID").getTextContent());
String name = boatNode.getAttributes().getNamedItem("BoatName").getTextContent();
if (isYachtNode(boatNode)) readYacht(boatNode, sourceID, name);
else readMark(boatNode, sourceID, name);
}
private void readYacht(Node boatNode, int sourceID, String name) {
String shortName = boatNode.getAttributes().getNamedItem("ShortName").getTextContent();
if (exists(boatNode, "Country")) {
String country = boatNode.getAttributes().getNamedItem("Country").getTextContent();
boatMap.put(sourceID, new Boat(sourceID, name, country));
} else {
boatMap.put(sourceID, new Boat(sourceID, name, shortName));
}
}
private void readMark(Node boatNode, int sourceID, String name) {
Node nCoord = ((Element)boatNode).getElementsByTagName("GPSposition").item(0);
double x = Double.parseDouble(nCoord.getAttributes().getNamedItem("X").getTextContent());
double y = Double.parseDouble(nCoord.getAttributes().getNamedItem("Y").getTextContent());
Mark mark = new Mark(sourceID, name, new GPSCoordinate(y,x));
markerMap.put(sourceID, mark);
}
@Override
public Map<Integer, Boat> getBoats() {
return boatMap;
}
@Override
public Map<Integer, Mark> getMarkerBoats() {
return markerMap;
}
}

@ -2,10 +2,11 @@ package seng302.DataInput;
; ;
import seng302.Model.Boat; import seng302.Model.Boat;
import seng302.Model.CompoundMark;
import seng302.Model.GPSCoordinate; import seng302.Model.GPSCoordinate;
import seng302.Model.Leg; import seng302.Model.Leg;
import seng302.Model.Marker;
import java.time.ZonedDateTime;
import java.util.List; import java.util.List;
/** /**
@ -18,13 +19,13 @@ public interface RaceDataSource {
List<GPSCoordinate> getBoundary(); List<GPSCoordinate> getBoundary();
List<Marker> getMarkers(); List<CompoundMark> getCompoundMarks();
int getRaceId(); int getRaceId();
String getRaceType(); String getRaceType();
GPSCoordinate getMark(); ZonedDateTime getZonedDateTime();
GPSCoordinate getMapTopLeft(); GPSCoordinate getMapTopLeft();

@ -1,373 +1,274 @@
package seng302.DataInput; package seng302.DataInput;
import javafx.scene.paint.Color;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.Exceptions.StreamedCourseXMLException;
import seng302.Model.Boat; import seng302.Model.*;
import seng302.Model.GPSCoordinate;
import seng302.Model.Leg;
import seng302.Model.Marker;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.text.ParseException;
import java.util.List; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/** /**
* Created by fwy13 on 26/03/2017. * Created by jjg64 on 21/04/17.
*/ */
public class RaceXMLReader extends XMLReader implements RaceDataSource { public class RaceXMLReader extends XMLReader implements RaceDataSource {
private static double COORDINATEPADDING = 0.0005; private static final double COORDINATEPADDING = 0.000;
private int raceID;
private List<Boat> boats = new ArrayList<>();
private 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 List<Leg> legs = new ArrayList<>();
private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2;
private GPSCoordinate mapTopLeft, mapBottomRight; private GPSCoordinate mapTopLeft, mapBottomRight;
private List<GPSCoordinate> boundary = new ArrayList<>(); private final List<GPSCoordinate> boundary = new ArrayList<>();
private List<Marker> markers = new ArrayList<>(); private final Map<Integer,Element> compoundMarkMap = new HashMap<>();
private final Map<Integer, Boat> participants = new HashMap<>();
private final List<Leg> legs = new ArrayList<>();
private final List<CompoundMark> compoundMarks = new ArrayList<>();
private ZonedDateTime creationTimeDate;
private ZonedDateTime raceStartTime;
private int raceID;
private String raceType;
private boolean postpone;
private Map<Integer, Boat> boats;
private Map<Integer, Mark> marks;
/** /**
* Constractor for Race XML * Constructor for Streamed Race XML
*
* @param filePath path of the file * @param filePath path of the file
* @throws IOException error * @throws IOException error
* @throws SAXException error * @throws SAXException error
* @throws ParserConfigurationException error * @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/ */
public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException { public RaceXMLReader(String filePath, BoatDataSource boatData) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
this(filePath, true); this(filePath, boatData, true);
} }
/** /**
* COnstructor for Race XML * Constructor for Streamed Race XML
*
* @param filePath file path to read * @param filePath file path to read
* @param read whether or not to read and store the files straight away. * @param read whether or not to read and store the files straight away.
* @throws IOException error * @throws IOException error
* @throws SAXException error * @throws SAXException error
* @throws ParserConfigurationException error * @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/ */
public RaceXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException { public RaceXMLReader(String filePath, BoatDataSource boatData, boolean read) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
super(filePath); super(filePath);
this.boats = boatData.getBoats();
this.marks = boatData.getMarkerBoats();
if (read) { if (read) {
read(); read();
} }
} }
/** /**
* Read the files * reads
* @throws StreamedCourseXMLException error
*/ */
private void read() { private void read() throws StreamedCourseXMLException {
readRace();
readParticipants();
readCourse(); readCourse();
readID();
readLegs();
readMarkers();
readBoats();
} }
/** /**
* Read in race ID from XML object. * reads a race
*/ */
public void readID() { private void readRace() {
NodeList race = doc.getElementsByTagName("race"); DateTimeFormatter dateFormat = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
raceID = Integer.parseInt(getTextValueOfNode((Element) race.item(0), "raceId")); Element settings = (Element) doc.getElementsByTagName("Race").item(0);
} NamedNodeMap raceTimeTag = doc.getElementsByTagName("RaceStartTime").item(0).getAttributes();
/** if (raceTimeTag.getNamedItem("Time") != null) dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
* 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"));
int sourceID = Integer.parseInt(getTextValueOfNode((Element) nBoats.item(i), "sourceID"));
Boat boat = new Boat(name, velo, abbrev, sourceID);
boat.setCurrentPosition(startPt1);
if (legs.size() > 0) {
boat.setCurrentLeg(legs.get(0));
}
boats.add(boat);
}
}
/** raceID = Integer.parseInt(getTextValueOfNode(settings, "RaceID"));
* Read all the boats in the XML file raceType = getTextValueOfNode(settings, "RaceType");
*/
public void readMarkers() {
//get all boats
NodeList nMarkers = doc.getElementsByTagName("marker");
for (int i = 0; i < nMarkers.getLength(); i++) { creationTimeDate = ZonedDateTime.parse(getTextValueOfNode(settings, "CreationTimeDate"), dateFormat);
Marker marker = getMarker((Element) nMarkers.item(i));
if (marker.getName() != null) markers.add(marker);
}
}
/** if (raceTimeTag.getNamedItem("Time") != null) raceStartTime = ZonedDateTime.parse(raceTimeTag.getNamedItem("Time").getTextContent(), dateFormat);
* Read all the legs in the XML file else raceStartTime = ZonedDateTime.parse(raceTimeTag.getNamedItem("Start").getTextContent(), dateFormat);
*/
public void readLegs() { postpone = Boolean.parseBoolean(raceTimeTag.getNamedItem("Postpone").getTextContent());
//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));
}
} }
/** private void readParticipants() {
* Read courses in XML file Element nParticipants = (Element) doc.getElementsByTagName("Participants").item(0);
*/ nParticipants.getChildNodes().getLength();
public void readCourse() { for (int i = 0; i < nParticipants.getChildNodes().getLength(); i++) {
NodeList nCourse = doc.getElementsByTagName("course"); int sourceID;
Node yacht = nParticipants.getChildNodes().item(i);
NodeList nBounds = ((Element) nCourse.item(0)).getElementsByTagName("boundaries"); if (yacht.getNodeName().equals("Yacht")) {
nBounds = ((Element) nBounds.item(0)).getElementsByTagName("coordinate"); if (exists(yacht, "SourceID")) {
int maxLatitudeIndex = 0; sourceID = Integer.parseInt(yacht.getAttributes().getNamedItem("SourceID").getTextContent());
double maxLatitude = -Double.MIN_VALUE; participants.put(sourceID, boats.get(sourceID));
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;
} }
maxLatitude += COORDINATEPADDING;
minLatitude -= COORDINATEPADDING;
maxLongitude += COORDINATEPADDING;
minLongitude -= COORDINATEPADDING;
//now create map boundaries
//top left canvas point is min logitude, 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 * reads a course
* * @throws StreamedCourseXMLException error
* @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) { private void readCourse() throws StreamedCourseXMLException {
return getMarker(start, startIndex, 0); readCompoundMarks();
readCompoundMarkSequence();
readCourseLimit();
} }
/** /**
* gets a marker from the XML file * Indexes CompoundMark elements by their ID for use in generating the course, and populates list of Markers.
* * @see CompoundMark
* @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) { private void readCompoundMarks() throws StreamedCourseXMLException {
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("marker"); Element nCourse = (Element) doc.getElementsByTagName("Course").item(0);
Element marker = (Element) nodeList.item(nodeIndex); for(int i = 0; i < nCourse.getChildNodes().getLength(); i++) {
return getMarker(marker); Node compoundMark = nCourse.getChildNodes().item(i);
if(compoundMark.getNodeName().equals("CompoundMark")) {
int compoundMarkID = getCompoundMarkID((Element) compoundMark);
compoundMarkMap.put(compoundMarkID, (Element)compoundMark);
compoundMarks.add(getCompoundMark(compoundMarkID));
}
}
} }
/** /**
* gets a changes a marker to GPS coordinates into a marker * Generates a CompoundMark from the CompoundMark element with given ID.
* * @param compoundMarkID index of required CompoundMark element
* @param markerNode marker to turn into coordinates * @return generated CompoundMark
* @return * @throws StreamedCourseXMLException if CompoundMark element contains unhandled number of compoundMarks
* @see CompoundMark
*/ */
private Marker getMarker(Element markerNode) { private CompoundMark getCompoundMark(int compoundMarkID) throws StreamedCourseXMLException {
Element compoundMark = compoundMarkMap.get(compoundMarkID);
NodeList nCoordinates = markerNode.getElementsByTagName("coordinate"); NodeList nMarks = compoundMark.getElementsByTagName("Mark");
CompoundMark marker;
GPSCoordinate side1 = getCoordinates((Element) nCoordinates.item(0));
GPSCoordinate side2; switch(nMarks.getLength()) {
if (nCoordinates.getLength() > 1) { case 1: marker = new CompoundMark(getMark((Element)nMarks.item(0)));
side2 = getCoordinates((Element) nCoordinates.item(1)); break;
} else { case 2: marker = new CompoundMark(getMark((Element)nMarks.item(0)), getMark((Element)nMarks.item(1))); break;
side2 = side1; default: throw new StreamedCourseXMLException();
} }
NodeList name = markerNode.getElementsByTagName("name");
return name.getLength() == 1 ? new Marker(getTextValueOfNode((Element) markerNode, "name"), side1, side2) : new Marker(side1, side2); return marker;
} }
/** private Mark getMark(Element mark) {
* gets a coordinates from the XML file int sourceID = Integer.parseInt(mark.getAttribute("SourceID"));
* return marks.get(sourceID);
* @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 * Reads "compoundMarkID" attribute of CompoundMark or Corner element
* * @param element with "compoundMarkID" attribute
* @param start base nodelist this should be the tag that contains <coordinate></coordinate> * @return value of "compoundMarkID" attribute
* @param startIndex the index the tag containing the coordinate should be in
* @return
*/ */
private GPSCoordinate getCoordinates(NodeList start, int startIndex) { private int getCompoundMarkID(Element element) {
return getCoordinates(start, startIndex, 0); return Integer.parseInt(element.getAttribute("CompoundMarkID"));
} }
/** /**
* gets a coordinates from the XML file * Reads "name" attribute of CompoundMark element with corresponding CompoundMarkID
* * @param compoundMarkID unique ID for CompoundMark element
* @param start base nodelist this should be the tag that contains <coordinate></coordinate> * @return value of "name" attribute
* @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) { private String getCompoundMarkName(int compoundMarkID) {
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("coordinate"); return compoundMarkMap.get(compoundMarkID).getAttribute("Name");
Element coord = (Element) nodeList.item(nodeIndex);
return getCoordinates(coord);
} }
/** /**
* Returns the coordinate TODO raise exception that runs when the XML is formatted wrongly. * Populates list of legs given CompoundMarkSequence element and referenced CompoundMark elements.
* * @throws StreamedCourseXMLException if compoundMarks cannot be resolved from CompoundMark
* @param coordNode
* @return
*/ */
private GPSCoordinate getCoordinates(Element coordNode) { private void readCompoundMarkSequence() throws StreamedCourseXMLException {
Element nCompoundMarkSequence = (Element) doc.getElementsByTagName("CompoundMarkSequence").item(0);
double startLat = Double.parseDouble(getTextValueOfNode(coordNode, "latitude")); NodeList nCorners = nCompoundMarkSequence.getElementsByTagName("Corner");
double startLong = Double.parseDouble(getTextValueOfNode(coordNode, "longitude")); Element markXML = (Element)nCorners.item(0);
return new GPSCoordinate(startLat, startLong); CompoundMark lastCompoundMark = getCompoundMark(getCompoundMarkID(markXML));
} String legName = getCompoundMarkName(getCompoundMarkID(markXML));
for(int i = 1; i < nCorners.getLength(); i++) {
public List<Boat> getBoats() { markXML = (Element)nCorners.item(i);
return boats; CompoundMark currentCompoundMark = getCompoundMark(getCompoundMarkID(markXML));
} legs.add(new Leg(legName, lastCompoundMark, currentCompoundMark, i-1));
lastCompoundMark = currentCompoundMark;
public List<Leg> getLegs() { legName = getCompoundMarkName(getCompoundMarkID(markXML));
return legs; }
}
public GPSCoordinate getMark() {
return mark;
} }
public GPSCoordinate getStartPt1() { private void readCourseLimit() {
return startPt1; Element nCourseLimit = (Element) doc.getElementsByTagName("CourseLimit").item(0);
} for(int i = 0; i < nCourseLimit.getChildNodes().getLength(); i++) {
Node limit = nCourseLimit.getChildNodes().item(i);
if (limit.getNodeName().equals("Limit")) {
double lat = Double.parseDouble(limit.getAttributes().getNamedItem("Lat").getTextContent());
double lon = Double.parseDouble(limit.getAttributes().getNamedItem("Lon").getTextContent());
boundary.add(new GPSCoordinate(lat, lon));
}
}
public GPSCoordinate getStartPt2() { double maxLatitude = boundary.stream().max(Comparator.comparingDouble(GPSCoordinate::getLatitude)).get().getLatitude() + COORDINATEPADDING;
return startPt2; double maxLongitude = boundary.stream().max(Comparator.comparingDouble(GPSCoordinate::getLongitude)).get().getLongitude() + COORDINATEPADDING;
} double minLatitude = boundary.stream().min(Comparator.comparingDouble(GPSCoordinate::getLatitude)).get().getLatitude() + COORDINATEPADDING;
double minLongitude = boundary.stream().min(Comparator.comparingDouble(GPSCoordinate::getLongitude)).get().getLongitude() + COORDINATEPADDING;
public GPSCoordinate getFinishPt1() { mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
return finishPt1; mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude);
} }
public GPSCoordinate getFinishPt2() { public List<GPSCoordinate> getBoundary() {
return finishPt2; return boundary;
} }
public GPSCoordinate getLeewardPt1() { public GPSCoordinate getMapTopLeft() {
return leewardPt1; return mapTopLeft;
} }
public GPSCoordinate getLeewardPt2() { public GPSCoordinate getMapBottomRight() {
return leewardPt2; return mapBottomRight;
} }
public GPSCoordinate getWindwardPt1() { public List<Leg> getLegs() {
return windwardPt1; return legs;
} }
public GPSCoordinate getWindwardPt2() { public List<CompoundMark> getCompoundMarks() { return compoundMarks; }
return windwardPt2;
}
public List<GPSCoordinate> getBoundary() { public Double getPadding() {
return boundary; return COORDINATEPADDING;
} }
public GPSCoordinate getMapTopLeft() { public ZonedDateTime getCreationTimeDate() {
return mapTopLeft; return creationTimeDate;
} }
public GPSCoordinate getMapBottomRight() { public ZonedDateTime getZonedDateTime() {
return mapBottomRight; return raceStartTime;
} }
public int getRaceId() { public int getRaceId() {
return raceID; return raceID;
} }
public List<Marker> getMarkers() { public String getRaceType() {
return markers; return raceType;
} }
public String getRaceType() { public boolean isPostpone() {
return "FLEET"; return postpone;
}
public List<Boat> getBoats() {
return new ArrayList<>(participants.values());
} }
} }

@ -1,11 +0,0 @@
package seng302.DataInput;
import seng302.Model.Regatta;
/**
* Created by zwu18 on 25/04/17.
*/
public interface RegattaDataSource {
Regatta getRegatta();
}

@ -1,75 +0,0 @@
package seng302.DataInput;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import seng302.Model.Regatta;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
/**
* Created by jjg64 on 19/04/17.
*/
public class RegattaXMLReader extends XMLReader implements RegattaDataSource {
private Regatta regatta;
/**
* Constructor for Regatta XML
*
* @param filePath path of the file
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
*/
public RegattaXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException {
this(filePath, true);
}
/**
* Constructor for Regatta 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 RegattaXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException {
super(filePath);
if (read) {
read();
}
}
/**
* Read the XML
*/
private void read() {
NodeList attributeConfig = doc.getElementsByTagName("RegattaConfig");
Element attributes = (Element) attributeConfig.item(0);
makeRegatta(attributes);
}
/**
* Create new regatta
* @param attributes
*/
private void makeRegatta(Element attributes) {
int regattaID = Integer.parseInt(getTextValueOfNode(attributes, "RegattaID"));
String regattaName = getTextValueOfNode(attributes, "RegattaName");
String courseName = getTextValueOfNode(attributes, "CourseName");
double centralLatitude = Double.parseDouble(getTextValueOfNode(attributes, "CentralLatitude"));
double centralLongitude = Double.parseDouble(getTextValueOfNode(attributes, "CentralLongitude"));
double centralAltitude = Double.parseDouble(getTextValueOfNode(attributes, "CentralAltitude"));
float utcOffset = Float.parseFloat(getTextValueOfNode(attributes, "UtcOffset"));
float magneticVariation = Float.parseFloat(getTextValueOfNode(attributes, "MagneticVariation"));
regatta = new Regatta(regattaID, regattaName, courseName, centralLatitude, centralLongitude, centralAltitude, utcOffset, magneticVariation);
}
public Regatta getRegatta() {
return regatta;
}
}

@ -2,6 +2,8 @@ package seng302.DataInput;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
@ -9,6 +11,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.StringReader;
/** /**
* Created by fwy13 on 26/03/2017. * Created by fwy13 on 26/03/2017.
@ -25,13 +28,26 @@ public abstract class XMLReader {
* @throws SAXException * @throws SAXException
*/ */
public XMLReader(String filePath) throws ParserConfigurationException, IOException, SAXException { public XMLReader(String filePath) throws ParserConfigurationException, IOException, SAXException {
InputStream fXmlFile = getClass().getClassLoader().getResourceAsStream(filePath);
InputSource fXmlFile;
if (filePath.contains("<")) {
fXmlFile = new InputSource();
fXmlFile.setCharacterStream(new StringReader(filePath));
} else {
fXmlFile = new InputSource(getClass().getClassLoader().getResourceAsStream(filePath));
}
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(fXmlFile); doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize(); doc.getDocumentElement().normalize();
} }
public XMLReader(String xmlFile, Boolean isWholeFile) {
}
/** /**
* Return Document data of the read-in XML * Return Document data of the read-in XML
* @return XML document * @return XML document
@ -60,4 +76,8 @@ public abstract class XMLReader {
return n.getAttribute(attr); return n.getAttribute(attr);
} }
protected boolean exists(Node node, String attribute) {
return node.getAttributes().getNamedItem(attribute) != null;
}
} }

@ -1,17 +0,0 @@
package seng302.Exceptions;
/**
* Created by f123 on 25-Apr-17.
*/
/**
* An exception thrown when a Regatta.xml message cannot be generated and sent.
*/
public class InvalidRegattaDataException extends RuntimeException {
public InvalidRegattaDataException() {
}
public InvalidRegattaDataException(String message) {
super(message);
}
}

@ -0,0 +1,7 @@
package seng302.Exceptions;
/**
* Created by cbt24 on 25/04/17.
*/
public class StreamedCourseXMLException extends Throwable {
}

@ -10,7 +10,7 @@ public class Boat {
private String name; private String name;
private double velocity; private double velocity;
private double scaledVelocity; private double scaledVelocity;
private String abbrev; private String country;
private int sourceID; private int sourceID;
private Leg currentLeg; private Leg currentLeg;
private double distanceTravelledInLeg; private double distanceTravelledInLeg;
@ -22,14 +22,12 @@ public class Boat {
/** /**
* Boat initialiser which keeps all of the information of the boat. * Boat initialiser which keeps all of the information of the boat.
* *
* @param name Name of the Boat.
* @param velocity Speed in m/s that the boat travels at.
* @param abbrev nam abbreviation
* @param sourceID id of boat * @param sourceID id of boat
* @param name Name of the Boat.
* @param country nam abbreviation
*/ */
public Boat(String name, double velocity, String abbrev, int sourceID) { public Boat(int sourceID, String name, String country) {
this.velocity = velocity; this.country = this.country;
this.abbrev = abbrev;
this.name = name; this.name = name;
this.sourceID = sourceID; this.sourceID = sourceID;
} }
@ -42,8 +40,8 @@ public class Boat {
public double calculateAzimuth() { public double calculateAzimuth() {
GeodeticCalculator calc = new GeodeticCalculator(); GeodeticCalculator calc = new GeodeticCalculator();
GPSCoordinate start = currentLeg.getStartMarker().getAverageGPSCoordinate(); GPSCoordinate start = currentLeg.getStartCompoundMark().getAverageGPSCoordinate();
GPSCoordinate end = currentLeg.getEndMarker().getAverageGPSCoordinate(); GPSCoordinate end = currentLeg.getEndCompoundMark().getAverageGPSCoordinate();
calc.setStartingGeographicPoint(start.getLongitude(), start.getLatitude()); calc.setStartingGeographicPoint(start.getLongitude(), start.getLatitude());
calc.setDestinationGeographicPoint(end.getLongitude(), end.getLatitude()); calc.setDestinationGeographicPoint(end.getLongitude(), end.getLatitude());
@ -90,12 +88,12 @@ public class Boat {
this.scaledVelocity = scaledVelocity; this.scaledVelocity = scaledVelocity;
} }
public String getAbbrev() { public String getCountry() {
return abbrev; return country;
} }
public void setAbbrev(String abbrev) { public void setCountry(String country) {
this.abbrev = abbrev; this.country = country;
} }
public int getSourceID() { public int getSourceID() {

@ -0,0 +1,61 @@
package seng302.Model;
import org.geotools.referencing.GeodeticCalculator;
import java.awt.geom.Point2D;
/**
* Created by esa46 on 29/03/17.
*/
public class CompoundMark extends Marker{
private GPSCoordinate averageGPSCoordinate;
private Mark mark1;
private Mark mark2 = null;
public CompoundMark(Mark mark1) {
super(mark1.getPosition());
this.mark1 = mark1;
this.averageGPSCoordinate = calculateAverage();
}
public CompoundMark(Mark mark1, Mark mark2) {
super(mark1.getPosition(), mark2.getPosition());
this.mark1 = mark1;
this.mark2 = mark2;
this.averageGPSCoordinate = calculateAverage();
}
public Mark getMark1Source() { return mark1; }
public Mark getMark2Source() { return mark2; }
public GPSCoordinate getMark1() {
return mark1.getPosition();
}
public GPSCoordinate getMark2() {
return mark2.getPosition();
}
public GPSCoordinate getAverageGPSCoordinate() {
return averageGPSCoordinate;
}
private GPSCoordinate calculateAverage() {
if(mark2 != null) {
GeodeticCalculator calc = new GeodeticCalculator();
calc.setStartingGeographicPoint(mark1.getPosition().getLongitude(), mark1.getPosition().getLatitude());
calc.setDestinationGeographicPoint(mark2.getPosition().getLongitude(), mark2.getPosition().getLatitude());
double azimuth = calc.getAzimuth();
double distance = calc.getOrthodromicDistance();
GeodeticCalculator middleCalc = new GeodeticCalculator();
middleCalc.setStartingGeographicPoint(mark1.getPosition().getLongitude(), mark1.getPosition().getLatitude());
middleCalc.setDirection(azimuth, distance / 2);
Point2D middlePoint = middleCalc.getDestinationGeographicPoint();
return new GPSCoordinate(middlePoint.getY(), middlePoint.getX());
} else return mark1.getPosition();
}
}

@ -1,16 +1,16 @@
package seng302.Model; package seng302.Model;
import seng302.Data.BoatData; import org.xml.sax.SAXException;
import seng302.Data.RaceData; import seng302.DataInput.*;
import seng302.Data.RegattaData; import seng302.Exceptions.StreamedCourseXMLException;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RegattaDataSource;
import seng302.Exceptions.InvalidBoatDataException;
import seng302.Exceptions.InvalidRaceDataException;
import seng302.Exceptions.InvalidRegattaDataException;
import seng302.MockOutput; import seng302.MockOutput;
import seng302.Networking.Messages.Enums.MessageType;
import java.io.IOException; import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.text.ParseException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/** /**
@ -18,14 +18,16 @@ import java.io.IOException;
*/ */
public class Event { public class Event {
RaceDataSource raceDataSource; String raceXML;
RegattaDataSource regattaDataSource; String regattaXML;
String boatXML;
MockOutput mockOutput; MockOutput mockOutput;
public Event(RaceDataSource raceData, RegattaDataSource regattaData) { public Event(String raceXML, String regattaXML, String boatXML) {
this.raceDataSource = raceData;
this.regattaDataSource = regattaData; this.raceXML = getRaceXMLAtCurrentTime(raceXML);
this.boatXML = boatXML;
this.regattaXML = regattaXML;
try { try {
mockOutput = new MockOutput(); mockOutput = new MockOutput();
new Thread(mockOutput).start(); new Thread(mockOutput).start();
@ -35,59 +37,44 @@ public class Event {
} }
/** /**
* Send the initial race data and then begin race simulation * Sends the initial race data and then begins race simulation
*/ */
public void start() { public void start() {
System.out.println("Sending Regatta"); try {
sendRegattaData(); sendXMLs();
System.out.println("Sending Race"); Race newRace = new Race(new RaceXMLReader(this.raceXML, new BoatXMLReader(boatXML)), mockOutput);
sendRaceData(); new Thread((newRace)).start();
System.out.println("Sending Boat");
sendBoatData();
int scaleFactor = 5;//TEMP - was 15. } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
Race newRace = new Race(raceDataSource, scaleFactor, mockOutput); e.printStackTrace();
new Thread((newRace)).start(); }
} }
/** /**
* Send XML string of initial regatta data to the visualiser * Sends out each xml string, via the mock output
* @throws InvalidRegattaDataException Invalid regatta
*/ */
public void sendRegattaData() throws InvalidRegattaDataException { private void sendXMLs() {
System.setOut(System.out); mockOutput.setRegattaXml(regattaXML);
RegattaData regattaData = new RegattaData(regattaDataSource); mockOutput.parseXMLString(regattaXML, MessageType.XMLMESSAGE.getValue());
String xmlString = regattaData.createXML();
mockOutput.setRegattaXml(xmlString);
mockOutput.parseXMLString(xmlString, 26);
} mockOutput.setRaceXml(raceXML);
mockOutput.parseXMLString(raceXML, MessageType.XMLMESSAGE.getValue());
/** mockOutput.setBoatsXml(boatXML);
* Send XML string of initial race data to the visualiser mockOutput.parseXMLString(boatXML, MessageType.XMLMESSAGE.getValue());
* @throws InvalidRaceDataException Invalid race
*/
public void sendRaceData() throws InvalidRaceDataException {
RaceData raceData = new RaceData(raceDataSource);
//Serialize race data to an XML as a string.
String xmlString = raceData.createXML();
mockOutput.setRaceXml(xmlString);
mockOutput.parseXMLString(xmlString, 26);
} }
/** /**
* Send XML string of initial boat data to the visualiser * Sets the xml description of the race to show the race was created now, and starts in 3 minutes
* @throws InvalidBoatDataException Invalid boat * @param raceXML
* @return String containing edited xml
*/ */
public void sendBoatData() throws InvalidBoatDataException { private String getRaceXMLAtCurrentTime(String raceXML) {
BoatData boatData = new BoatData(raceDataSource.getBoats()); DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
//Serialize race data to an XML as a string. ZonedDateTime creationTime = ZonedDateTime.now();
String xmlString = boatData.createXML(); return raceXML.replace("CREATION_TIME", dateFormat.format(creationTime))
mockOutput.setBoatsXml(xmlString); .replace("START_TIME", dateFormat.format(creationTime.plusMinutes(3)));
mockOutput.parseXMLString(xmlString, 26);
} }
} }

@ -10,8 +10,8 @@ import seng302.Constants;
public class Leg { public class Leg {
private String name; //nautical miles private String name; //nautical miles
private double distance; private double distance;
private Marker startMarker; private Marker startCompoundMark;
private Marker endMarker; private Marker endCompoundMark;
private int legNumber; private int legNumber;
/** /**
@ -24,8 +24,8 @@ public class Leg {
*/ */
public Leg(String name, Marker start, Marker end, int number) { public Leg(String name, Marker start, Marker end, int number) {
this.name = name; this.name = name;
this.startMarker = start; this.startCompoundMark = start;
this.endMarker = end; this.endCompoundMark = end;
this.legNumber = number; this.legNumber = number;
calculateDistance(); calculateDistance();
} }
@ -69,20 +69,20 @@ public class Leg {
} }
public Marker getStartMarker() { public Marker getStartCompoundMark() {
return startMarker; return startCompoundMark;
} }
public void setStartMarker(Marker startMarker) { public void setStartCompoundMark(Marker startCompoundMark) {
this.startMarker = startMarker; this.startCompoundMark = startCompoundMark;
} }
public Marker getEndMarker() { public Marker getEndCompoundMark() {
return endMarker; return endCompoundMark;
} }
public void setEndMarker(Marker endMarker) { public void setEndCompoundMark(Marker endCompoundMark) {
this.endMarker = endMarker; this.endCompoundMark = endCompoundMark;
} }
/** /**
@ -92,8 +92,8 @@ public class Leg {
GeodeticCalculator calc = new GeodeticCalculator(); GeodeticCalculator calc = new GeodeticCalculator();
//Load start and end of leg //Load start and end of leg
GPSCoordinate startMarker = this.startMarker.getAverageGPSCoordinate(); GPSCoordinate startMarker = this.startCompoundMark.getAverageGPSCoordinate();
GPSCoordinate endMarker = this.endMarker.getAverageGPSCoordinate(); GPSCoordinate endMarker = this.endCompoundMark.getAverageGPSCoordinate();
calc.setStartingGeographicPoint(startMarker.getLongitude(), startMarker.getLatitude()); calc.setStartingGeographicPoint(startMarker.getLongitude(), startMarker.getLatitude());
calc.setDestinationGeographicPoint(endMarker.getLongitude(), endMarker.getLatitude()); calc.setDestinationGeographicPoint(endMarker.getLongitude(), endMarker.getLatitude());
this.distance = calc.getOrthodromicDistance() / Constants.NMToMetersConversion; this.distance = calc.getOrthodromicDistance() / Constants.NMToMetersConversion;

@ -0,0 +1,28 @@
package seng302.Model;
/**
* Created by cbt24 on 10/05/17.
*/
public class Mark {
private int sourceID;
private String name;
private GPSCoordinate position;
public Mark(int sourceID, String name, GPSCoordinate position) {
this.sourceID = sourceID;
this.name = name;
this.position = position;
}
public String getName() {
return name;
}
public int getSourceID() {
return sourceID;
}
public GPSCoordinate getPosition() {
return position;
}
}

@ -71,4 +71,4 @@ public class Marker {
} }
} }

@ -1,12 +1,10 @@
package seng302.Model; package seng302.Model;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import org.geotools.referencing.GeodeticCalculator; import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants; import seng302.Constants;
import seng302.DataInput.RaceDataSource; import seng302.DataInput.RaceDataSource;
import seng302.MockOutput; import seng302.MockOutput;
@ -19,81 +17,31 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
/** /**
* Parent class for races * Parent class for races
* Created by fwy13 on 3/03/17. * Created by fwy13 on 3/03/17.
*/ */
public class Race implements Runnable { public class Race implements Runnable {
//protected Boat[] startingBoats;
protected ObservableList<Boat> startingBoats; protected ObservableList<Boat> startingBoats;
protected ObservableList<CompoundMark> compoundMarks;
protected List<Leg> legs; protected List<Leg> legs;
protected int boatsFinished = 0; protected int boatsFinished = 0;
protected long totalTimeElapsed; protected long totalTimeElapsed;
protected int scaleFactor=25; protected int scaleFactor = 3;
protected int PRERACE_TIME = 180000; //time in milliseconds to pause during pre-race. At the moment, 3 minutes
private long startTime; private long startTime;
protected boolean countdownFinish = false;
protected boolean runRace = true;
private int lastFPS = 20;
private int raceId; private int raceId;
private int dnfChance = 0; //percentage chance a boat fails at each checkpoint private int dnfChance = 0; //percentage chance a boat fails at each checkpoint
private MockOutput mockOutput; private MockOutput mockOutput;
private static int boatOffset = 0;
private int finished = 0;
public Race(RaceDataSource raceData, MockOutput mockOutput) {
/** this.startingBoats = FXCollections.observableArrayList(raceData.getBoats());
* Initailiser for Race this.legs = raceData.getLegs();
* this.compoundMarks = FXCollections.observableArrayList(raceData.getCompoundMarks());
* @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 scaleFactor for race
*/
public Race(List<Boat> boats, List<Leg> legs, int raceID, int scaleFactor, MockOutput mockOutput) {
this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size())); this.legs.add(new Leg("Finish", this.legs.size()));
this.raceId = raceID; this.raceId = raceData.getRaceId();
this.scaleFactor = scaleFactor;
this.mockOutput = mockOutput; this.mockOutput = mockOutput;
this.startTime = System.currentTimeMillis() + (Constants.PRE_RACE_WAIT_TIME / this.scaleFactor);
//TODO refactor
this.startTime = System.currentTimeMillis() + (this.PRERACE_TIME / this.scaleFactor);
if (startingBoats != null && startingBoats.size() > 0) {
initialiseBoats();
}
}
public Race(RaceDataSource raceData, int scaleFactor, MockOutput mockOutput) {
this(raceData.getBoats(), raceData.getLegs(), raceData.getRaceId(), scaleFactor, mockOutput);
}
/**
* 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 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);
//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());
} }
/** /**
@ -101,165 +49,142 @@ public class Race implements Runnable {
*/ */
public void run() { public void run() {
initialiseBoats(); initialiseBoats();
countdownTimer(); countdownTimer.start();
} }
/** /**
* Starts the heartbeat timer, which sends a heartbeat message every so often (i.e., 5 seconds). * Parse the marker boats through mock output
*/
/**
* Countdown timer until race starts. Use PRERACE_TIME to set countdown duration.
*/ */
protected void countdownTimer() { public void parseMarks() {
AnimationTimer timer = new AnimationTimer() { for (CompoundMark mark : compoundMarks){
long currentTime = System.currentTimeMillis(); mockOutput.parseBoatLocation(mark.getMark1Source().getSourceID(), mark.getMark1().getLatitude(), mark.getMark1().getLongitude(),0,0);
//long startTime = currentTime + (PRERACE_TIME / scaleFactor); if (mark.getMark2Source()!=null){
//long minutes; mockOutput.parseBoatLocation(mark.getMark2Source().getSourceID(), mark.getMark2().getLatitude(), mark.getMark2().getLongitude(),0,0);
//long hours;
long timeLeft;
@Override
public void handle(long arg0) {
timeLeft = startTime - currentTime;
ArrayList<BoatStatus> boatStatuses = new ArrayList<>();
//For each boat, we update it's position, and generate a BoatLocationMessage.
for (int i = 0; i < startingBoats.size(); i++) {
Boat boat = startingBoats.get((i + boatOffset) % startingBoats.size());
if (boat != null) {
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), 0);
boatStatuses.add(new BoatStatus(boat.getSourceID(),
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
}
}
boatOffset = (boatOffset + 1) % (startingBoats.size());
if (timeLeft <= 60000/scaleFactor && timeLeft > 0) {
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 2, startTime, 0, 2300, 1, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
}
else if (timeLeft <= 0) {
countdownFinish = true;
if (runRace) {
simulateRace();
}
stop();
}
else {
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 1, startTime, 0, 2300,1, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
}
currentTime = System.currentTimeMillis();
} }
}; }
timer.start();
//countdownFinish = true;
} }
/** /**
* Starts the Race Simulation, playing the race start to finish with the timescale. * Countdown timer until race starts.
* 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"); protected AnimationTimer countdownTimer = new AnimationTimer() {
long currentTime = System.currentTimeMillis();
long timeLeft;
@Override
public void handle(long arg0) {
timeLeft = startTime - currentTime;
if (timeLeft <= 0) {
System.setProperty("javafx.animation.fullspeed", "true");
raceTimer.start();
stop();
}
ArrayList<BoatStatus> boatStatuses = new ArrayList<>();
for (Boat boat : startingBoats) {
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(),
boat.getCurrentPosition().getLongitude(), boat.getHeading(), 0);
boatStatuses.add(new BoatStatus(boat.getSourceID(), BoatStatusEnum.PRESTART, 0));
}
parseMarks();
int raceStatusNumber = timeLeft <= 60000 / scaleFactor && timeLeft > 0? 2 : 1;
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, raceStatusNumber, startTime, 0, 2300, 1, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
for (Boat boat : startingBoats) { currentTime = System.currentTimeMillis();
boat.setStarted(true);
} }
};
new AnimationTimer() { private AnimationTimer raceTimer = new AnimationTimer() {
//Start time of loop. //Start time of loop.
long timeRaceStarted = System.currentTimeMillis(); long timeRaceStarted = System.currentTimeMillis();
int boatOffset = 0;
@Override
public void handle(long arg0) { @Override
if (boatsFinished < startingBoats.size()) { public void handle(long arg0) {
//Get the current time. if (boatsFinished < startingBoats.size()) {
long currentTime = System.currentTimeMillis(); //Get the current time.
//Update the total elapsed time. long currentTime = System.currentTimeMillis();
totalTimeElapsed = currentTime - timeRaceStarted; //Update the total elapsed time.
ArrayList<BoatStatus> boatStatuses = new ArrayList<BoatStatus>(); totalTimeElapsed = currentTime - timeRaceStarted;
finished = 0; ArrayList<BoatStatus> boatStatuses = new ArrayList<>();
//For each boat, we update it's position, and generate a BoatLocationMessage. //For each boat, we update its position, and generate a BoatLocationMessage.
for (int i = 0; i < startingBoats.size(); i++) { for (int i = 0; i < startingBoats.size(); i++) {
Boat boat = startingBoats.get((i + boatOffset) % startingBoats.size()); Boat boat = startingBoats.get((i + boatOffset) % startingBoats.size());
if (boat != null) { if (boat != null) {
//Update position. //Update position.
if (boat.getTimeFinished() < 0) { if (boat.getTimeFinished() < 0) {
updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS)); updatePosition(boat, 15);
checkPosition(boat, totalTimeElapsed); checkPosition(boat, totalTimeElapsed);
} }
if (boat.getTimeFinished() > 0) { if (boat.getTimeFinished() > 0) {
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity()); mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity());
boatStatuses.add(new BoatStatus(boat.getSourceID(), BoatStatusEnum.FINISHED, boat.getCurrentLeg().getLegNumber())); boatStatuses.add(new BoatStatus(boat.getSourceID(), BoatStatusEnum.FINISHED, boat.getCurrentLeg().getLegNumber()));
finished++;
} else {
mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity());
boatStatuses.add(new BoatStatus(boat.getSourceID(),
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
}
if (startingBoats.size()==finished){
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 4, startTime, 0, 2300, 2, boatStatuses);//TODO FIX the second currentTime is a placeholder! Also, replace magic values.
mockOutput.parseRaceStatus(raceStatus);
}
} else { } else {
stop(); mockOutput.parseBoatLocation(boat.getSourceID(), boat.getCurrentPosition().getLatitude(), boat.getCurrentPosition().getLongitude(), boat.getHeading(), boat.getVelocity());
boatStatuses.add(new BoatStatus(boat.getSourceID(),
boat.getCurrentLeg().getLegNumber() >= 0 ? BoatStatusEnum.RACING : BoatStatusEnum.DNF, boat.getCurrentLeg().getLegNumber()));
} }
} else {
stop();
} }
boatOffset = (boatOffset + 1) % (startingBoats.size());
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 3, startTime, 0, 2300, 2, boatStatuses);//TODO FIX the second currentTime is a placeholder! Also, replace magic values.
mockOutput.parseRaceStatus(raceStatus);
} }
parseMarks();
boatOffset = (boatOffset + 1) % (startingBoats.size());
RaceStatus raceStatus = new RaceStatus(System.currentTimeMillis(), raceId, 3, startTime, 0, 2300, 2, boatStatuses);
mockOutput.parseRaceStatus(raceStatus);
} }
}.start(); }
} };
public void initialiseBoats() { public void initialiseBoats() {
Leg officialStart = legs.get(0); Leg officialStart = legs.get(0);
String name = officialStart.getName(); String name = officialStart.getName();
Marker endMarker = officialStart.getEndMarker(); Marker endMark = officialStart.getEndCompoundMark();
ArrayList<GPSCoordinate> startingPositions = getSpreadStartingPositions();
ArrayList<Marker> startMarkers = getSpreadStartingPositions();
for (int i = 0; i < startingBoats.size(); i++) { for (int i = 0; i < startingBoats.size(); i++) {
Boat boat = startingBoats.get(i); Boat boat = startingBoats.get(i);
if (boat != null) { if (boat != null) {
Leg newLeg = new Leg(name, new Marker(startingPositions.get(i)), endMark, 0);
boat.setCurrentLeg(newLeg);
boat.setVelocity(Constants.TEST_VELOCITIES[i]);
boat.setScaledVelocity(boat.getVelocity() * scaleFactor); boat.setScaledVelocity(boat.getVelocity() * scaleFactor);
Leg startLeg = new Leg(name, 0); boat.setCurrentPosition(startingPositions.get(i));
boat.setCurrentPosition(startMarkers.get(i).getAverageGPSCoordinate());
startLeg.setStartMarker(startMarkers.get(i));
startLeg.setEndMarker(endMarker);
startLeg.calculateDistance();
boat.setCurrentLeg(startLeg);
boat.setHeading(boat.calculateHeading()); boat.setHeading(boat.calculateHeading());
} }
} }
} }
/** /**
* Creates a list of starting positions for the different boats, so they do not appear cramped at the start line * Creates a list of starting positions for the different boats, so they do not appear cramped at the start line
* *
* @return list of starting positions * @return list of starting positions
*/ */
public ArrayList<Marker> getSpreadStartingPositions() { public ArrayList<GPSCoordinate> getSpreadStartingPositions() {
int nBoats = startingBoats.size(); int nBoats = startingBoats.size();
Marker marker = legs.get(0).getStartMarker(); Marker compoundMark = legs.get(0).getStartCompoundMark();
GeodeticCalculator initialCalc = new GeodeticCalculator(); GeodeticCalculator initialCalc = new GeodeticCalculator();
initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); initialCalc.setStartingGeographicPoint(compoundMark.getMark1().getLongitude(), compoundMark.getMark1().getLatitude());
initialCalc.setDestinationGeographicPoint(marker.getMark2().getLongitude(), marker.getMark2().getLatitude()); initialCalc.setDestinationGeographicPoint(compoundMark.getMark2().getLongitude(), compoundMark.getMark2().getLatitude());
double azimuth = initialCalc.getAzimuth(); double azimuth = initialCalc.getAzimuth();
double distanceBetweenMarkers = initialCalc.getOrthodromicDistance(); double distanceBetweenMarkers = initialCalc.getOrthodromicDistance();
double distanceBetweenBoats = distanceBetweenMarkers / (nBoats + 1); double distanceBetweenBoats = distanceBetweenMarkers / (nBoats + 1);
GeodeticCalculator positionCalc = new GeodeticCalculator(); GeodeticCalculator positionCalc = new GeodeticCalculator();
positionCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); positionCalc.setStartingGeographicPoint(compoundMark.getMark1().getLongitude(), compoundMark.getMark1().getLatitude());
ArrayList<Marker> positions = new ArrayList<>(); ArrayList<GPSCoordinate> positions = new ArrayList<>();
for (int i = 0; i < nBoats; i++) { for (int i = 0; i < nBoats; i++) {
positionCalc.setDirection(azimuth, distanceBetweenBoats); positionCalc.setDirection(azimuth, distanceBetweenBoats);
Point2D position = positionCalc.getDestinationGeographicPoint(); Point2D position = positionCalc.getDestinationGeographicPoint();
positions.add(new Marker(new GPSCoordinate(position.getY(), position.getX()))); positions.add(new GPSCoordinate(position.getY(), position.getX()));
positionCalc = new GeodeticCalculator(); positionCalc = new GeodeticCalculator();
positionCalc.setStartingGeographicPoint(position); positionCalc.setStartingGeographicPoint(position);
@ -268,19 +193,26 @@ public class Race implements Runnable {
} }
/** /**
* Sets the chance each boat has of failing at a gate or marker * Calculates the boats next GPS position based on its distance travelled and heading
* *
* @param chance percentage chance a boat has of failing per checkpoint. * @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 The boat's new coordinate
*/ */
protected void setDnfChance(int chance) { public static GPSCoordinate calculatePosition(GPSCoordinate oldCoordinates, double distanceTravelled, double azimuth) {
if (chance >= 0 && chance <= 100) {
dnfChance = chance;
}
}
protected boolean doNotFinish() { //Find new coordinate using current heading and distance
Random rand = new Random(); GeodeticCalculator geodeticCalculator = new GeodeticCalculator();
return rand.nextInt(100) < dnfChance; //Load start point into calculator
Point2D startPoint = new Point2D.Double(oldCoordinates.getLongitude(), oldCoordinates.getLatitude());
geodeticCalculator.setStartingGeographicPoint(startPoint);
//load direction and distance travelled into calculator
geodeticCalculator.setDirection(azimuth, distanceTravelled * Constants.NMToMetersConversion);
//get new point
Point2D endPoint = geodeticCalculator.getDestinationGeographicPoint();
return new GPSCoordinate(endPoint.getY(), endPoint.getX());
} }
/** /**
@ -293,8 +225,8 @@ public class Race implements Runnable {
//distanceTravelled = velocity (nm p hr) * time taken to update loop //distanceTravelled = velocity (nm p hr) * time taken to update loop
double distanceTravelled = (boat.getScaledVelocity() * millisecondsElapsed) / 3600000; double distanceTravelled = (boat.getScaledVelocity() * millisecondsElapsed) / 3600000;
double totalDistanceTravelled = distanceTravelled + boat.getDistanceTravelledInLeg(); double totalDistanceTravelled = distanceTravelled + boat.getDistanceTravelledInLeg();
System.out.println(totalDistanceTravelled);
boolean finish = boat.getCurrentLeg().getName().equals("Finish"); boolean finish = boat.getCurrentLeg().getName().equals("Finish");
if (!finish) { if (!finish) {
@ -302,7 +234,7 @@ public class Race implements Runnable {
//update boat's distance travelled //update boat's distance travelled
boat.setDistanceTravelledInLeg(totalDistanceTravelled); boat.setDistanceTravelledInLeg(totalDistanceTravelled);
//Calculate boat's new position by adding the distance travelled onto the start point of the leg //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())); totalDistanceTravelled, boat.calculateAzimuth()));
} }
} }
@ -310,11 +242,14 @@ public class Race implements Runnable {
protected void checkPosition(Boat boat, long timeElapsed) { protected void checkPosition(Boat boat, long timeElapsed) {
if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()) { if (boat.getDistanceTravelledInLeg() > boat.getCurrentLeg().getDistance()) {
//boat has passed onto new leg //boat has passed onto new leg
if (boat.getCurrentLeg().getName().equals("Finish")) { if (boat.getCurrentLeg().getName().equals("Finish")) {
//boat has finished //boat has finished
boatsFinished++; boatsFinished++;
boat.setTimeFinished(timeElapsed); boat.setTimeFinished(timeElapsed);
boat.setTimeFinished(timeElapsed); boat.setTimeFinished(timeElapsed);
boat.setVelocity(0);
boat.setScaledVelocity(0);
} else if (doNotFinish()) { } else if (doNotFinish()) {
boatsFinished++; boatsFinished++;
boat.setTimeFinished(timeElapsed); boat.setTimeFinished(timeElapsed);
@ -326,22 +261,25 @@ public class Race implements Runnable {
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance()); boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance());
//Move boat on to next leg //Move boat on to next leg
Leg nextLeg = legs.get(boat.getCurrentLeg().getLegNumber() + 1); Leg nextLeg = legs.get(boat.getCurrentLeg().getLegNumber() + 1);
boat.setCurrentLeg(nextLeg); boat.setCurrentLeg(nextLeg);
//Add overshoot distance into the distance travelled for the next leg
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg());
} }
} }
} }
/** /**
* Returns the boats that have started the race. * Sets the chance each boat has of failing at a gate or marker
* *
* @return ObservableList of Boat class that participated in the race. * @param chance percentage chance a boat has of failing per checkpoint.
* @see ObservableList
* @see Boat
*/ */
public ObservableList<Boat> getStartingBoats() { protected void setDnfChance(int chance) {
return startingBoats; if (chance >= 0 && chance <= 100) {
dnfChance = chance;
}
} }
protected boolean doNotFinish() {
Random rand = new Random();
return rand.nextInt(100) < dnfChance;
}
} }

@ -1,99 +0,0 @@
package seng302.Model;
/**
* Created by jjg64 on 19/04/17.
*/
public class Regatta {
int regattaID;
String RegattaName;
int raceID = 0;
String courseName;
double centralLatitude;
double centralLongitude;
double centralAltitude;
float utcOffset;
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;
}
}

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<BoatConfig>
<Boats>
<!--Mark Boats-->
<Boat Type="Mark" BoatName="PRO" SourceID="101" >
<GPSposition X= "-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="PIN" SourceID="102" >
<GPSposition X= "-64.855242" Y="32.293771" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="Marker1" SourceID="103" >
<GPSposition X= "-64.843983" Y="32.293039" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="WGL" SourceID="104" >
<GPSposition X= "-64.850045" Y="32.28468" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="WGR" SourceID="105" >
<GPSposition X= "-64.847591" Y="32.280164" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="LGL" SourceID="106" >
<GPSposition X= "-64.835249" Y="32.309693" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="LGR" SourceID="107" >
<GPSposition X= "-64.831785" Y="32.308046" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="FL" SourceID="108" >
<GPSposition X= "-64.839291" Y="32.317379" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="FR" SourceID="109" >
<GPSposition X= "-64.83626" Y="32.317257" Z="0"/>
</Boat>
<!--Participants-->
<Boat BoatName="Team ORACLE USA" HullNum="RG01" ShapeID="0" ShortName="USA" SourceID="121" StoweName="USA" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Land Rover BAR" HullNum="RG01" ShapeID="0" ShortName="GBR" SourceID="122" StoweName="GBR" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="SoftBank Team Japan" HullNum="RG01" ShapeID="0" ShortName="JPN" SourceID="123" StoweName="JPN" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Groupama Team France" HullNum="RG01" ShapeID="0" ShortName="FRA" SourceID="124" StoweName="FRA" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Artemis Racing" HullNum="RG01" ShapeID="0" ShortName="SWE" SourceID="125" StoweName="SWE" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Emirates Team New Zealand" HullNum="RG01" ShapeID="0" ShortName="NZL" SourceID="126" StoweName="NZL" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
</Boats>
</BoatConfig>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Race>
<RaceID>5326</RaceID>
<RaceType>FLEET</RaceType>
<CreationTimeDate>CREATION_TIME</CreationTimeDate>
<RaceStartTime Postpone="false" Time="START_TIME"/>
<Participants>
<Yacht SourceID="121"/>
<Yacht SourceID="122"/>
<Yacht SourceID="123"/>
<Yacht SourceID="124"/>
<Yacht SourceID="125"/>
<Yacht SourceID="126"/>
</Participants>
<CompoundMarkSequence>
<Corner CompoundMarkID="1" SeqID="1"/>
<Corner CompoundMarkID="2" SeqID="2"/>
<Corner CompoundMarkID="4" SeqID="3"/>
<Corner CompoundMarkID="3" SeqID="4"/>
<Corner CompoundMarkID="4" SeqID="5"/>
<Corner CompoundMarkID="5" SeqID="6"/>
</CompoundMarkSequence>
<Course>
<CompoundMark CompoundMarkID="1" Name="Start Line">
<Mark SeqId="1" Name="PRO" TargetLat="32.296577" TargetLng="-64.854304" SourceID="101"/>
<Mark SeqId="2" Name="PIN" TargetLat="32.293771" TargetLng="-64.855242" SourceID="102"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2" Name="Marker 1">
<Mark Name="Marker1" TargetLat="32.293039" TargetLng="-64.843983" SourceID="103"/>
</CompoundMark>
<CompoundMark CompoundMarkID="3" Name="Windward Gate">
<Mark Name="WGL" SeqId="1" TargetLat="32.28468" TargetLng="-64.850045" SourceID="104"/>
<Mark Name="WGR" SeqId="2" TargetLat="32.280164" TargetLng="-64.847591" SourceID="105"/>
</CompoundMark>
<CompoundMark CompoundMarkID="4" Name="Leeward Gate">
<Mark Name="LGL" SeqId="1" TargetLat="32.309693" TargetLng="-64.835249" SourceID="106"/>
<Mark Name="LGR" SeqId="2" TargetLat="32.308046" TargetLng="-64.831785" SourceID="107"/>
</CompoundMark>
<CompoundMark CompoundMarkID="5" Name="Finish Line">
<Mark Name="FL" SeqId="1" TargetLat="32.317379" TargetLng="-64.839291" SourceID="108"/>
<Mark Name="FR" SeqId="2" TargetLat="32.317257" TargetLng="-64.83626" SourceID="109"/>
</CompoundMark>
</Course>
<CourseLimit>
<Limit Lat="32.313922" Lon="-64.837168" SeqID="1"/>
<Limit Lat="32.317379" Lon="-64.839291" SeqID="2"/>
<Limit Lat="32.317911" Lon="-64.836996" SeqID="3"/>
<Limit Lat="32.317257" Lon="-64.83626" SeqID="4"/>
<Limit Lat="32.304273" Lon="-64.822834" SeqID="5"/>
<Limit Lat="32.279097" Lon="-64.841545" SeqID="6"/>
<Limit Lat="32.279604" Lon="-64.849871" SeqID="7"/>
<Limit Lat="32.289545" Lon="-64.854162" SeqID="8"/>
<Limit Lat="32.290198" Lon="-64.858711" SeqID="9"/>
<Limit Lat="32.297164" Lon="-64.856394" SeqID="10"/>
<Limit Lat="32.296148" Lon="-64.849184" SeqID="11"/>
</CourseLimit>
</Race>

@ -1,286 +0,0 @@
<race>
<raceId>5326</raceId>
<boats>
<boat>
<name>Team ORACLE USA</name>
<speed>20</speed>
<abbr>USA</abbr>
<sourceID>121</sourceID>
<colour>BLUEVIOLET</colour>
</boat>
<boat>
<name>Land Rover BAR</name>
<speed>30</speed>
<abbr>GBR</abbr>
<sourceID>122</sourceID>
<colour>BLACK</colour>
</boat>
<boat>
<name>SoftBank Team Japan</name>
<speed>25</speed>
<abbr>JPN</abbr>
<sourceID>123</sourceID>
<colour>RED</colour>
</boat>
<boat>
<name>Groupama Team France</name>
<speed>20</speed>
<abbr>FRA</abbr>
<sourceID>124</sourceID>
<colour>ORANGE</colour>
</boat>
<boat>
<name>Artemis Racing</name>
<speed>29</speed>
<abbr>SWE</abbr>
<sourceID>125</sourceID>
<colour>DARKOLIVEGREEN</colour>
</boat>
<boat>
<name>Emirates Team New Zealand</name>
<speed>62</speed>
<abbr>NZL</abbr>
<sourceID>126</sourceID>
<colour>LIMEGREEN</colour>
</boat>
</boats>
<legs>
<leg>
<name>Start to Mark 1</name>
<start>
<marker>
<coordinate>
<latitude>32.296577</latitude>
<longitude>-64.854304</longitude>
</coordinate>
<coordinate>
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
</start>
<finish>
<marker>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</finish>
</leg>
<leg>
<name>Mark 1 to Leeward Gate</name>
<start>
<marker>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
</start>
<finish>
<marker>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
</coordinate>
<coordinate>
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</finish>
</leg>
<leg>
<name>Leeward Gate to Windward Gate</name>
<start>
<marker>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
</coordinate>
<coordinate>
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</start>
<finish>
<marker>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
<coordinate>
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</finish>
</leg>
<leg>
<name>Windward Gate to Leeward Gate</name>
<start>
<marker>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
<coordinate>
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
</start>
<finish>
<marker>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
</coordinate>
<coordinate>
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</finish>
</leg>
<leg>
<name>Leeward Gate to Finish</name>
<start>
<marker>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
</coordinate>
<coordinate>
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
</start>
<finish>
<marker>
<coordinate>
<latitude>32.317379</latitude>
<longitude>-64.839291</longitude>
</coordinate>
<coordinate>
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</finish>
</leg>
</legs>
<course>
<boundaries>
<coordinate>
<latitude>32.313922</latitude>
<longitude>-64.837168</longitude>
</coordinate>
<coordinate>
<latitude>32.317379</latitude>
<longitude>-64.839291</longitude>
</coordinate>
<coordinate>
<latitude>32.317911</latitude>
<longitude>-64.836996</longitude>
</coordinate>
<coordinate>
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
<coordinate>
<latitude>32.304273</latitude>
<longitude>-64.822834</longitude>
</coordinate>
<coordinate>
<latitude>32.279097</latitude>
<longitude>-64.841545</longitude>
</coordinate>
<coordinate>
<latitude>32.279604</latitude>
<longitude>-64.849871</longitude>
</coordinate>
<coordinate>
<latitude>32.289545</latitude>
<longitude>-64.854162</longitude>
</coordinate>
<coordinate>
<latitude>32.290198</latitude>
<longitude>-64.858711</longitude>
</coordinate>
<coordinate>
<latitude>32.297164</latitude>
<longitude>-64.856394</longitude>
</coordinate>
<coordinate>
<latitude>32.296148</latitude>
<longitude>-64.849184</longitude>
</coordinate>
</boundaries>
<marker>
<name>Start Line</name>
<coordinate>
<latitude>32.296577</latitude>
<longitude>-64.854304</longitude>
</coordinate>
<coordinate>
<latitude>32.293771</latitude>
<longitude>-64.855242</longitude>
</coordinate>
</marker>
<marker>
<name>Mark</name>
<coordinate>
<latitude>32.293039</latitude>
<longitude>-64.843983</longitude>
</coordinate>
</marker>
<marker>
<name>Windward Gate</name>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
<coordinate>
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
<marker>
<name>Leeward Gate</name>
<coordinate>
<latitude>32.309693</latitude>
<longitude>-64.835249</longitude>
</coordinate>
<coordinate>
<latitude>32.308046</latitude>
<longitude>-64.831785</longitude>
</coordinate>
</marker>
<marker>
<name>Windward Gate</name>
<coordinate>
<latitude>32.284680</latitude>
<longitude>-64.850045</longitude>
</coordinate>
<coordinate>
<latitude>32.280164</latitude>
<longitude>-64.847591</longitude>
</coordinate>
</marker>
<marker>
<name>Finish Line</name>
<coordinate>
<latitude>32.317379</latitude>
<longitude>-64.839291</longitude>
</coordinate>
<coordinate>
<latitude>32.317257</latitude>
<longitude>-64.836260</longitude>
</coordinate>
</marker>
</course>
</race>

@ -1,87 +0,0 @@
package seng302.Data;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import static junit.framework.TestCase.assertTrue;
/**
* Created by esa46 on 25/04/17.
*/
public class BoatDataTest {
private static final String ROOT_TAG = "BoatConfig";
private static final String[] REQUIRED_TAGS = new String[]{
"Boats", "GPSposition"
};
private static final String[] REQUIRED_ATTRIBUTES = new String[]{
"SourceID", "ShapeID", "HullNum", "StoweName",
"ShortName", "BoatName"
};
String result;
RaceDataSource raceDataSource;
@Before
public void initReader() {
try {
raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml");
BoatData boatData = new BoatData(raceDataSource.getBoats());
result = boatData.createXML();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
@Test
public void xmlHasAllNecessaryTags() {
assertTrue(result.contains("<" + ROOT_TAG + ">"));
for (String tag : REQUIRED_TAGS) {
assertTrue(result.contains("<" + tag + ">") || result.contains("<" + tag + " "));
}
}
@Test
public void xmlHasAllNecessaryAttributes() {
for (String attribute : REQUIRED_ATTRIBUTES) {
assertTrue(result.contains(attribute + "="));
}
}
@Test
public void allTagsAreTerminated() {
for (String tag : REQUIRED_TAGS) {
int lastIndex = 0;
String openTag = "<" + tag + ">";
String closeTag = "</" + tag + ">";
while (lastIndex < result.length() && lastIndex > 0) {
lastIndex = result.indexOf(openTag, lastIndex);
if (lastIndex > 0) {
lastIndex = result.indexOf(closeTag, lastIndex);
assertTrue(lastIndex > 0);
}
}
}
}
}

@ -1,83 +0,0 @@
package seng302.Data;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import static junit.framework.TestCase.assertTrue;
/**
* Created by esa46 on 25/04/17.
*/
public class RaceDataTest {
private static final String ROOT_TAG = "Race";
private static final String[] REQUIRED_TAGS = new String[]{
"RaceID", "RaceType", "CreationTimeDate", "RaceStartTime", "Participants", "Yacht",
"CompoundMarkSequence", "Course", "CompoundMark", "Mark", "CourseLimit", "Limit"
};
String result;
RaceDataSource raceDataSource;
@Before
public void initReader() {
try {
raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml");
RaceData raceData = new RaceData(raceDataSource);
result = raceData.createXML();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
@Test
public void xmlHasAllNecessaryFields() {
assertTrue(result.contains("<" + ROOT_TAG + ">"));
for (String tag : REQUIRED_TAGS) {
System.out.println(tag);
assertTrue(result.contains("<" + tag + ">") || result.contains("<" + tag + " "));
}
}
@Test
public void allTagsAreTerminated() {
for (String tag : REQUIRED_TAGS) {
int lastIndex = 0;
String openTag = "<" + tag + ">";
String closeTag = "</" + tag + ">";
while (lastIndex < result.length() && lastIndex > 0) {
lastIndex = result.indexOf(openTag, lastIndex);
if (lastIndex > 0) {
lastIndex = result.indexOf(closeTag, lastIndex);
assertTrue(lastIndex > 0);
}
}
}
}
@Test
public void idAndTypeAreEquivalent() {
String newId = result.substring(result.indexOf("<RaceID>") + 8, result.indexOf("</RaceID>"));
String newRaceType = result.substring(result.indexOf("<RaceType>") + 10, result.indexOf("</RaceType>"));
assertTrue(raceDataSource.getRaceId() == Integer.parseInt(newId));
assertTrue(raceDataSource.getRaceType().equals(newRaceType));
}
}

@ -1,74 +0,0 @@
package seng302.Data;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RaceXMLReader;
import seng302.DataInput.RegattaDataSource;
import seng302.DataInput.RegattaXMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import static junit.framework.TestCase.assertTrue;
/**
* Created by esa46 on 25/04/17.
*/
public class RegattaDataTest {
private static final String ROOT_TAG = "RegattaConfig";
private static final String[] REQUIRED_TAGS = new String[]{
"RegattaID", "RegattaName", "CourseName", "CentralLatitude", "CentralLongitude",
"CentralAltitude", "UtcOffset", "MagneticVariation"
};
String result;
RegattaDataSource regattaDataSource;
@Before
public void initReader() {
try {
regattaDataSource = new RegattaXMLReader("mockXML/regattaTest.xml");
RegattaData regattaData = new RegattaData(regattaDataSource);
result = regattaData.createXML();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
@Test
public void xmlHasAllNecessaryFields() {
assertTrue(result.contains("<" + ROOT_TAG + ">"));
for (String tag : REQUIRED_TAGS) {
System.out.println(tag);
assertTrue(result.contains("<" + tag + ">") || result.contains("<" + tag + " "));
}
}
@Test
public void allTagsAreTerminated() {
for (String tag : REQUIRED_TAGS) {
int lastIndex = 0;
String openTag = "<" + tag + ">";
String closeTag = "</" + tag + ">";
while (lastIndex < result.length() && lastIndex > 0) {
lastIndex = result.indexOf(openTag, lastIndex);
if (lastIndex > 0) {
lastIndex = result.indexOf(closeTag, lastIndex);
assertTrue(lastIndex > 0);
}
}
}
}
}

@ -0,0 +1,58 @@
package seng302.DataInput;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.SAXException;
import seng302.Model.Boat;
import seng302.Model.Mark;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.testng.Assert.*;
/**
* Created by cbt24 on 10/05/17.
*/
public class BoatXMLReaderTest {
BoatDataSource boatData;
List<Boat> boats;
List<Mark> marks;
@Before
public void setUp() {
try {
boatData = new BoatXMLReader("mockXML/boatTest.xml");
boats = new ArrayList<>(boatData.getBoats().values());
marks = new ArrayList<>(boatData.getMarkerBoats().values());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void boatsReadNameFromFile() {
String[] names = {
"Team ORACLE USA","Land Rover BAR","SoftBank Team Japan","Groupama Team France","Artemis Racing","Emirates Team New Zealand"
};
for(int i = 0; i < boats.size(); i++) {
assertEquals(names[i], boats.get(i).getName());
}
}
@Test
public void marksReadNameFromFile() {
String[] names = {
"PRO","PIN","Marker1","WGL","WGR","LGL","LGR","FL","FR"
};
for(int i = 0; i < marks.size(); i++) {
assertEquals(names[i], marks.get(i).getName());
}
}
}

@ -1,51 +0,0 @@
package seng302.DataInput;
import org.junit.Before;
import org.junit.Test;
import seng302.Model.Regatta;
import static org.junit.Assert.*;
/**
* Created by jjg64 on 19/04/17.
*/
public class RegattaXMLTest {
RegattaXMLReader regattaXMLReader;
@Before
public void findFile() {
try {
regattaXMLReader = new RegattaXMLReader("mockXML/regattaTest.xml", false);
} catch (Exception e) {
fail("Cannot find mockXML/regattaXML/regattaTest.xml in the resources folder");
}
}
@Test
public void makeRegattaTest() {
try {
regattaXMLReader = new RegattaXMLReader("mockXML/regattaTest.xml");
assertNotEquals(regattaXMLReader.getRegatta(), null);
} catch (Exception e) {
fail("Did not make a Regatta object");
}
}
@Test
public void correctValuesTest() {
try {
regattaXMLReader = new RegattaXMLReader("mockXML/regattaTest.xml");
Regatta regatta = regattaXMLReader.getRegatta();
assertEquals(regatta.getRegattaID(), 3);
assertEquals(regatta.getRegattaName(), "New Zealand Test");
assertEquals(regatta.getCourseName(), "North Head");
assertEquals(regatta.getCentralLatitude(), -36.82791529, 0.00000001);
assertEquals(regatta.getCentralLongitude(), 174.81218919, 0.00000001);
assertEquals(regatta.getCentralAltitude(), 0.00, 0.00000001);
assertEquals(regatta.getUtcOffset(), 12.0, 0.001);
assertEquals(regatta.getMagneticVariation(), 14.1, 0.001);
} catch (Exception e) {
fail("Did not have the correct values");
}
}
}

@ -13,7 +13,7 @@ public class BoatTest {
private GPSCoordinate ORIGIN_COORDS = new GPSCoordinate(0, 0); private GPSCoordinate ORIGIN_COORDS = new GPSCoordinate(0, 0);
private Boat TEST_BOAT = new Boat("Test", 1, "tt", 1); private Boat TEST_BOAT = new Boat(1, "Test", "tt");
@Test @Test
public void calculateDueNorthAzimuthReturns0() { public void calculateDueNorthAzimuthReturns0() {

@ -4,11 +4,12 @@ import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.testng.AssertJUnit.assertEquals;
/** /**
* Created by esa46 on 29/03/17. * Created by esa46 on 29/03/17.
*/ */
public class MarkerTest { public class CompoundMarkTest {
GPSCoordinate ORIGIN_COORD = new GPSCoordinate(0, 0); GPSCoordinate ORIGIN_COORD = new GPSCoordinate(0, 0);
@ -29,13 +30,12 @@ public class MarkerTest {
} }
@Ignore
@Test @Test
public void averageLatOfTwoMarksIsAccurate() { public void averageLatOfTwoMarksIsAccurate() {
GPSCoordinate testCoord = new GPSCoordinate(10, 0); GPSCoordinate testCoord = new GPSCoordinate(0.001, 0);
Marker testMark = new Marker(ORIGIN_COORD, testCoord); Marker testMark = new Marker(ORIGIN_COORD, testCoord);
assertTrue(testMark.getAverageGPSCoordinate().equals(new GPSCoordinate(5, 0))); assertEquals(testMark.getAverageGPSCoordinate(), new GPSCoordinate(0.0005, 0));
} }
@Test @Test
@ -50,10 +50,11 @@ public class MarkerTest {
@Test @Test
public void averageLatAndLongOfTwoMarksIsAccurate() { public void averageLatAndLongOfTwoMarksIsAccurate() {
GPSCoordinate testCoord1 = new GPSCoordinate(10, 30); GPSCoordinate testCoord1 = new GPSCoordinate(0.0, 30);
GPSCoordinate testCoord2 = new GPSCoordinate(30, 60); GPSCoordinate testCoord2 = new GPSCoordinate(0.001, 60);
Marker testMark = new Marker(testCoord1, testCoord2); Marker testMark = new Marker(testCoord1, testCoord2);
assertTrue(testMark.getAverageGPSCoordinate().equals(new GPSCoordinate(020.644102, 44.014817))); assertEquals(testMark.getAverageGPSCoordinate().getLatitude(), 0.00051776, 1e-8);
assertEquals(testMark.getAverageGPSCoordinate().getLongitude(), 45.000000, 1e-8);
} }
} }

@ -14,7 +14,7 @@ import static junit.framework.TestCase.assertEquals;
*/ */
public class LegTest { public class LegTest {
private Marker ORIGIN_MARKER = new Marker(new GPSCoordinate(0, 0)); private Marker ORIGIN_Compound_MARKER = new Marker(new GPSCoordinate(0, 0));
@Test @Test
public void calculateDistanceHandles5nmNorth() { public void calculateDistanceHandles5nmNorth() {
@ -23,7 +23,7 @@ public class LegTest {
calc.setDirection(0, 5 * Constants.NMToMetersConversion); calc.setDirection(0, 5 * Constants.NMToMetersConversion);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0); Leg test = new Leg("Test", ORIGIN_Compound_MARKER, endMarker, 0);
assertEquals(test.getDistance(), 5, 1e-8); assertEquals(test.getDistance(), 5, 1e-8);
} }
@ -34,7 +34,7 @@ public class LegTest {
calc.setDirection(90, 12 * Constants.NMToMetersConversion); calc.setDirection(90, 12 * Constants.NMToMetersConversion);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0); Leg test = new Leg("Test", ORIGIN_Compound_MARKER, endMarker, 0);
assertEquals(test.getDistance(), 12, 1e-8); assertEquals(test.getDistance(), 12, 1e-8);
} }
@ -45,7 +45,7 @@ public class LegTest {
calc.setDirection(180, 0.5 * Constants.NMToMetersConversion); calc.setDirection(180, 0.5 * Constants.NMToMetersConversion);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0); Leg test = new Leg("Test", ORIGIN_Compound_MARKER, endMarker, 0);
assertEquals(test.getDistance(), 0.5, 1e-8); assertEquals(test.getDistance(), 0.5, 1e-8);
} }
@ -56,14 +56,14 @@ public class LegTest {
calc.setDirection(-90, 0.1 * Constants.NMToMetersConversion); calc.setDirection(-90, 0.1 * Constants.NMToMetersConversion);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint());
Leg test = new Leg("Test", ORIGIN_MARKER, endMarker, 0); Leg test = new Leg("Test", ORIGIN_Compound_MARKER, endMarker, 0);
assertEquals(test.getDistance(), 0.1, 1e-8); assertEquals(test.getDistance(), 0.1, 1e-8);
} }
@Test @Test
public void calculateDistanceHandlesZeroDifference() { public void calculateDistanceHandlesZeroDifference() {
Leg test = new Leg("Test", ORIGIN_MARKER, ORIGIN_MARKER, 0); Leg test = new Leg("Test", ORIGIN_Compound_MARKER, ORIGIN_Compound_MARKER, 0);
assertEquals(test.getDistance(), 0, 1e-8); assertEquals(test.getDistance(), 0, 1e-8);
} }

@ -1,251 +1,300 @@
//package seng302.Model; package seng302.Model;
//
//import javafx.scene.paint.Color;
//import org.junit.BeforeClass; import org.junit.Before;
//import org.junit.Ignore; import org.junit.Ignore;
//import org.junit.Test; import org.junit.Test;
//import org.mockito.Mockito; import org.mockito.Mockito;
//import org.xml.sax.SAXException; import org.xml.sax.SAXException;
//import seng302.DataInput.RaceDataSource; import seng302.DataInput.BoatDataSource;
//import seng302.DataInput.RaceXMLReader; import seng302.DataInput.BoatXMLReader;
//import seng302.MockOutput; import seng302.DataInput.RaceDataSource;
// import seng302.DataInput.RaceXMLReader;
//import javax.xml.parsers.ParserConfigurationException; import seng302.Exceptions.StreamedCourseXMLException;
//import java.io.IOException; import seng302.MockOutput;
//import java.util.ArrayList;
//import java.util.List; import javax.xml.parsers.ParserConfigurationException;
// import java.io.IOException;
//import static org.junit.Assert.assertEquals; import java.text.ParseException;
//import static org.junit.Assert.assertTrue; import java.util.ArrayList;
//import static org.junit.Assert.fail;
//import static org.mockito.Matchers.any;
//import static org.mockito.Mockito.atLeast; import static org.junit.Assert.*;
//import static org.mockito.Mockito.verify; import static org.mockito.Matchers.*;
// import static org.mockito.Mockito.*;
///**
// * Created by esa46 on 15/03/17. /**
// */ * Created by esa46 on 15/03/17.
//public class RaceTest{ */
// public class RaceTest{
// private static MockOutput mockOutput;
// SharedModel.Leg START_LEG = new SharedModel.Leg("Start", new SharedModel.Marker(new SharedModel.GPSCoordinate(0, 0)), new SharedModel.Marker(new SharedModel.GPSCoordinate(1, 1)), 0);
// SharedModel.Leg FINISH_LEG = new SharedModel.Leg("Finish", new SharedModel.Marker(new SharedModel.GPSCoordinate(1, 1)), new SharedModel.Marker(new SharedModel.GPSCoordinate(2, 2)), 0); public static final Marker ORIGIN = new Marker(new GPSCoordinate(0, 0));
// public static final Marker THREE_NM_FROM_ORIGIN = new Marker(new GPSCoordinate(0.050246769, 0));
//// @Override public static final Marker FIFTEEN_NM_FROM_ORIGIN = new Marker(new GPSCoordinate(0.251233845, 0));
//// public void start(Stage primaryStage) throws Exception{} public static ArrayList<Leg> TEST_LEGS = new ArrayList<>();
//// public static final int START_LEG_DISTANCE = 3;
//// public static void main(String[] args) { public static final int MIDDLE_LEG_DISTANCE = 12;
//// launch(args); public static final Leg START_LEG = new Leg("Start", ORIGIN, THREE_NM_FROM_ORIGIN, 0);
//// } public static final Leg MIDDLE_LEG = new Leg("Middle", THREE_NM_FROM_ORIGIN, FIFTEEN_NM_FROM_ORIGIN, 1);
// public static final Leg FINISH_LEG = new Leg("Finish", FIFTEEN_NM_FROM_ORIGIN, FIFTEEN_NM_FROM_ORIGIN, 2);
//
//// @BeforeClass @Before
//// public static void initJFX() { public void setUp() {
//// Thread t = new Thread("JavaFX Init Thread") { TEST_LEGS.add(START_LEG);
//// public void run() { TEST_LEGS.add(MIDDLE_LEG);
//// Application.launch(TestApp.class, new String[0]); TEST_LEGS.add(FINISH_LEG);
//// } }
//// };
//// t.setDaemon(true); @Ignore
//// t.start(); @Test
//// } public void countdownTimerSendsBoatLocations() {
//
// @BeforeClass try {
// public static void setUp() { MockOutput mockOutput = Mockito.mock(MockOutput.class);
// try { BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
// mockOutput = new MockOutput(); RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
// } catch(IOException e) { Race testRace = new Race(raceDataSource, mockOutput);
// fail(); testRace.initialiseBoats();
// } testRace.countdownTimer.handle(1);
// } verify(mockOutput, atLeast(boatDataSource.getBoats().size())).parseBoatLocation(anyInt(), anyDouble(), anyDouble(), anyDouble(), anyDouble());
//
// @Ignore } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// @Test e.printStackTrace();
// public void boatLocationMessagesAreGenerated() { fail();
// try { }
// RaceDataSource raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml"); }
//
// MockOutput mockOutput = Mockito.mock(MockOutput.class); @Ignore
// Race race = new Race(raceDataSource, 100, mockOutput); @Test
// new Thread((race)).start(); public void countdownTimerSendsRaceStatusMessages() {
//
// try { try {
// Thread.sleep(5000); MockOutput mockOutput = Mockito.mock(MockOutput.class);
// } catch (InterruptedException e) { RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// fail(); Race testRace = new Race(dataSource, mockOutput);
// } testRace.initialiseBoats();
// verify(mockOutput, atLeast(400)).parseBoatLocation(any()); testRace.countdownTimer.handle(1);
// verify(mockOutput, atLeast(1)).parseRaceStatus(any());
// } catch (IOException e) {
// fail(); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// } catch (SAXException e) { e.printStackTrace();
// fail(); fail();
// } catch (ParserConfigurationException e) { }
// fail(); }
// }
// } @Ignore
// @Test
// @Test public void checkPositionFinishedUpdatesNumberFinishedBoats() {
// public void timerCanBeDisabled() {
// SharedModel.BoatInRace boat1 = new SharedModel.BoatInRace("Test 1", 10000, Color.ALICEBLUE, "t1", 1); try {
// SharedModel.BoatInRace boat2 = new SharedModel.BoatInRace("Test 2", 10000, Color.BURLYWOOD, "t2", 2); MockOutput mockOutput = Mockito.mock(MockOutput.class);
// List<SharedModel.BoatInRace> boats = new ArrayList<>(); RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// boats.add(boat1); Race testRace = new Race(dataSource, mockOutput);
// boats.add(boat2); testRace.initialiseBoats();
// Boat testBoat = testRace.startingBoats.get(0);
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); testBoat.setCurrentLeg(FINISH_LEG);
// legs.add(START_LEG); testBoat.setDistanceTravelledInLeg(1);
// legs.add(FINISH_LEG); testRace.checkPosition(testBoat, 1);
//
// assertEquals(testRace.boatsFinished, 1);
// Race race = new Race(boats, legs, 5, mockOutput);
// race.setDnfChance(0); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// long timeStarted = System.currentTimeMillis(); e.printStackTrace();
// race.run(); fail();
// assertTrue(System.currentTimeMillis() - timeStarted < 4000); }
// } }
//
// @Test @Ignore
// public void checkPositionUpdatesNumberFinishedBoats() { @Test
// public void checkPositionSetFinishedBoatVelocityTo0() {
// SharedModel.BoatInRace finishedBoat = new SharedModel.BoatInRace("Test", 1000, Color.ALICEBLUE, "tt", 1);
// finishedBoat.setDistanceTravelledInLeg(500); try {
// MockOutput mockOutput = Mockito.mock(MockOutput.class);
// finishedBoat.setCurrentLeg(FINISH_LEG); RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// Race testRace = new Race(dataSource, mockOutput);
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); testRace.initialiseBoats();
// boats.add(finishedBoat); Boat testBoat = testRace.startingBoats.get(0);
// testBoat.setCurrentLeg(FINISH_LEG);
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); testBoat.setDistanceTravelledInLeg(1);
// legs.add(FINISH_LEG); testRace.checkPosition(testBoat, 1);
//
// Race race = new Race(boats, legs, 5, mockOutput); assertEquals(testBoat.getVelocity(), 0, 1e-8);
// race.setDnfChance(0);
// assertEquals(race.boatsFinished, 0); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// e.printStackTrace();
// race.checkPosition(finishedBoat, 100000); fail();
// assertEquals(race.boatsFinished, 1); }
// assertEquals(finishedBoat.getTimeFinished(), 100000); }
//
// } @Ignore
// @Test
// @Test public void checkPositionSetsFinishTime() {
// public void checkPositionDoesntUpdateNumberFinishedBoats() {
// try {
// SharedModel.BoatInRace unFinishedBoat = new SharedModel.BoatInRace("Test", 10, Color.ALICEBLUE, "tt", 1); MockOutput mockOutput = Mockito.mock(MockOutput.class);
// unFinishedBoat.setDistanceTravelledInLeg(0); RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// Race testRace = new Race(dataSource, mockOutput);
// unFinishedBoat.setCurrentLeg(FINISH_LEG); testRace.initialiseBoats();
// Boat testBoat = testRace.startingBoats.get(0);
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); testBoat.setCurrentLeg(FINISH_LEG);
// boats.add(unFinishedBoat); testBoat.setDistanceTravelledInLeg(1);
// testRace.checkPosition(testBoat, 1);
// ArrayList<SharedModel.Leg> legs = new ArrayList<>();
// legs.add(FINISH_LEG); assertEquals(testBoat.getTimeFinished(), 1, 1e-8);
//
// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// Race race = new Race(boats, legs, 1, mockOutput); e.printStackTrace();
// race.setDnfChance(0); fail();
// assertEquals(race.boatsFinished, 0); }
// race.checkPosition(unFinishedBoat, 100); }
// assertEquals(race.boatsFinished, 0);
// @Ignore
// } @Test
// public void checkPositionUnfinishedDoesntUpdateNumberFinishedBoats() {
// @Test
// public void distanceTravelledBeforeUpdatingLegIsRetained() { try {
// MockOutput mockOutput = Mockito.mock(MockOutput.class);
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// Race testRace = new Race(dataSource, mockOutput);
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); testRace.initialiseBoats();
// Boat testBoat = testRace.startingBoats.get(0);
// legs.add(START_LEG); testBoat.setCurrentLeg(START_LEG);
// legs.add(FINISH_LEG); testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE);
// testRace.checkPosition(testBoat, 1);
// Race race = new Race(boats, legs, 1, mockOutput);
// race.setDnfChance(0); assertEquals(testRace.boatsFinished, 0);
//
// SharedModel.BoatInRace unFinishedBoat = new SharedModel.BoatInRace("Test", 10, Color.ALICEBLUE, "tt", 4); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// unFinishedBoat.setDistanceTravelledInLeg(100); e.printStackTrace();
// unFinishedBoat.setCurrentLeg(START_LEG); fail();
// }
// race.checkPosition(unFinishedBoat, 100); }
// assertEquals(unFinishedBoat.getCurrentLeg().getName(), "Finish");
// assertTrue(unFinishedBoat.getDistanceTravelledInLeg() > 0);
// assertTrue(unFinishedBoat.getDistanceTravelledInLeg() < 100); @Ignore
// } @Test
// public void distanceTravelledBeforeUpdatingLegIsRetained() {
// @Ignore
// @Test try {
// public void timerDelaysByHalfSecond() throws InterruptedException { MockOutput mockOutput = Mockito.mock(MockOutput.class);
// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml"));
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); Race testRace = new Race(dataSource, mockOutput);
// testRace.initialiseBoats();
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); Boat testBoat = testRace.startingBoats.get(0);
// legs.add(START_LEG); testBoat.setCurrentLeg(START_LEG);
// testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE + 1);
// Race race = new Race(boats, legs, 1, mockOutput); testRace.checkPosition(testBoat, 0);
// race.PRERACE_TIME = 500;
// race.runRace = false; assertEquals(testBoat.getDistanceTravelledInLeg(), 1, 1e-7);
//
// race.countdownTimer(); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// e.printStackTrace();
// long timeStarted = System.currentTimeMillis(); fail();
// long currentTime = System.currentTimeMillis(); }
// while (!race.countdownFinish) { }
// currentTime = System.currentTimeMillis();
// } @Ignore
// @Test
// assertTrue(currentTime - timeStarted > 500); public void doNotFinishAnswersYesIf100PercentChance() {
// }
// try {
// @Test MockOutput mockOutput = Mockito.mock(MockOutput.class);
// public void scalerScalesVelocityCorrectly() { BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
// int scaleFactor = 3; Race testRace = new Race(raceDataSource, mockOutput);
// float vel1 = 0;
// float vel2 = (float) 1.999; testRace.setDnfChance(100);
// float vel3 = (float) 32.5; assertTrue(testRace.doNotFinish());
// float vel4 = 500;
// SharedModel.BoatInRace boat1 = new SharedModel.BoatInRace("test", vel1, Color.ALICEBLUE, "tt",1); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// SharedModel.BoatInRace boat2 = new SharedModel.BoatInRace("test", vel2, Color.ALICEBLUE, "tt", 2); e.printStackTrace();
// SharedModel.BoatInRace boat3 = new SharedModel.BoatInRace("test", vel3, Color.ALICEBLUE, "tt", 3); fail();
// SharedModel.BoatInRace boat4 = new SharedModel.BoatInRace("test", vel4, Color.ALICEBLUE, "tt", 4); }
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); }
// boats.add(boat1);
// boats.add(boat2); @Ignore
// boats.add(boat3); @Test
// boats.add(boat4); public void doNotFinishAnswersNoIf0PercentChance() {
//
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); try {
// legs.add(START_LEG); MockOutput mockOutput = Mockito.mock(MockOutput.class);
// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
// Race race = new Race(boats, legs, scaleFactor, mockOutput); Race testRace = new Race(raceDataSource, mockOutput);
// race.setDnfChance(0);
// testRace.setDnfChance(0);
// assertEquals(race.getStartingBoats().get(0).getScaledVelocity(), vel1 * scaleFactor, 1e-6); assertFalse(testRace.doNotFinish());
// assertEquals(race.getStartingBoats().get(1).getScaledVelocity(), vel2 * scaleFactor, 1e-6);
// assertEquals(race.getStartingBoats().get(2).getScaledVelocity(), vel3 * scaleFactor, 1e-6); } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
// assertEquals(race.getStartingBoats().get(3).getScaledVelocity(), vel4 * scaleFactor, 1e-6); e.printStackTrace();
// fail();
// } }
// @Test }
// public void doNotFinishCorrectly() {
// ArrayList<SharedModel.BoatInRace> boats = new ArrayList<>(); @Ignore
// @Test
// ArrayList<SharedModel.Leg> legs = new ArrayList<>(); public void boatsAreSetToDNF() {
// legs.add(START_LEG); try {
// MockOutput mockOutput = Mockito.mock(MockOutput.class);
// Race race = new Race(boats, legs, 1, mockOutput); BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
// race.setDnfChance(100); Race testRace = new Race(raceDataSource, mockOutput);
// assertTrue(race.doNotFinish()); testRace.setDnfChance(100);
// Boat testBoat = testRace.startingBoats.get(0);
// race.setDnfChance(0); testBoat.setCurrentLeg(START_LEG);
// assertTrue(!race.doNotFinish()); testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE + 1);
// } testRace.checkPosition(testBoat, 1);
// assertEquals(testBoat.getCurrentLeg().getName(), "DNF");
//
// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
//} e.printStackTrace();
fail();
}
}
@Ignore
@Test
public void updatePositionIgnoresFinishedBoats() {
try {
MockOutput mockOutput = Mockito.mock(MockOutput.class);
BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
Race testRace = new Race(raceDataSource, mockOutput);
Boat testBoat = testRace.startingBoats.get(0);
testBoat.setCurrentLeg(FINISH_LEG);
testBoat.setCurrentPosition(ORIGIN.getAverageGPSCoordinate());
testRace.updatePosition(testBoat, 1);
assertEquals(testBoat.getCurrentPosition(), ORIGIN.getAverageGPSCoordinate());
} catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
e.printStackTrace();
fail();
}
}
@Ignore
@Test
public void updatePositionChangesBoatPosition() {
try {
MockOutput mockOutput = Mockito.mock(MockOutput.class);
BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml");
RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource);
Race testRace = new Race(raceDataSource, mockOutput);
testRace.initialiseBoats();
Boat testBoat = testRace.startingBoats.get(0);
testBoat.setCurrentLeg(START_LEG);
testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE - 1);
testBoat.setCurrentPosition(ORIGIN.getAverageGPSCoordinate());
testRace.updatePosition(testBoat, 100);
assertFalse(testBoat.getCurrentPosition() == ORIGIN.getAverageGPSCoordinate());
} catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
e.printStackTrace();
fail();
}
}
}

@ -1,96 +0,0 @@
package seng302.Model;/**
* Created by Gondr on 26/03/2017.
*/
import org.junit.Ignore;
import org.junit.Test;
import seng302.DataInput.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");
}
}
@Ignore
@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(), "ORACLE TEAM USA");
assertTrue(boats.get(0).getVelocity() == 20);
//test boat 2
assertEquals(boats.get(1).getName(), "Land Rover BAR");
assertTrue(boats.get(1).getVelocity() == 30);
assertEquals(boats.get(1).getAbbrev(), "GBR");
//test boat 3
assertEquals(boats.get(2).getName(), "SoftBank Team Japan");
assertTrue(boats.get(2).getVelocity() == 25);
assertEquals(boats.get(2).getAbbrev(), "JPN");
//test boat 4
assertEquals(boats.get(3).getName(), "Groupama Team France");
assertTrue(boats.get(3).getVelocity() == 20);
assertEquals(boats.get(3).getAbbrev(), "FRA");
//test boat 5
assertEquals(boats.get(4).getName(), "Artemis Racing");
assertTrue(boats.get(4).getVelocity() == 29);
assertEquals(boats.get(4).getAbbrev(), "SWE");
//test boat 6
assertEquals(boats.get(5).getName(), "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.getMark() != null);
assertTrue(raceXMLReader.getBoundary().size() == 11);
} catch (Exception e) {
e.printStackTrace();
fail("Course Unreadable");
}
}
}

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<BoatConfig>
<Boats>
<!--Mark Boats-->
<Boat Type="Mark" BoatName="PRO" SourceID="101" >
<GPSposition X= "-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="PIN" SourceID="102" >
<GPSposition X= "-64.855242" Y="32.293771" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="Marker1" SourceID="103" >
<GPSposition X= "-64.843983" Y="32.293039" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="WGL" SourceID="104" >
<GPSposition X= "-64.850045" Y="32.28468" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="WGR" SourceID="105" >
<GPSposition X= "-64.847591" Y="32.280164" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="LGL" SourceID="106" >
<GPSposition X= "-64.835249" Y="32.309693" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="LGR" SourceID="107" >
<GPSposition X= "-64.831785" Y="32.308046" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="FL" SourceID="108" >
<GPSposition X= "-64.839291" Y="32.317379" Z="0"/>
</Boat>
<Boat Type="Mark" BoatName="FR" SourceID="109" >
<GPSposition X= "-64.83626" Y="32.317257" Z="0"/>
</Boat>
<!--Participants-->
<Boat BoatName="Team ORACLE USA" HullNum="RG01" ShapeID="0" ShortName="USA" SourceID="121" StoweName="USA" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Land Rover BAR" HullNum="RG01" ShapeID="0" ShortName="GBR" SourceID="122" StoweName="GBR" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="SoftBank Team Japan" HullNum="RG01" ShapeID="0" ShortName="JPN" SourceID="123" StoweName="JPN" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Groupama Team France" HullNum="RG01" ShapeID="0" ShortName="FRA" SourceID="124" StoweName="FRA" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Artemis Racing" HullNum="RG01" ShapeID="0" ShortName="SWE" SourceID="125" StoweName="SWE" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
<Boat BoatName="Emirates Team New Zealand" HullNum="RG01" ShapeID="0" ShortName="NZL" SourceID="126" StoweName="NZL" Type="Yacht">
<GPSposition X="-64.854304" Y="32.296577" Z="0"/>
</Boat>
</Boats>
</BoatConfig>

@ -1,251 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<BoatConfig>
<Modified>2012-05-17T07:49:40+0200</Modified>
<Version>12</Version>
<Settings>
<RaceBoatType Type="AC45"/>
<BoatDimension BoatLength="14.019" HullLength="13.449"/>
<ZoneSize MarkZoneSize="40.347" CourseZoneSize="40.347"/>
<ZoneLimits Limit1="200" Limit2="100" Limit3="40.347" Limit4="0" Limit5="-100"/>
</Settings>
<BoatShapes>
<BoatShape ShapeID="0">
<Vertices>
<Vtx Seq="1" Y="0" X="-2.659"/>
<Vtx Seq="2" Y="18.359" X="-2.659"/>
<Vtx Seq="3" Y="18.359" X="2.659"/>
<Vtx Seq="4" Y="0" X="2.659"/>
</Vertices>
</BoatShape>
<BoatShape ShapeID="1">
<Vertices>
<Vtx Seq="1" Y="0" X="-1.278"/>
<Vtx Seq="2" Y="8.876" X="-1.278"/>
<Vtx Seq="3" Y="8.876" X="1.278"/>
<Vtx Seq="4" Y="0" X="1.278"/>
</Vertices>
</BoatShape>
<BoatShape ShapeID="2">
<Vertices>
<Vtx Seq="1" Y="0" X="-1.1"/>
<Vtx Seq="2" Y="8.3" X="-1.1"/>
<Vtx Seq="3" Y="8.3" X="1.1"/>
<Vtx Seq="4" Y="0" X="1.1"/>
</Vertices>
</BoatShape>
<BoatShape ShapeID="3">
<Vertices>
<Vtx Seq="1" Y="0" X="-0.75"/>
<Vtx Seq="2" Y="3" X="-0.75"/>
<Vtx Seq="3" Y="3" X="0.75"/>
<Vtx Seq="4" Y="0" X="0.75"/>
</Vertices>
</BoatShape>
<BoatShape ShapeID="4">
<Vertices>
<Vtx Seq="1" Y="0" X="-3.46"/>
<Vtx Seq="2" Y="13.449" X="-3.46"/>
<Vtx Seq="3" Y="14.019" X="0"/>
<Vtx Seq="4" Y="13.449" X="3.46"/>
<Vtx Seq="5" Y="0" X="3.46"/>
</Vertices>
<Catamaran>
<Vtx Seq="1" Y="1.769" X="-2.752"/>
<Vtx Seq="2" Y="0" X="-2.813"/>
<Vtx Seq="3" Y="0" X="-3.34"/>
<Vtx Seq="4" Y="5.351" X="-3.46"/>
<Vtx Seq="5" Y="10.544" X="-3.387"/>
<Vtx Seq="6" Y="13.449" X="-3.075"/>
<Vtx Seq="7" Y="10.851" X="-2.793"/>
<Vtx Seq="8" Y="6.669" X="-2.699"/>
<Vtx Seq="9" Y="6.669" X="2.699"/>
<Vtx Seq="10" Y="10.851" X="2.793"/>
<Vtx Seq="11" Y="13.449" X="3.075"/>
<Vtx Seq="12" Y="10.544" X="3.387"/>
<Vtx Seq="13" Y="5.351" X="3.46"/>
<Vtx Seq="14" Y="0" X="3.34"/>
<Vtx Seq="15" Y="0" X="2.813"/>
<Vtx Seq="16" Y="1.769" X="2.752"/>
</Catamaran>
<Bowsprit>
<Vtx Seq="1" Y="6.669" X="-0.2"/>
<Vtx Seq="2" Y="11.377" X="-0.2"/>
<Vtx Seq="3" Y="14.019" X="0"/>
<Vtx Seq="4" Y="11.377" X="0.2"/>
<Vtx Seq="5" Y="6.669" X="0.2"/>
</Bowsprit>
<Trampoline>
<Vtx Seq="1" Y="2" X="-2.699"/>
<Vtx Seq="2" Y="6.438" X="-2.699"/>
<Vtx Seq="3" Y="6.438" X="2.699"/>
<Vtx Seq="4" Y="2" X="2.699"/>
</Trampoline>
</BoatShape>
<BoatShape ShapeID="5"/>
</BoatShapes>
<Boats>
<Boat Type="RC" SourceID="121" ShapeID="0" HullNum="RG01" StoweName="PRO" ShortName="PRO"
BoatName="Regardless">
<GPSposition Z="6.840" Y="7.800" X="0.000"/>
<FlagPosition Z="0.000" Y="7.800" X="0.000"/>
</Boat>
<Boat Type="Mark" SourceID="122" ShapeID="1" HullNum="LC05" StoweName="CON" ShortName="Constellation"
BoatName="Constellation">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat Type="Mark" SourceID="123" ShapeID="1" HullNum="LC04" StoweName="MIS" ShortName="Mischief"
BoatName="Mischief">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat Type="Mark" SourceID="124" ShapeID="1" HullNum="LC03" ShortName="Atalanta" BoatName="Atalanta">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat SourceID="125" ShapeID="1" StoweName="VOL" HullNum="LC01" ShortName="Volunteer"
BoatName="Volunteer">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat Type="Mark" SourceID="126" ShapeID="1" HullNum="LC13" StoweName="MS2" ShortName="Defender"
BoatName="Defender">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat Type="Mark" SourceID="128" ShapeID="1" HullNum="LC01" ShortName="Shamrock" BoatName="Shamrock">
<GPSposition Z="5.334" Y="3.804" X="0.000"/>
<FlagPosition Z="0.000" Y="3.426" X="0.000"/>
</Boat>
<Boat Type="Yacht" SourceID="101" ShapeID="4" HullNum="AC4501" StoweName="KOR" ShortName="TEAM KOREA"
BoatName="TEAM KOREA" Country="KOR">
<GPSposition Z="1.738" Y="0.625" X="0.001"/>
<MastTop Z="21.496" Y="4.233" X="0.000"/>
</Boat>
</Boats>
</BoatConfig>

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Race>
<RaceID>5326</RaceID>
<RaceType>FLEET</RaceType>
<CreationTimeDate>2017-04-19T15:30:00+1200</CreationTimeDate>
<RaceStartTime Postpone="false" Time="2017-04-19T15:33:00+1200"/>
<Participants>
<Yacht SourceID="121"/>
<Yacht SourceID="122"/>
<Yacht SourceID="123"/>
<Yacht SourceID="124"/>
<Yacht SourceID="125"/>
<Yacht SourceID="126"/>
</Participants>
<CompoundMarkSequence>
<Corner CompoundMarkID="1" SeqID="1"/>
<Corner CompoundMarkID="2" SeqID="2"/>
<Corner CompoundMarkID="4" SeqID="3"/>
<Corner CompoundMarkID="3" SeqID="4"/>
<Corner CompoundMarkID="4" SeqID="5"/>
<Corner CompoundMarkID="5" SeqID="6"/>
</CompoundMarkSequence>
<Course>
<CompoundMark CompoundMarkID="1" Name="Start Line">
<Mark SeqId="1" Name="PRO" TargetLat="32.296577" TargetLng="-64.854304" SourceID="101"/>
<Mark SeqId="2" Name="PIN" TargetLat="32.293771" TargetLng="-64.855242" SourceID="102"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2" Name="Marker 1">
<Mark Name="Marker1" TargetLat="32.293039" TargetLng="-64.843983" SourceID="103"/>
</CompoundMark>
<CompoundMark CompoundMarkID="3" Name="Windward Gate">
<Mark Name="WGL" SeqId="1" TargetLat="32.28468" TargetLng="-64.850045" SourceID="104"/>
<Mark Name="WGR" SeqId="2" TargetLat="32.280164" TargetLng="-64.847591" SourceID="105"/>
</CompoundMark>
<CompoundMark CompoundMarkID="4" Name="Leeward Gate">
<Mark Name="LGL" SeqId="1" TargetLat="32.309693" TargetLng="-64.835249" SourceID="106"/>
<Mark Name="LGR" SeqId="2" TargetLat="32.308046" TargetLng="-64.831785" SourceID="107"/>
</CompoundMark>
<CompoundMark CompoundMarkID="5" Name="Finish Line">
<Mark Name="FL" SeqId="1" TargetLat="32.317379" TargetLng="-64.839291" SourceID="108"/>
<Mark Name="FR" SeqId="2" TargetLat="32.317257" TargetLng="-64.83626" SourceID="109"/>
</CompoundMark>
</Course>
<CourseLimit>
<Limit Lat="32.313922" Lon="-64.837168" SeqID="1"/>
<Limit Lat="32.317379" Lon="-64.839291" SeqID="2"/>
<Limit Lat="32.317911" Lon="-64.836996" SeqID="3"/>
<Limit Lat="32.317257" Lon="-64.83626" SeqID="4"/>
<Limit Lat="32.304273" Lon="-64.822834" SeqID="5"/>
<Limit Lat="32.279097" Lon="-64.841545" SeqID="6"/>
<Limit Lat="32.279604" Lon="-64.849871" SeqID="7"/>
<Limit Lat="32.289545" Lon="-64.854162" SeqID="8"/>
<Limit Lat="32.290198" Lon="-64.858711" SeqID="9"/>
<Limit Lat="32.297164" Lon="-64.856394" SeqID="10"/>
<Limit Lat="32.296148" Lon="-64.849184" SeqID="11"/>
</CourseLimit>
</Race>

@ -1,20 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<RegattaConfig> <RegattaConfig>
<RegattaID>3</RegattaID> <RegattaID>3</RegattaID>
<RegattaName>New Zealand Test</RegattaName> <RegattaName>New Zealand Test</RegattaName>
<CourseName>North Head</CourseName> <CourseName>North Head</CourseName>
<CentralLatitude>-36.82791529</CentralLatitude> <CentralLatitude>-36.82791529</CentralLatitude>
<CentralLongitude>174.81218919</CentralLongitude> <CentralLongitude>174.81218919</CentralLongitude>
<CentralAltitude>0.00</CentralAltitude> <CentralAltitude>0.00</CentralAltitude>
<UtcOffset>12</UtcOffset> <UtcOffset>12</UtcOffset>
<MagneticVariation>14.1</MagneticVariation> <MagneticVariation>14.1</MagneticVariation>
</RegattaConfig> </RegattaConfig>

@ -48,7 +48,7 @@
<leg> <leg>
<name>Start to Mark 1</name> <name>Start to Mark 1</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
<longitude>-64.854304</longitude> <longitude>-64.854304</longitude>
@ -57,29 +57,29 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Mark 1 to Leeward Gate</name> <name>Mark 1 to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -88,13 +88,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Windward Gate</name> <name>Leeward Gate to Windward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -103,10 +103,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -115,13 +115,13 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Windward Gate to Leeward Gate</name> <name>Windward Gate to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -130,10 +130,10 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -142,13 +142,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Finish</name> <name>Leeward Gate to Finish</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -157,10 +157,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
<longitude>-64.839291</longitude> <longitude>-64.839291</longitude>
@ -169,7 +169,7 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
</legs> </legs>
@ -220,7 +220,7 @@
<longitude>-64.849184</longitude> <longitude>-64.849184</longitude>
</coordinate> </coordinate>
</boundaries> </boundaries>
<marker> <compoundMark>
<name>Start Line</name> <name>Start Line</name>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
@ -230,15 +230,15 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Mark</name> <name>Mark</name>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Windward Gate</name> <name>Windward Gate</name>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
@ -248,8 +248,8 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Leeward Gate</name> <name>Leeward Gate</name>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
@ -259,8 +259,8 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Finish Line</name> <name>Finish Line</name>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
@ -270,6 +270,6 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</course> </course>
</race> </race>

@ -88,7 +88,7 @@ public class BoatXMLReader extends XMLReader {
Element nBoats = (Element) doc.getElementsByTagName("Boats").item(0); Element nBoats = (Element) doc.getElementsByTagName("Boats").item(0);
for (int i = 0; i < nBoats.getChildNodes().getLength(); i++) { for (int i = 0; i < nBoats.getChildNodes().getLength(); i++) {
Node boat = nBoats.getChildNodes().item(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); readSingleBoat(boat);
} }
} }

@ -29,18 +29,4 @@ public class StreamedBoat extends Boat {
return sourceID; 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;
}
} }

@ -25,6 +25,7 @@ public class StreamedCourse extends Observable implements RaceDataSource {
this.boatXMLReader = boatXMLReader; this.boatXMLReader = boatXMLReader;
if (streamedCourseXMLReader != null && boatXMLReader != null) { if (streamedCourseXMLReader != null && boatXMLReader != null) {
this.boatXMLReader.setParticipants(streamedCourseXMLReader.getParticipants()); this.boatXMLReader.setParticipants(streamedCourseXMLReader.getParticipants());
System.out.println(streamedCourseXMLReader.getParticipants().size());
boatXMLReader.read(); boatXMLReader.read();
} }

@ -49,12 +49,12 @@ public class StreamedRace implements Runnable {
private void initialiseBoats() { private void initialiseBoats() {
Leg officialStart = legs.get(0); Leg officialStart = legs.get(0);
String name = officialStart.getName(); String name = officialStart.getName();
Marker endMarker = officialStart.getEndMarker(); Marker endCompoundMark = officialStart.getEndMarker();
for (Boat boat : startingBoats) { for (Boat boat : startingBoats) {
if (boat != null) { if (boat != null) {
Leg startLeg = new Leg(name, 0); Leg startLeg = new Leg(name, 0);
startLeg.setEndMarker(endMarker); startLeg.setEndMarker(endCompoundMark);
boat.setCurrentLeg(startLeg); boat.setCurrentLeg(startLeg);
} }
} }

@ -60,19 +60,19 @@
// public void initialiseBoats() { // public void initialiseBoats() {
// Leg officialStart = legs.get(0); // Leg officialStart = legs.get(0);
// String name = officialStart.getName(); // String name = officialStart.getName();
// Marker endMarker = officialStart.getEndMarker(); // CompoundMark endMarker = officialStart.getEndCompoundMark();
// //
// BoatInRace.setTrackPointTimeInterval(BoatInRace.getBaseTrackPointTimeInterval() / scaleFactor); // BoatInRace.setTrackPointTimeInterval(BoatInRace.getBaseTrackPointTimeInterval() / scaleFactor);
// //
// ArrayList<Marker> startMarkers = getSpreadStartingPositions(); // ArrayList<CompoundMark> startMarkers = getSpreadStartingPositions();
// for (int i = 0; i < startingBoats.size(); i++) { // for (int i = 0; i < startingBoats.size(); i++) {
// BoatInRace boat = startingBoats.get(i); // BoatInRace boat = startingBoats.get(i);
// if (boat != null) { // if (boat != null) {
// boat.setScaledVelocity(boat.getVelocity() * scaleFactor); // boat.setScaledVelocity(boat.getVelocity() * scaleFactor);
// Leg startLeg = new Leg(name, 0); // Leg startLeg = new Leg(name, 0);
// boat.setCurrentPosition(startMarkers.get(i).getAverageGPSCoordinate()); // boat.setCurrentPosition(startMarkers.get(i).getAverageGPSCoordinate());
// startLeg.setStartMarker(startMarkers.get(i)); // startLeg.setStartCompoundMark(startMarkers.get(i));
// startLeg.setEndMarker(endMarker); // startLeg.setEndCompoundMark(endMarker);
// startLeg.calculateDistance(); // startLeg.calculateDistance();
// boat.setCurrentLeg(startLeg); // boat.setCurrentLeg(startLeg);
// boat.setHeading(boat.calculateHeading()); // boat.setHeading(boat.calculateHeading());
@ -85,10 +85,10 @@
// * // *
// * @return list of starting positions // * @return list of starting positions
// */ // */
// public ArrayList<Marker> getSpreadStartingPositions() { // public ArrayList<CompoundMark> getSpreadStartingPositions() {
// //
// int nBoats = startingBoats.size(); // int nBoats = startingBoats.size();
// Marker marker = legs.get(0).getStartMarker(); // CompoundMark marker = legs.get(0).getStartCompoundMark();
// //
// GeodeticCalculator initialCalc = new GeodeticCalculator(); // GeodeticCalculator initialCalc = new GeodeticCalculator();
// initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); // initialCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude());
@ -100,12 +100,12 @@
// //
// GeodeticCalculator positionCalc = new GeodeticCalculator(); // GeodeticCalculator positionCalc = new GeodeticCalculator();
// positionCalc.setStartingGeographicPoint(marker.getMark1().getLongitude(), marker.getMark1().getLatitude()); // 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++) { // for (int i = 0; i < nBoats; i++) {
// positionCalc.setDirection(azimuth, distanceBetweenBoats); // positionCalc.setDirection(azimuth, distanceBetweenBoats);
// Point2D position = positionCalc.getDestinationGeographicPoint(); // 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 = new GeodeticCalculator();
// positionCalc.setStartingGeographicPoint(position); // positionCalc.setStartingGeographicPoint(position);
@ -147,7 +147,7 @@
// //update boat's distance travelled // //update boat's distance travelled
// boat.setDistanceTravelledInLeg(totalDistanceTravelled); // boat.setDistanceTravelledInLeg(totalDistanceTravelled);
// //Calculate boat's new position by adding the distance travelled onto the start point of the leg // //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())); // totalDistanceTravelled, boat.calculateAzimuth()));
// } // }
// } // }

@ -42,7 +42,7 @@
<leg> <leg>
<name>Start to Mark 1</name> <name>Start to Mark 1</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
<longitude>-64.854304</longitude> <longitude>-64.854304</longitude>
@ -51,29 +51,29 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Mark 1 to Leeward Gate</name> <name>Mark 1 to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -82,13 +82,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Windward Gate</name> <name>Leeward Gate to Windward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -97,10 +97,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -109,13 +109,13 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Windward Gate to Leeward Gate</name> <name>Windward Gate to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -124,10 +124,10 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -136,13 +136,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Finish</name> <name>Leeward Gate to Finish</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -151,10 +151,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
<longitude>-64.839291</longitude> <longitude>-64.839291</longitude>
@ -163,7 +163,7 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
</legs> </legs>
@ -214,7 +214,7 @@
<longitude>-64.849184</longitude> <longitude>-64.849184</longitude>
</coordinate> </coordinate>
</boundaries> </boundaries>
<marker> <compoundMark>
<name>Start Line</name> <name>Start Line</name>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
@ -224,15 +224,15 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Mark</name> <name>Mark</name>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Windward Gate</name> <name>Windward Gate</name>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
@ -242,8 +242,8 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Leeward Gate</name> <name>Leeward Gate</name>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
@ -253,8 +253,8 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Finish Line</name> <name>Finish Line</name>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
@ -264,6 +264,6 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</course> </course>
</race> </race>

@ -1,47 +1,47 @@
package seng302.Mock; //package seng302.Mock;
//
import org.junit.Before; //import org.junit.Before;
import org.junit.Test; //import org.junit.Test;
//
import java.util.HashMap; //import java.util.HashMap;
import java.util.Map; //import java.util.Map;
//
import static org.junit.Assert.assertEquals; //import static org.junit.Assert.assertEquals;
//
/** ///**
* Created by jjg64 on 21/04/17. // * Created by jjg64 on 21/04/17.
*/ // */
public class BoatsXMLTest { //public class BoatsXMLTest {
private BoatXMLReader boatXMLReader; // private BoatXMLReader boatXMLReader;
//
@Before // @Before
public void setup() { // public void setup() {
try { // try {
boatXMLReader = new BoatXMLReader("mockXML/boatXML/boatTest.xml", false); // boatXMLReader = new BoatXMLReader("mockXML/boatXML/boatTest.xml", false);
} catch (Exception e) { // } catch (Exception e) {
e.printStackTrace(); // e.printStackTrace();
//fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder"); // //fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder");
} // }
} // }
//
@Test // @Test
public void testInvalidParticipant() { // public void testInvalidParticipant() {
Map<Integer, StreamedBoat> inputParticipants = new HashMap<>(); // Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
inputParticipants.put(420, new StreamedBoat(420)); // inputParticipants.put(420, new StreamedBoat(420));
boatXMLReader.setParticipants(inputParticipants); // boatXMLReader.setParticipants(inputParticipants);
boatXMLReader.read(); // boatXMLReader.read();
assertEquals(boatXMLReader.getBoats().size(), 0); // assertEquals(boatXMLReader.getBoats().size(), 0);
} // }
//
@Test // @Test
public void testValidParticipant() { // public void testValidParticipant() {
Map<Integer, StreamedBoat> inputParticipants = new HashMap<>(); // Map<Integer, StreamedBoat> inputParticipants = new HashMap<>();
inputParticipants.put(101, new StreamedBoat(101)); // inputParticipants.put(101, new StreamedBoat(101));
boatXMLReader.setParticipants(inputParticipants); // boatXMLReader.setParticipants(inputParticipants);
boatXMLReader.read(); // boatXMLReader.read();
assertEquals(boatXMLReader.getBoats().size(), 1); // assertEquals(boatXMLReader.getBoats().size(), 1);
StreamedBoat boat = (StreamedBoat) boatXMLReader.getBoats().get(0); // StreamedBoat boat = (StreamedBoat) boatXMLReader.getBoats().get(0);
assertEquals(boat.getSourceID(), 101); // assertEquals(boat.getSourceID(), 101);
} // }
//
} //}

@ -1,26 +1,26 @@
package seng302.Mock; //package seng302.Mock;
//
import org.junit.Test; //import org.junit.Test;
import org.xml.sax.SAXException; //import org.xml.sax.SAXException;
//
import javax.xml.parsers.ParserConfigurationException; //import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; //import java.io.IOException;
import java.text.ParseException; //import java.text.ParseException;
//
/** ///**
* Created by jjg64 on 1/05/17. // * Created by jjg64 on 1/05/17.
*/ // */
public class FailBoatXMLTest { //public class FailBoatXMLTest {
private final String path = "mockXML/boatXML/"; // private final String path = "mockXML/boatXML/";
//
@Test(expected = NumberFormatException.class) // @Test(expected = NumberFormatException.class)
public void invalidSourceID() throws SAXException, ParserConfigurationException, ParseException, IOException { // public void invalidSourceID() throws SAXException, ParserConfigurationException, ParseException, IOException {
new BoatXMLReader(path + "invalidSourceID.xml"); // new BoatXMLReader(path + "invalidSourceID.xml");
} // }
//
@Test(expected = NullPointerException.class) // @Test(expected = NullPointerException.class)
public void insufficientInformation() throws SAXException, ParserConfigurationException, ParseException, IOException { // public void insufficientInformation() throws SAXException, ParserConfigurationException, ParseException, IOException {
new BoatXMLReader(path + "insufficientInformation.xml"); // new BoatXMLReader(path + "insufficientInformation.xml");
} // }
//
} //}

@ -87,8 +87,8 @@ public class StreamedRaceTest {
GPSCoordinate topLeft = streamedCourseXMLReader.getMapTopLeft(); GPSCoordinate topLeft = streamedCourseXMLReader.getMapTopLeft();
GPSCoordinate bottomRight = streamedCourseXMLReader.getMapBottomRight(); GPSCoordinate bottomRight = streamedCourseXMLReader.getMapBottomRight();
for(Marker marker: streamedCourseXMLReader.getMarkers()) { for(Marker compoundMark : streamedCourseXMLReader.getMarkers()) {
GPSCoordinate centre = marker.getAverageGPSCoordinate(); GPSCoordinate centre = compoundMark.getAverageGPSCoordinate();
assertTrue(centre.getLatitude() < bottomRight.getLatitude()); assertTrue(centre.getLatitude() < bottomRight.getLatitude());
assertTrue(centre.getLatitude() > topLeft.getLatitude()); assertTrue(centre.getLatitude() > topLeft.getLatitude());
assertTrue(centre.getLongitude() > bottomRight.getLongitude()); assertTrue(centre.getLongitude() > bottomRight.getLongitude());

@ -17,8 +17,8 @@
// */ // */
//public class ConstantVelocityRaceTest { //public class ConstantVelocityRaceTest {
// //
// Marker START_MARKER = new Marker(new GPSCoordinate(0, 0)); // CompoundMark START_MARKER = new CompoundMark(new GPSCoordinate(0, 0));
// Marker END_MARKER = new Marker(new GPSCoordinate(10, 10)); // CompoundMark END_MARKER = new CompoundMark(new GPSCoordinate(10, 10));
// Leg START_LEG = new Leg("Start", START_MARKER, END_MARKER, 0); // Leg START_LEG = new Leg("Start", START_MARKER, END_MARKER, 0);
// //
// int ONE_HOUR = 3600000; //1 hour in milliseconds // int ONE_HOUR = 3600000; //1 hour in milliseconds

@ -14,7 +14,7 @@ import static seng302.Model.Leg.NM_TO_METERS;
*/ */
public class LegTest { 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 @Test
public void calculateDistanceHandles5nmNorth() { public void calculateDistanceHandles5nmNorth() {
@ -23,7 +23,7 @@ public class LegTest {
calc.setDirection(0, 5 * NM_TO_METERS); calc.setDirection(0, 5 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); 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); assertEquals(test.getDistance(), 5, 1e-8);
} }
@ -34,7 +34,7 @@ public class LegTest {
calc.setDirection(90, 12 * NM_TO_METERS); calc.setDirection(90, 12 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); 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); assertEquals(test.getDistance(), 12, 1e-8);
} }
@ -45,7 +45,7 @@ public class LegTest {
calc.setDirection(180, 0.5 * NM_TO_METERS); calc.setDirection(180, 0.5 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); 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); assertEquals(test.getDistance(), 0.5, 1e-8);
} }
@ -56,14 +56,14 @@ public class LegTest {
calc.setDirection(-90, 0.1 * NM_TO_METERS); calc.setDirection(-90, 0.1 * NM_TO_METERS);
Marker endMarker = getEndMarker(calc.getDestinationGeographicPoint()); 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); assertEquals(test.getDistance(), 0.1, 1e-8);
} }
@Test @Test
public void calculateDistanceHandlesZeroDifference() { 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); assertEquals(test.getDistance(), 0, 1e-8);
} }

@ -41,7 +41,7 @@
<leg> <leg>
<name>Start to Mark 1</name> <name>Start to Mark 1</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
<longitude>-64.854304</longitude> <longitude>-64.854304</longitude>
@ -50,29 +50,29 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Mark 1 to Leeward Gate</name> <name>Mark 1 to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -81,13 +81,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Windward Gate</name> <name>Leeward Gate to Windward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -96,10 +96,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -108,13 +108,13 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Windward Gate to Leeward Gate</name> <name>Windward Gate to Leeward Gate</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
<longitude>-64.850045</longitude> <longitude>-64.850045</longitude>
@ -123,10 +123,10 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -135,13 +135,13 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
<leg> <leg>
<name>Leeward Gate to Finish</name> <name>Leeward Gate to Finish</name>
<start> <start>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
<longitude>-64.835249</longitude> <longitude>-64.835249</longitude>
@ -150,10 +150,10 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</start> </start>
<finish> <finish>
<marker> <compoundMark>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
<longitude>-64.839291</longitude> <longitude>-64.839291</longitude>
@ -162,7 +162,7 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</finish> </finish>
</leg> </leg>
</legs> </legs>
@ -213,7 +213,7 @@
<longitude>-64.849184</longitude> <longitude>-64.849184</longitude>
</coordinate> </coordinate>
</boundaries> </boundaries>
<marker> <compoundMark>
<name>Start Line</name> <name>Start Line</name>
<coordinate> <coordinate>
<latitude>32.296577</latitude> <latitude>32.296577</latitude>
@ -223,15 +223,15 @@
<latitude>32.293771</latitude> <latitude>32.293771</latitude>
<longitude>-64.855242</longitude> <longitude>-64.855242</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Mark</name> <name>Mark</name>
<coordinate> <coordinate>
<latitude>32.293039</latitude> <latitude>32.293039</latitude>
<longitude>-64.843983</longitude> <longitude>-64.843983</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Windward Gate</name> <name>Windward Gate</name>
<coordinate> <coordinate>
<latitude>32.284680</latitude> <latitude>32.284680</latitude>
@ -241,8 +241,8 @@
<latitude>32.280164</latitude> <latitude>32.280164</latitude>
<longitude>-64.847591</longitude> <longitude>-64.847591</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Leeward Gate</name> <name>Leeward Gate</name>
<coordinate> <coordinate>
<latitude>32.309693</latitude> <latitude>32.309693</latitude>
@ -252,8 +252,8 @@
<latitude>32.308046</latitude> <latitude>32.308046</latitude>
<longitude>-64.831785</longitude> <longitude>-64.831785</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
<marker> <compoundMark>
<name>Finish Line</name> <name>Finish Line</name>
<coordinate> <coordinate>
<latitude>32.317379</latitude> <latitude>32.317379</latitude>
@ -263,6 +263,6 @@
<latitude>32.317257</latitude> <latitude>32.317257</latitude>
<longitude>-64.836260</longitude> <longitude>-64.836260</longitude>
</coordinate> </coordinate>
</marker> </compoundMark>
</course> </course>
</race> </race>

Loading…
Cancel
Save