Event takes string and sets time of race

- RaceXmlReaders can handle strings now
- Not working with visualiser, gps coords may be worng

#story[881]
main
Erika Savell 9 years ago
parent 91b1773703
commit ffa3d530ae

@ -6,13 +6,14 @@ import javafx.stage.Stage;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.DataInput.*; import seng302.DataInput.*;
import seng302.Model.Event; import seng302.Model.Event;
import seng302.Model.StreamedCourseXMLException; import seng302.Exceptions.StreamedCourseXMLException;
import seng302.Model.StreamedCourseXMLReader; import seng302.DataInput.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.ParseException; import java.text.ParseException;
@ -30,6 +31,7 @@ public class App extends Application {
static String readFile(String path, Charset encoding) throws IOException { static String readFile(String path, Charset encoding) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path)); byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding); return new String(encoded, encoding);
@ -38,21 +40,16 @@ public class App extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
try { try {
RegattaDataSource regattaData = new RegattaXMLReader("mockXML/regattaTest.xml");
BoatDataSource boatData = new BoatXMLReader("mockXML/boatTest.xml"); String regattaXML = readFile("mock/src/main/resources/mockXML/regattaTest.xml", StandardCharsets.UTF_8);
RaceDataSource raceData = new StreamedCourseXMLReader("mockXML/raceTest.xml", boatData); String raceXML = readFile("mock/src/main/resources/mockXML/raceTest.xml", StandardCharsets.UTF_8);
Event raceEvent = new Event(raceData, regattaData, boatData); 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();
} catch (ParseException e) {
e.printStackTrace();
} catch (StreamedCourseXMLException e) {
e.printStackTrace();
} }
} }
} }

@ -66,8 +66,6 @@ public class BoatData {
StreamResult result = new StreamResult(stringWriter); StreamResult result = new StreamResult(stringWriter);
transformer.transform(source, result); transformer.transform(source, result);
System.out.println(stringWriter.toString());
return stringWriter.toString(); return stringWriter.toString();

@ -124,7 +124,7 @@ public class RaceData {
*/ */
private void appendRaceStartTime() { private void appendRaceStartTime() {
Element startTimeElement = doc.createElement("RaceStartTime"); Element startTimeElement = doc.createElement("RaceStartTime");
startTimeElement.setAttribute("Time", (toTruncatedString(creationTimeDate.plusMinutes(0)))); startTimeElement.setAttribute("Time", (toTruncatedString(creationTimeDate.plusMinutes(3))));
startTimeElement.setAttribute("Postpone", "false"); startTimeElement.setAttribute("Postpone", "false");
rootElement.appendChild(startTimeElement); rootElement.appendChild(startTimeElement);
} }
@ -232,19 +232,19 @@ public class RaceData {
rootElement.appendChild(courseLimitElement); rootElement.appendChild(courseLimitElement);
} }
/** /**
* Format time data and return it. * Format time data and return it.
* @param time time data. * @param time time data.
* @return formatted time data. * @return formatted time data.
*/ */
private String toTruncatedString(ZonedDateTime time) { private String toTruncatedString(ZonedDateTime time) {
DateTimeFormatter dateFormat = DateTimeFormatter.ISO_OFFSET_DATE_TIME; DateTimeFormatter dateFormat = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
String text = dateFormat.format(time); String text = dateFormat.format(time);
return text; return text;
}
}
} }

