Event takes string and sets time of race
- RaceXmlReaders can handle strings now - Not working with visualiser, gps coords may be worng #story[881]
This commit is contained in:
@@ -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,348 +1,229 @@
|
|||||||
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");
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
||||||
* Read all the boats in the XML file
|
Element nParticipants = (Element) doc.getElementsByTagName("Participants").item(0);
|
||||||
*/
|
nParticipants.getChildNodes().getLength();
|
||||||
public void readBoats() {
|
for (int i = 0; i < nParticipants.getChildNodes().getLength(); i++) {
|
||||||
//get all boats
|
int sourceID;
|
||||||
NodeList nBoats = doc.getElementsByTagName("boat");
|
Node yacht = nParticipants.getChildNodes().item(i);
|
||||||
|
if (yacht.getNodeName().equals("Yacht")) {
|
||||||
for (int i = 0; i < nBoats.getLength(); i++) {
|
if (exists(yacht, "SourceID")) {
|
||||||
String name = getTextValueOfNode((Element) nBoats.item(i), "name");
|
sourceID = Integer.parseInt(yacht.getAttributes().getNamedItem("SourceID").getTextContent());
|
||||||
String country = getTextValueOfNode((Element) nBoats.item(i), "abbr");
|
participants.put(sourceID, boats.get(sourceID));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all the boats in the XML file
|
|
||||||
*/
|
|
||||||
public void readMarkers() {
|
|
||||||
//get all boats
|
|
||||||
NodeList nMarkers = doc.getElementsByTagName("marker");
|
|
||||||
|
|
||||||
for (int i = 0; i < nMarkers.getLength(); i++) {
|
|
||||||
CompoundMark compoundMark = getMarker((Element) nMarkers.item(i));
|
|
||||||
if (compoundMark.getName() != null) compoundMarks.add(compoundMark);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all the legs in the XML file
|
* reads a course
|
||||||
|
* @throws StreamedCourseXMLException error
|
||||||
*/
|
*/
|
||||||
public void readLegs() {
|
private void readCourse() throws StreamedCourseXMLException {
|
||||||
//get all legs
|
readCompoundMarks();
|
||||||
NodeList nLegs = doc.getElementsByTagName("leg");
|
readCompoundMarkSequence();
|
||||||
|
readCourseLimit();
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < nLegs.getLength(); i++) {
|
/**
|
||||||
String label = getTextValueOfNode((Element) nLegs.item(i), "name");
|
* Indexes CompoundMark elements by their ID for use in generating the course, and populates list of Markers.
|
||||||
NodeList start = ((Element) nLegs.item(i)).getElementsByTagName("start");
|
* @see CompoundMark
|
||||||
CompoundMark startCompoundMark = getMarker(start);
|
*/
|
||||||
NodeList finish = ((Element) nLegs.item(i)).getElementsByTagName("finish");
|
private void readCompoundMarks() throws StreamedCourseXMLException {
|
||||||
CompoundMark finishCompoundMark = getMarker(finish);
|
Element nCourse = (Element) doc.getElementsByTagName("Course").item(0);
|
||||||
legs.add(new Leg(label, startCompoundMark, finishCompoundMark, i));
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read courses in XML file
|
* 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
|
||||||
*/
|
*/
|
||||||
public void readCourse() {
|
private CompoundMark getCompoundMark(int compoundMarkID) throws StreamedCourseXMLException {
|
||||||
NodeList nCourse = doc.getElementsByTagName("course");
|
Element compoundMark = compoundMarkMap.get(compoundMarkID);
|
||||||
|
NodeList nMarks = compoundMark.getElementsByTagName("Mark");
|
||||||
|
CompoundMark marker;
|
||||||
|
|
||||||
NodeList nBounds = ((Element) nCourse.item(0)).getElementsByTagName("boundaries");
|
switch(nMarks.getLength()) {
|
||||||
nBounds = ((Element) nBounds.item(0)).getElementsByTagName("coordinate");
|
case 1: marker = new CompoundMark(getMark((Element)nMarks.item(0))); break;
|
||||||
int maxLatitudeIndex = 0;
|
case 2: marker = new CompoundMark(getMark((Element)nMarks.item(0)), getMark((Element)nMarks.item(1))); break;
|
||||||
double maxLatitude = -Double.MIN_VALUE;
|
default: throw new StreamedCourseXMLException();
|
||||||
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;
|
return marker;
|
||||||
minLatitude = boundary.get(i).getLatitude();
|
|
||||||
}
|
}
|
||||||
if (boundary.get(i).getLongitude() > maxLongitude) {
|
|
||||||
maxLongitudeIndex = i;
|
private Mark getMark(Element mark) {
|
||||||
maxLongitude = boundary.get(i).getLongitude();
|
int sourceID = Integer.parseInt(mark.getAttribute("SourceID"));
|
||||||
|
return marks.get(sourceID);
|
||||||
}
|
}
|
||||||
if (boundary.get(i).getLongitude() < minLongitude) {
|
|
||||||
minLongitudeIndex = i;
|
/**
|
||||||
minLongitude = boundary.get(i).getLongitude();
|
* 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double difference = 0;//this will hold the largest difference so we can make the map square.
|
private void readCourseLimit() {
|
||||||
double latitudeDiff = Math.abs(Math.abs(boundary.get(maxLatitudeIndex).getLatitude()) - Math.abs(boundary.get(minLatitudeIndex).getLatitude()));
|
Element nCourseLimit = (Element) doc.getElementsByTagName("CourseLimit").item(0);
|
||||||
double longitudeDiff = Math.abs(Math.abs(boundary.get(maxLongitudeIndex).getLongitude()) - Math.abs(boundary.get(minLongitudeIndex).getLongitude()));
|
for(int i = 0; i < nCourseLimit.getChildNodes().getLength(); i++) {
|
||||||
if (latitudeDiff >= longitudeDiff) {
|
Node limit = nCourseLimit.getChildNodes().item(i);
|
||||||
difference = latitudeDiff - longitudeDiff;
|
if (limit.getNodeName().equals("Limit")) {
|
||||||
maxLongitude += difference / 2;
|
double lat = Double.parseDouble(limit.getAttributes().getNamedItem("Lat").getTextContent());
|
||||||
minLongitude -= difference / 2;
|
double lon = Double.parseDouble(limit.getAttributes().getNamedItem("Lon").getTextContent());
|
||||||
} else {
|
boundary.add(new GPSCoordinate(lat, lon));
|
||||||
difference = longitudeDiff - latitudeDiff;
|
|
||||||
maxLatitude += difference / 2;
|
|
||||||
minLatitude -= difference / 2;
|
|
||||||
}
|
}
|
||||||
maxLatitude += COORDINATEPADDING;
|
}
|
||||||
minLatitude -= COORDINATEPADDING;
|
|
||||||
maxLongitude += COORDINATEPADDING;
|
|
||||||
minLongitude -= COORDINATEPADDING;
|
double maxLatitude = boundary.stream().max(Comparator.comparingDouble(GPSCoordinate::getLatitude)).get().getLatitude() + COORDINATEPADDING;
|
||||||
//now create map boundaries
|
double maxLongitude = boundary.stream().max(Comparator.comparingDouble(GPSCoordinate::getLongitude)).get().getLongitude() + COORDINATEPADDING;
|
||||||
//top left canvas point is min logitude, max latitude
|
double minLatitude = boundary.stream().min(Comparator.comparingDouble(GPSCoordinate::getLatitude)).get().getLatitude() + COORDINATEPADDING;
|
||||||
//bottom right of canvas point is min longitude, max latitude.
|
double minLongitude = boundary.stream().min(Comparator.comparingDouble(GPSCoordinate::getLongitude)).get().getLongitude() + COORDINATEPADDING;
|
||||||
|
|
||||||
mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
|
mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
|
||||||
mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude);
|
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
|
|
||||||
*
|
|
||||||
* @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) {
|
|
||||||
return getMarker(start, startIndex, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a marker from the XML file
|
|
||||||
*
|
|
||||||
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
||||||
* @param startIndex index in the node that has the coordinate tag
|
|
||||||
* @param nodeIndex coordinate index
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private CompoundMark getMarker(NodeList start, int startIndex, int nodeIndex) {
|
|
||||||
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("marker");
|
|
||||||
Element marker = (Element) nodeList.item(nodeIndex);
|
|
||||||
return getMarker(marker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a changes a marker to GPS coordinates into a marker
|
|
||||||
*
|
|
||||||
* @param markerNode marker to turn into coordinates
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private CompoundMark getMarker(Element markerNode) {
|
|
||||||
|
|
||||||
NodeList nCoordinates = markerNode.getElementsByTagName("coordinate");
|
|
||||||
|
|
||||||
GPSCoordinate side1 = getCoordinates((Element) nCoordinates.item(0));
|
|
||||||
GPSCoordinate side2;
|
|
||||||
if (nCoordinates.getLength() > 1) {
|
|
||||||
side2 = getCoordinates((Element) nCoordinates.item(1));
|
|
||||||
} else {
|
|
||||||
side2 = side1;
|
|
||||||
}
|
|
||||||
NodeList name = markerNode.getElementsByTagName("name");
|
|
||||||
return null;//name.getLength() == 1 ? new CompoundMark(getTextValueOfNode((Element) markerNode, "name"), side1, side2) : new CompoundMark(side1, side2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a coordinates from the XML file
|
|
||||||
*
|
|
||||||
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private GPSCoordinate getCoordinates(NodeList start) {
|
|
||||||
return getCoordinates(start, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a coordinates from the XML file
|
|
||||||
*
|
|
||||||
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
||||||
* @param startIndex the index the tag containing the coordinate should be in
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private GPSCoordinate getCoordinates(NodeList start, int startIndex) {
|
|
||||||
return getCoordinates(start, startIndex, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a coordinates from the XML file
|
|
||||||
*
|
|
||||||
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
||||||
* @param startIndex the index the tag containing the coordinate should be in
|
|
||||||
* @param nodeIndex The coordinate index
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private GPSCoordinate getCoordinates(NodeList start, int startIndex, int nodeIndex) {
|
|
||||||
NodeList nodeList = ((Element) start.item(startIndex)).getElementsByTagName("coordinate");
|
|
||||||
Element coord = (Element) nodeList.item(nodeIndex);
|
|
||||||
return getCoordinates(coord);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the coordinate TODO raise exception that runs when the XML is formatted wrongly.
|
|
||||||
*
|
|
||||||
* @param coordNode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private GPSCoordinate getCoordinates(Element coordNode) {
|
|
||||||
|
|
||||||
double startLat = Double.parseDouble(getTextValueOfNode(coordNode, "latitude"));
|
|
||||||
double startLong = Double.parseDouble(getTextValueOfNode(coordNode, "longitude"));
|
|
||||||
return new GPSCoordinate(startLat, startLong);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Boat> getBoats() {
|
|
||||||
return boats;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Leg> getLegs() {
|
|
||||||
return legs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getMark() {
|
|
||||||
return mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getStartPt1() {
|
|
||||||
return startPt1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getStartPt2() {
|
|
||||||
return startPt2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getFinishPt1() {
|
|
||||||
return finishPt1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getFinishPt2() {
|
|
||||||
return finishPt2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getLeewardPt1() {
|
|
||||||
return leewardPt1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getLeewardPt2() {
|
|
||||||
return leewardPt2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getWindwardPt1() {
|
|
||||||
return windwardPt1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GPSCoordinate getWindwardPt2() {
|
|
||||||
return windwardPt2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GPSCoordinate> getBoundary() {
|
public List<GPSCoordinate> getBoundary() {
|
||||||
@@ -357,20 +238,37 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource {
|
|||||||
return mapBottomRight;
|
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() {
|
public int getRaceId() {
|
||||||
return raceID;
|
return raceID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CompoundMark> getCompoundMarks() {
|
|
||||||
return compoundMarks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRaceType() {
|
public String getRaceType() {
|
||||||
return "FLEET";
|
return raceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public boolean isPostpone() {
|
||||||
public ZonedDateTime getZonedDateTime() {
|
return postpone;
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
public List<Boat> getBoats() {
|
||||||
|
return new ArrayList<>(participants.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
-1
@@ -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");
|
System.out.println("Sending Race");
|
||||||
String raceData = readFile("mock/src/main/resources/mockXML/raceTest.xml", StandardCharsets.UTF_8);
|
mockOutput.setRaceXml(raceXML);
|
||||||
mockOutput.setRaceXml(raceData);
|
System.out.println(raceXML);
|
||||||
mockOutput.parseXMLString(raceData, 26);
|
mockOutput.parseXMLString(raceXML, 26);
|
||||||
|
|
||||||
System.out.println("Sending Boat");
|
System.out.println("Sending Boat");
|
||||||
String boatData = readFile("mock/src/main/resources/mockXML/boatTest.xml", StandardCharsets.UTF_8);
|
mockOutput.setBoatsXml(boatXML);
|
||||||
mockOutput.setBoatsXml(boatData);
|
mockOutput.parseXMLString(boatXML, 26);
|
||||||
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()){
|
||||||
|
|||||||
Reference in New Issue
Block a user