@ -1,376 +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.*; import seng302.Model.*;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.*;
/** /**
* Created by fwy13 on 26/03/2017. * Created by jjg64 on 21/04/17.
* @deprecated please use {@link seng302.Model.StreamedCourseXMLReader}
*/ */
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<CompoundMark> compoundMarks = 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 country = getTextValueOfNode((Element) nBoats.item(i), "abbr");
int sourceID = Integer.parseInt(getTextValueOfNode((Element) nBoats.item(i), "sourceID"));
Boat boat = new Boat(sourceID, name, country);
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);
CompoundMark compoundMark = getMarker((Element) nMarkers.item(i));
if (compoundMark.getName() != null) compoundMarks.add(compoundMark);
}
}
/** 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");
CompoundMark startCompoundMark = getMarker(start);
NodeList finish = ((Element) nLegs.item(i)).getElementsByTagName("finish");
CompoundMark finishCompoundMark = getMarker(finish);
legs.add(new Leg(label, startCompoundMark, finishCompoundMark, 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 CompoundMark 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 CompoundMark 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 CompoundMark 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 CompoundMark 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))); break;
side2 = getCoordinates((Element) nCoordinates.item(1)); case 2: marker = new CompoundMark(getMark((Element)nMarks.item(0)), getMark((Element)nMarks.item(1))); break;
} else { default: throw new StreamedCourseXMLException();
side2 = side1;
} }
NodeList name = markerNode.getElementsByTagName("name");
return null;//name.getLength() == 1 ? new CompoundMark(getTextValueOfNode((Element) markerNode, "name"), side1, side2) : new CompoundMark(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() { private void readCourseLimit() {
return mark; 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 getStartPt1() {
return startPt1;
}
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<CompoundMark> getCompoundMarks() { public String getRaceType() {
return compoundMarks; return raceType;
} }
public String getRaceType() { public boolean isPostpone() {
return "FLEET"; return postpone;
} }
@Override public List<Boat> getBoats() {
public ZonedDateTime getZonedDateTime() { return new ArrayList<>(participants.values());
return null;
} }
} }

@ -3,6 +3,7 @@ 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.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;
@ -10,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.
@ -26,13 +28,28 @@ 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

@ -1,4 +1,4 @@
package seng302.Model; package seng302.Exceptions;
/** /**
* Created by cbt24 on 25/04/17. * Created by cbt24 on 25/04/17.

@ -27,7 +27,7 @@ public class Boat {
* @param country nam abbreviation * @param country nam abbreviation
*/ */
public Boat(int sourceID, String name, String country) { public Boat(int sourceID, String name, String country) {
this.velocity = 5; // TODO - please dont commit this.velocity = 30; // TODO - please dont commit
this.country = this.country; this.country = this.country;
this.name = name; this.name = name;
this.sourceID = sourceID; this.sourceID = sourceID;

@ -1,21 +1,19 @@
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.BoatDataSource;
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 javax.xml.parsers.ParserConfigurationException;
import java.io.*; import java.io.*;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.ParseException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/** /**
@ -24,59 +22,87 @@ import java.nio.file.Paths;
public class Event { public class Event {
RaceDataSource raceDataSource; RaceDataSource raceDataSource;
String raceXML;
RegattaDataSource regattaDataSource; RegattaDataSource regattaDataSource;
String regattaXML;
BoatDataSource boatDataSource; BoatDataSource boatDataSource;
String boatXML;
MockOutput mockOutput; MockOutput mockOutput;
public Event(RaceDataSource raceData, RegattaDataSource regattaData, BoatDataSource boatDataSource) {
this.raceDataSource = raceData; public Event(String raceXML, String regattaXML, String boatXML) {
this.regattaDataSource = regattaData;
this.boatDataSource = boatDataSource; this.raceXML = getRaceAtCurrentTime(raceXML);
this.boatXML = boatXML;
this.regattaXML = regattaXML;
try { try {
boatDataSource = new BoatXMLReader(boatXML);
raceDataSource = new RaceXMLReader(this.raceXML, boatDataSource);
regattaDataSource = new RegattaXMLReader(regattaXML);
mockOutput = new MockOutput(); mockOutput = new MockOutput();
new Thread(mockOutput).start(); new Thread(mockOutput).start();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (StreamedCourseXMLException e) {
e.printStackTrace();
} }
}
private String getRaceAtCurrentTime(String raceXML) {
ZonedDateTime creationTime = ZonedDateTime.now();
return raceXML.replace("CREATION_TIME", toTruncatedString(creationTime))
.replace("START_TIME", toTruncatedString(creationTime.plusMinutes(3)));
} }
/** /**
* Send the initial race data and then begin race simulation * Send the initial race data and then begin race simulation
*/ */
public void start() { public void start() {
sendXMLs(); sendXMLs();
int scaleFactor = 5;//TEMP - was 15. int scaleFactor = 10;//TEMP - was 15.
Race newRace = new Race(raceDataSource, scaleFactor, mockOutput); Race newRace = new Race(raceDataSource, scaleFactor, mockOutput);
new Thread((newRace)).start(); new Thread((newRace)).start();
} }
private void sendXMLs() { private void sendXMLs() {
try {
System.out.println("Sending Regatta"); System.out.println("Sending Regatta");
String regattaData = readFile("mock/src/main/resources/mockXML/regattaTest.xml", StandardCharsets.UTF_8); mockOutput.setRegattaXml(regattaXML);
mockOutput.setRegattaXml(regattaData); mockOutput.parseXMLString(regattaXML, 26);
mockOutput.parseXMLString(regattaData, 26);
System.out.println("Sending Race");
mockOutput.setRaceXml(raceXML);
System.out.println(raceXML);
mockOutput.parseXMLString(raceXML, 26);
System.out.println("Sending Boat");
mockOutput.setBoatsXml(boatXML);
mockOutput.parseXMLString(boatXML, 26);
System.out.println("Sending Race");
String raceData = readFile("mock/src/main/resources/mockXML/raceTest.xml", StandardCharsets.UTF_8);
mockOutput.setRaceXml(raceData);
mockOutput.parseXMLString(raceData, 26);
System.out.println("Sending Boat");
String boatData = readFile("mock/src/main/resources/mockXML/boatTest.xml", StandardCharsets.UTF_8);
mockOutput.setBoatsXml(boatData);
mockOutput.parseXMLString(boatData, 26);
} catch (IOException e) {
e.printStackTrace();
}
} }
static String readFile(String path, Charset encoding) throws IOException { /**
byte[] encoded = Files.readAllBytes(Paths.get(path)); * Format time data and return it.
return new String(encoded, encoding); * @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;
} }
} }

@ -25,13 +25,13 @@ import java.util.Random;
* 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 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 = 25;
protected int PRERACE_TIME = 180000; //time in milliseconds to pause during pre-race. At the moment, 3 minutes protected int PRERACE_TIME = 1800; //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 countdownFinish = false;
protected boolean runRace = true; protected boolean runRace = true;
@ -59,7 +59,7 @@ public class Race implements Runnable {
this.scaleFactor = scaleFactor; this.scaleFactor = scaleFactor;
this.mockOutput = mockOutput; this.mockOutput = mockOutput;
//TODO refactor
this.startTime = System.currentTimeMillis() + (this.PRERACE_TIME / this.scaleFactor); this.startTime = System.currentTimeMillis() + (this.PRERACE_TIME / this.scaleFactor);
if (startingBoats != null && startingBoats.size() > 0) { if (startingBoats != null && startingBoats.size() > 0) {
@ -83,7 +83,6 @@ public class Race implements Runnable {
public static GPSCoordinate calculatePosition(GPSCoordinate oldCoordinates, double distanceTravelled, double azimuth) { public static GPSCoordinate calculatePosition(GPSCoordinate oldCoordinates, double distanceTravelled, double azimuth) {
//Find new coordinate using current heading and distance //Find new coordinate using current heading and distance
GeodeticCalculator geodeticCalculator = new GeodeticCalculator(); GeodeticCalculator geodeticCalculator = new GeodeticCalculator();
//Load start point into calculator //Load start point into calculator
Point2D startPoint = new Point2D.Double(oldCoordinates.getLongitude(), oldCoordinates.getLatitude()); Point2D startPoint = new Point2D.Double(oldCoordinates.getLongitude(), oldCoordinates.getLatitude());
@ -93,6 +92,7 @@ public class Race implements Runnable {
//get new point //get new point
Point2D endPoint = geodeticCalculator.getDestinationGeographicPoint(); Point2D endPoint = geodeticCalculator.getDestinationGeographicPoint();
System.out.println(endPoint.getX());
return new GPSCoordinate(endPoint.getY(), endPoint.getX()); return new GPSCoordinate(endPoint.getY(), endPoint.getX());
} }
@ -121,6 +121,7 @@ public class Race implements Runnable {
@Override @Override
public void handle(long arg0) { public void handle(long arg0) {
timeLeft = startTime - currentTime; timeLeft = startTime - currentTime;
System.out.println(timeLeft);
ArrayList<BoatStatus> boatStatuses = new ArrayList<>(); ArrayList<BoatStatus> boatStatuses = new ArrayList<>();
//For each boat, we update it's position, and generate a BoatLocationMessage. //For each boat, we update it's position, and generate a BoatLocationMessage.
for (int i = 0; i < startingBoats.size(); i++) { for (int i = 0; i < startingBoats.size(); i++) {
@ -165,6 +166,7 @@ public class Race implements Runnable {
for (Boat boat : startingBoats) { for (Boat boat : startingBoats) {
boat.setStarted(true); boat.setStarted(true);
System.out.println(boat.getName());
} }
new AnimationTimer() { new AnimationTimer() {
@ -208,6 +210,7 @@ public class Race implements Runnable {
} }
boatOffset = (boatOffset + 1) % (startingBoats.size()); 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. 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.
System.out.println(raceStatus.getBoatStatuses().get(0).getLegNumber());
mockOutput.parseRaceStatus(raceStatus); mockOutput.parseRaceStatus(raceStatus);
} }
} }

@ -1,274 +0,0 @@
package seng302.Model;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import seng302.DataInput.BoatDataSource;
import seng302.DataInput.RaceDataSource;
import seng302.DataInput.XMLReader;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.text.ParseException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
* Created by jjg64 on 21/04/17.
*/
public class StreamedCourseXMLReader extends XMLReader implements RaceDataSource {
private static final double COORDINATEPADDING = 0.000;
private GPSCoordinate mapTopLeft, mapBottomRight;
private final List<GPSCoordinate> boundary = 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;
/**
* Constructor for Streamed Race XML
* @param filePath path of the file
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/
public StreamedCourseXMLReader(String filePath, BoatDataSource boatData) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
this(filePath, boatData, true);
}
/**
* Constructor for Streamed Race XML
* @param filePath file path to read
* @param read whether or not to read and store the files straight away.
* @throws IOException error
* @throws SAXException error
* @throws ParserConfigurationException error
* @throws ParseException error
* @throws StreamedCourseXMLException error
*/
public StreamedCourseXMLReader(String filePath, BoatDataSource boatData, boolean read) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException {
super(filePath);
this.boats = boatData.getBoats();
this.marks = boatData.getMarkerBoats();
if (read) {
read();
}
}
/**
* reads
* @throws StreamedCourseXMLException error
*/
private void read() throws StreamedCourseXMLException {
readRace();
readParticipants();
readCourse();
}
/**
* reads a race
*/
private void readRace() {
DateTimeFormatter dateFormat = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
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");
raceID = Integer.parseInt(getTextValueOfNode(settings, "RaceID"));
raceType = getTextValueOfNode(settings, "RaceType");
creationTimeDate = ZonedDateTime.parse(getTextValueOfNode(settings, "CreationTimeDate"), dateFormat);
if (raceTimeTag.getNamedItem("Time") != null) raceStartTime = ZonedDateTime.parse(raceTimeTag.getNamedItem("Time").getTextContent(), dateFormat);
else raceStartTime = ZonedDateTime.parse(raceTimeTag.getNamedItem("Start").getTextContent(), dateFormat);
postpone = Boolean.parseBoolean(raceTimeTag.getNamedItem("Postpone").getTextContent());
}
private void readParticipants() {
Element nParticipants = (Element) doc.getElementsByTagName("Participants").item(0);
nParticipants.getChildNodes().getLength();
for (int i = 0; i < nParticipants.getChildNodes().getLength(); i++) {
int sourceID;
Node yacht = nParticipants.getChildNodes().item(i);
if (yacht.getNodeName().equals("Yacht")) {
if (exists(yacht, "SourceID")) {
sourceID = Integer.parseInt(yacht.getAttributes().getNamedItem("SourceID").getTextContent());
participants.put(sourceID, boats.get(sourceID));
}
}
}
}
/**
* reads a course
* @throws StreamedCourseXMLException error
*/
private void readCourse() throws StreamedCourseXMLException {
readCompoundMarks();
readCompoundMarkSequence();
readCourseLimit();
}
/**
* Indexes CompoundMark elements by their ID for use in generating the course, and populates list of Markers.
* @see CompoundMark
*/
private void readCompoundMarks() throws StreamedCourseXMLException {
Element nCourse = (Element) doc.getElementsByTagName("Course").item(0);
for(int i = 0; i < nCourse.getChildNodes().getLength(); i++) {
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));
}
}
}
/**
* Generates a CompoundMark from the CompoundMark element with given ID.
* @param compoundMarkID index of required CompoundMark element
* @return generated CompoundMark
* @throws StreamedCourseXMLException if CompoundMark element contains unhandled number of compoundMarks
* @see CompoundMark
*/
private CompoundMark getCompoundMark(int compoundMarkID) throws StreamedCourseXMLException {
Element compoundMark = compoundMarkMap.get(compoundMarkID);
NodeList nMarks = compoundMark.getElementsByTagName("Mark");
CompoundMark marker;
switch(nMarks.getLength()) {
case 1: marker = new CompoundMark(getMark((Element)nMarks.item(0))); break;
case 2: marker = new CompoundMark(getMark((Element)nMarks.item(0)), getMark((Element)nMarks.item(1))); break;
default: throw new StreamedCourseXMLException();
}
return marker;
}
private Mark getMark(Element mark) {
int sourceID = Integer.parseInt(mark.getAttribute("SourceID"));
System.out.println(marks.get(sourceID).getPosition());
return marks.get(sourceID);
}
/**
* Reads "compoundMarkID" attribute of CompoundMark or Corner element
* @param element with "compoundMarkID" attribute
* @return value of "compoundMarkID" attribute
*/
private int getCompoundMarkID(Element element) {
return Integer.parseInt(element.getAttribute("CompoundMarkID"));
}
/**
* Reads "name" attribute of CompoundMark element with corresponding CompoundMarkID
* @param compoundMarkID unique ID for CompoundMark element
* @return value of "name" attribute
*/
private String getCompoundMarkName(int compoundMarkID) {
return compoundMarkMap.get(compoundMarkID).getAttribute("Name");
}
/**
* Populates list of legs given CompoundMarkSequence element and referenced CompoundMark elements.
* @throws StreamedCourseXMLException if compoundMarks cannot be resolved from CompoundMark
*/
private void readCompoundMarkSequence() throws StreamedCourseXMLException {
Element nCompoundMarkSequence = (Element) doc.getElementsByTagName("CompoundMarkSequence").item(0);
NodeList nCorners = nCompoundMarkSequence.getElementsByTagName("Corner");
Element markXML = (Element)nCorners.item(0);
CompoundMark lastCompoundMark = getCompoundMark(getCompoundMarkID(markXML));
String legName = getCompoundMarkName(getCompoundMarkID(markXML));
for(int i = 1; i < nCorners.getLength(); i++) {
markXML = (Element)nCorners.item(i);
CompoundMark currentCompoundMark = getCompoundMark(getCompoundMarkID(markXML));
legs.add(new Leg(legName, lastCompoundMark, currentCompoundMark, i-1));
lastCompoundMark = currentCompoundMark;
legName = getCompoundMarkName(getCompoundMarkID(markXML));
}
}
private void readCourseLimit() {
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));
}
}
double maxLatitude = boundary.stream().max(Comparator.comparingDouble(GPSCoordinate::getLatitude)).get().getLatitude() + COORDINATEPADDING;
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;
mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude);
}
public List<GPSCoordinate> getBoundary() {
return boundary;
}
public GPSCoordinate getMapTopLeft() {
return mapTopLeft;
}
public GPSCoordinate getMapBottomRight() {
return mapBottomRight;
}
public List<Leg> getLegs() {
return legs;
}
public List<CompoundMark> getCompoundMarks() { return compoundMarks; }
public Double getPadding() {
return COORDINATEPADDING;
}
public ZonedDateTime getCreationTimeDate() {
return creationTimeDate;
}
public ZonedDateTime getZonedDateTime() {
return raceStartTime;
}
public int getRaceId() {
return raceID;
}
public String getRaceType() {
return raceType;
}
public boolean isPostpone() {
return postpone;
}
public List<Boat> getBoats() {
return new ArrayList<>(participants.values());
}
}

@ -2,8 +2,8 @@
<Race> <Race>
<RaceID>5326</RaceID> <RaceID>5326</RaceID>
<RaceType>FLEET</RaceType> <RaceType>FLEET</RaceType>
<CreationTimeDate>2017-05-10T12:35:19+1200</CreationTimeDate> <CreationTimeDate>CREATION_TIME</CreationTimeDate>
<RaceStartTime Postpone="false" Time="2017-05-10T12:35:19+1200"/> <RaceStartTime Postpone="false" Time="START_TIME"/>
<Participants> <Participants>
<Yacht SourceID="121"/> <Yacht SourceID="121"/>
<Yacht SourceID="122"/> <Yacht SourceID="122"/>

@ -4,7 +4,6 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.DataInput.RaceDataSource; import seng302.DataInput.RaceDataSource;
import seng302.DataInput.RaceXMLReader;
import seng302.DataInput.RegattaDataSource; import seng302.DataInput.RegattaDataSource;
import seng302.DataInput.RegattaXMLReader; import seng302.DataInput.RegattaXMLReader;

@ -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;
}
} }

@ -33,6 +33,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();
} }

@ -219,7 +219,6 @@ public class VisualiserInput implements Runnable {
//If no heartbeat has been received in more the heartbeat period //If no heartbeat has been received in more the heartbeat period
//then the connection will need to be restarted. //then the connection will need to be restarted.
System.out.println("time since last heartbeat: " + timeSinceHeartbeat());//TEMP REMOVE
long heartBeatPeriod = 10 * 1000; long heartBeatPeriod = 10 * 1000;
if (timeSinceHeartbeat() > heartBeatPeriod) { if (timeSinceHeartbeat() > heartBeatPeriod) {
System.out.println("Connection has stopped, trying to reconnect."); System.out.println("Connection has stopped, trying to reconnect.");
@ -369,6 +368,8 @@ public class VisualiserInput implements Runnable {
BoatLocation boatLocation = (BoatLocation) message; BoatLocation boatLocation = (BoatLocation) message;
//System.out.println("Boat Location!"); //System.out.println("Boat Location!");
//System.out.println(boatLocation.getSourceID());
if (this.boatLocationMap.containsKey(boatLocation.getSourceID())) { if (this.boatLocationMap.containsKey(boatLocation.getSourceID())) {
//If our boatlocation map already contains a boat location message for this boat, check that the new message is actually for a later timestamp (i.e., newer). //If our boatlocation map already contains a boat location message for this boat, check that the new message is actually for a later timestamp (i.e., newer).
if (boatLocation.getTime() > this.boatLocationMap.get(boatLocation.getSourceID()).getTime()){ if (boatLocation.getTime() > this.boatLocationMap.get(boatLocation.getSourceID()).getTime()){

Loading…
Cancel
Save