diff --git a/visualiser/src/main/java/seng302/Constants.java b/visualiser/src/main/java/seng302/Constants.java index b2d96fcb..096e5a2b 100644 --- a/visualiser/src/main/java/seng302/Constants.java +++ b/visualiser/src/main/java/seng302/Constants.java @@ -6,6 +6,7 @@ import seng302.Model.BoatInRace; /** * Constants that are used throughout the program * Created by Erika on 19-Mar-17. + * @deprecated please use XML for constant data */ public class Constants { diff --git a/visualiser/src/main/java/seng302/Controllers/RaceController.java b/visualiser/src/main/java/seng302/Controllers/RaceController.java index 9c64bbfa..69bbf74b 100644 --- a/visualiser/src/main/java/seng302/Controllers/RaceController.java +++ b/visualiser/src/main/java/seng302/Controllers/RaceController.java @@ -125,7 +125,6 @@ public class RaceController extends Controller { raceMap.widthProperty().bind(canvasBase.widthProperty()); raceMap.heightProperty().bind(canvasBase.heightProperty()); //raceMap.setBoats(newRace.getStartingBoats()); - raceMap.setRaceBoundaries(raceData.getBoundary()); raceMap.drawRaceMap(); raceMap.setVisible(true); diff --git a/visualiser/src/main/java/seng302/Mock/StreamedCourse.java b/visualiser/src/main/java/seng302/Mock/StreamedCourse.java index ebde5a4c..f2bcfed0 100644 --- a/visualiser/src/main/java/seng302/Mock/StreamedCourse.java +++ b/visualiser/src/main/java/seng302/Mock/StreamedCourse.java @@ -3,6 +3,7 @@ package seng302.Mock; import seng302.GPSCoordinate; import seng302.Model.BoatInRace; import seng302.Model.Leg; +import seng302.Model.Marker; import seng302.Model.RaceClock; import seng302.RaceDataSource; @@ -58,12 +59,14 @@ public class StreamedCourse implements RaceDataSource { return streamedCourseXMLReader.getLegs(); } + public List getMarkers() { return streamedCourseXMLReader.getMarkers(); } + public List getBoundary() { return streamedCourseXMLReader.getBoundary(); } public ZonedDateTime getZonedDateTime() { - return RaceClock.getCurrentZonedDateTime(regattaXMLReader.getRegatta().getGPSCoordinate()); + return streamedCourseXMLReader.getRaceStartTime(); } public GPSCoordinate getMapTopLeft() { diff --git a/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java index 8fe86835..43cd9f44 100644 --- a/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java +++ b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java @@ -1,5 +1,6 @@ package seng302.Mock; +import org.joda.time.DateTime; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; @@ -15,20 +16,23 @@ import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; /** * Created by jjg64 on 21/04/17. */ public class StreamedCourseXMLReader extends XMLReader { - private static double COORDINATEPADDING = 0.0005; + private static double COORDINATEPADDING = 0.000; private GPSCoordinate mapTopLeft, mapBottomRight; private List boundary = new ArrayList<>(); - private Map marks = new HashMap<>(); + private Map compoundMarks = new HashMap<>(); private Map participants = new HashMap<>(); private List legs = new ArrayList<>(); - Date creationTimeDate; - Date raceStartTime; + private List markers = new ArrayList<>(); + ZonedDateTime creationTimeDate; + ZonedDateTime raceStartTime; int raceID; String raceType; boolean postpone; @@ -66,14 +70,14 @@ public class StreamedCourseXMLReader extends XMLReader { } private void readRace() throws ParseException { - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"); Element settings = (Element) doc.getElementsByTagName("Race").item(0); raceID = Integer.parseInt(getTextValueOfNode(settings, "RaceID")); raceType = getTextValueOfNode(settings, "RaceType"); - creationTimeDate = dateFormat.parse(getTextValueOfNode(settings, "CreationTimeDate")); + creationTimeDate = ZonedDateTime.parse(getTextValueOfNode(settings, "CreationTimeDate"), dateFormat); NamedNodeMap raceTimeTag = doc.getElementsByTagName("RaceStartTime").item(0).getAttributes(); - raceStartTime = dateFormat.parse(raceTimeTag.getNamedItem("Time").getTextContent()); + raceStartTime = ZonedDateTime.parse(raceTimeTag.getNamedItem("Time").getTextContent(), dateFormat); postpone = Boolean.parseBoolean(raceTimeTag.getNamedItem("Postpone").getTextContent()); } @@ -98,14 +102,17 @@ public class StreamedCourseXMLReader extends XMLReader { } /** - * Indexes CompoundMark elements by their ID for use in generating the course. + * Indexes CompoundMark elements by their ID for use in generating the course, and populates list of Markers. + * @see seng302.Model.Marker */ - private void readCompoundMarks() { + 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")) { - marks.put(getCompoundMarkID((Element)compoundMark),(Element)compoundMark); + int compoundMarkID = getCompoundMarkID((Element) compoundMark); + compoundMarks.put(compoundMarkID, (Element)compoundMark); + markers.add(getMarker(compoundMarkID)); } } } @@ -114,11 +121,11 @@ public class StreamedCourseXMLReader extends XMLReader { * Generates a Marker from the CompoundMark element with given ID. * @param compoundMarkID index of required CompoundMark element * @return generated Marker - * @throws StreamedCourseXMLException if CompoundMark element contains unhandled number of marks + * @throws StreamedCourseXMLException if CompoundMark element contains unhandled number of compoundMarks * @see seng302.Model.Marker */ private Marker getMarker(int compoundMarkID) throws StreamedCourseXMLException { - Element compoundMark = marks.get(compoundMarkID); + Element compoundMark = compoundMarks.get(compoundMarkID); NodeList nMarks = compoundMark.getElementsByTagName("Mark"); Marker marker; @@ -152,7 +159,7 @@ public class StreamedCourseXMLReader extends XMLReader { * @return value of "name" attribute */ private String getCompoundMarkName(int compoundMarkID) { - return marks.get(compoundMarkID).getAttribute("Name"); + return compoundMarks.get(compoundMarkID).getAttribute("Name"); } /** @@ -184,6 +191,7 @@ public class StreamedCourseXMLReader extends XMLReader { } } + 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; @@ -209,15 +217,17 @@ public class StreamedCourseXMLReader extends XMLReader { return legs; } + public List getMarkers() { return markers; } + public Double getPadding() { return COORDINATEPADDING; } - public Date getCreationTimeDate() { + public ZonedDateTime getCreationTimeDate() { return creationTimeDate; } - public Date getRaceStartTime() { + public ZonedDateTime getRaceStartTime() { return raceStartTime; } diff --git a/visualiser/src/main/java/seng302/Model/Marker.java b/visualiser/src/main/java/seng302/Model/Marker.java index 118219f1..ec46edb2 100644 --- a/visualiser/src/main/java/seng302/Model/Marker.java +++ b/visualiser/src/main/java/seng302/Model/Marker.java @@ -37,6 +37,14 @@ public class Marker { return mark2; } + /** + * Returns true if mark consists of two points, e.g. it is a gate. + * @return boolean + */ + public boolean isCompoundMark() { + return mark1 != mark2; + } + public GPSCoordinate getAverageGPSCoordinate() { return averageGPSCoordinate; } diff --git a/visualiser/src/main/java/seng302/Model/RaceClock.java b/visualiser/src/main/java/seng302/Model/RaceClock.java index 3dfb5af5..c4ce751d 100644 --- a/visualiser/src/main/java/seng302/Model/RaceClock.java +++ b/visualiser/src/main/java/seng302/Model/RaceClock.java @@ -43,7 +43,7 @@ public class RaceClock { */ public void setTime(ZonedDateTime time) { this.time = time; - this.timeString.set(DateTimeFormatter.ofPattern("dd-MM HH:mm:ss z").format(time)); + this.timeString.set(DateTimeFormatter.ofPattern("HH:mm:ss dd/MM/YYYY Z").format(time)); this.lastTime = System.currentTimeMillis(); } diff --git a/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java b/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java index 1df65127..66ccb518 100644 --- a/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -22,13 +22,13 @@ public class ResizableRaceCanvas extends Canvas { private GraphicsContext gc; private RaceMap map; private List boats; - private RaceDataSource raceData; private boolean raceAnno = true; private boolean annoName = true; private boolean annoAbbrev = true; private boolean annoSpeed = true; private boolean annoPath = true; - private ArrayList raceBoundaries; + private List raceBoundaries; + private List markers; double[] xpoints = {}, ypoints = {}; public ResizableRaceCanvas(RaceDataSource raceData) { @@ -41,9 +41,11 @@ public class ResizableRaceCanvas extends Canvas { double long1 = raceData.getMapTopLeft().getLongitude(); double lat2 = raceData.getMapBottomRight().getLatitude(); double long2 = raceData.getMapBottomRight().getLongitude(); + setMap(new RaceMap(lat1, long1, lat2, long2, (int) getWidth(), (int) getHeight())); - this.raceData = raceData; + this.raceBoundaries = raceData.getBoundary(); + this.markers = raceData.getMarkers(); } /** @@ -209,6 +211,22 @@ public class ResizableRaceCanvas extends Canvas { gc.fillPolygon(xpoints, ypoints, xpoints.length); } + /** + * Draw race markers + */ + public void drawMarkers() { + for(Marker marker: markers) { + GraphCoordinate mark1 = this.map.convertGPS(marker.getMark1()); + if(marker.isCompoundMark()) { + GraphCoordinate mark2 = this.map.convertGPS(marker.getMark2()); + // TODO - improve colour coding of markers + displayLine(mark1, mark2, Color.GREEN); + } else { + displayPoint(mark1, Color.GREEN); + } + } + } + /** * Draws the Race Map */ @@ -225,67 +243,16 @@ public class ResizableRaceCanvas extends Canvas { this.map.setHeight((int) height); this.map.setWidth((int) width); - //finish line gc.setLineWidth(2); drawBoundaries(); - drawPoints(); + drawMarkers(); + updateBoats(); //display wind direction arrow - specify origin point and angle - angle now set to random angle displayArrow(new GraphCoordinate((int) getWidth() - 40, 40), 150); } - private void drawPoints() { -// GraphCoordinate finishLineCoord1 = this.map.convertGPS(Constants.finishLineMarker1); -// GraphCoordinate finishLineCoord2 = this.map.convertGPS(Constants.finishLineMarker2); -// displayLine(finishLineCoord1, finishLineCoord2, Color.DARKRED); -// //marks -// GraphCoordinate markCoord = this.map.convertGPS(Constants.mark1); -// GraphCoordinate windwardGate1 = this.map.convertGPS(Constants.windwardGate1); -// GraphCoordinate windwardGate2 = this.map.convertGPS(Constants.windwardGate2); -// GraphCoordinate leewardGate1 = this.map.convertGPS(Constants.leewardGate1); -// GraphCoordinate leewardGate2 = this.map.convertGPS(Constants.leewardGate2); -// displayMark(markCoord, Color.GOLD); -// displayLine(windwardGate1, windwardGate2, Color.DARKCYAN); -// displayLine(leewardGate1, leewardGate2, Color.DARKVIOLET); -// //start line -// GraphCoordinate startline1 = this.map.convertGPS(Constants.startLineMarker1); -// GraphCoordinate startline2 = this.map.convertGPS(Constants.startLineMarker2); -// -// displayLine(startline1, startline2, Color.GREEN); - - for (Leg leg : raceData.getLegs()) { - boolean hasStart = false; - boolean hasEnd = false; - GraphCoordinate start1 = null; - GraphCoordinate start2 = null; - GraphCoordinate end1 = null; - GraphCoordinate end2 = null; - String legName = leg.getName().toLowerCase(); - if (leg.getStartMarker() != null) { - start1 = this.map.convertGPS(leg.getStartMarker().getMark1()); - start2 = this.map.convertGPS(leg.getStartMarker().getMark2()); - hasStart = true; - } if (leg.getEndMarker() != null) { - end1 = this.map.convertGPS(leg.getEndMarker().getMark1()); - end2 = this.map.convertGPS(leg.getEndMarker().getMark2()); - hasEnd = true; - } - - if (legName.contains("line") || legName.contains("gate")) { - if (hasStart && start1 != null && start2 != null) displayLine(start1, start2, Color.BLACK); - if (hasEnd && start1 != null && start2 != null) displayLine(end1, end2, Color.BLACK); - } else if (hasStart && start1 != null && start2 != null) { - if (legName.contains("start")) displayLine(start1, start2, Color.BLACK); - else displayMark(start1, Color.BLACK); - } - else if (hasEnd && end1 != null && end2 != null) { - if (legName.contains("finish")) displayLine(end1, end2, Color.BLACK); - else displayMark(end1, Color.BLACK); - } - } - } - /** * Draws a boat at a certain GPSCoordinate * @@ -356,7 +323,7 @@ public class ResizableRaceCanvas extends Canvas { */ public void updateBoats() { // TODO Remove null when boats are ready - //boats = null; + boats = null; if (boats != null) { for (BoatInRace boat : boats) { boolean finished = boat.getCurrentLeg().getName().equals("Finish") || boat.getCurrentLeg().getName().equals("DNF"); diff --git a/visualiser/src/main/java/seng302/RaceDataSource.java b/visualiser/src/main/java/seng302/RaceDataSource.java index 82d30b73..c309661b 100644 --- a/visualiser/src/main/java/seng302/RaceDataSource.java +++ b/visualiser/src/main/java/seng302/RaceDataSource.java @@ -2,6 +2,7 @@ package seng302; import seng302.Model.BoatInRace; import seng302.Model.Leg; +import seng302.Model.Marker; import java.time.ZonedDateTime; import java.util.List; @@ -12,6 +13,7 @@ import java.util.List; public interface RaceDataSource { List getBoats(); List getLegs(); + List getMarkers(); List getBoundary(); ZonedDateTime getZonedDateTime(); diff --git a/visualiser/src/main/java/seng302/RaceXMLReader.java b/visualiser/src/main/java/seng302/RaceXMLReader.java index 14244417..a3b0dfeb 100644 --- a/visualiser/src/main/java/seng302/RaceXMLReader.java +++ b/visualiser/src/main/java/seng302/RaceXMLReader.java @@ -14,6 +14,7 @@ import java.util.List; /** * Created by fwy13 on 26/03/2017. + * @deprecated use {@link seng302.Mock.StreamedCourseXMLReader} */ public class RaceXMLReader extends XMLReader implements RaceDataSource { private List boats = new ArrayList<>(); @@ -263,6 +264,11 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource { return new GPSCoordinate(startLat, startLong); } + @Override + public List getMarkers() { + return null; + } + public List getBoats() { return boats; } diff --git a/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java b/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java index c7ddb3d3..d842c9c0 100644 --- a/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java +++ b/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java @@ -1,13 +1,16 @@ package seng302.Mock; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import seng302.GPSCoordinate; import seng302.Model.Leg; +import seng302.Model.Marker; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** @@ -75,4 +78,21 @@ public class StreamedRaceTest { }; for(int i = 0; i < legs.size(); i++) assertEquals(expectedNames[i], legs.get(i).getName()); } + + /** + * raceTest.xml is not compliant with this test. Markers are positioned far out of bounds. + */ + @Test + public void markersWithinRaceBoundaries() { + GPSCoordinate topLeft = streamedCourseXMLReader.getMapTopLeft(); + GPSCoordinate bottomRight = streamedCourseXMLReader.getMapBottomRight(); + + for(Marker marker: streamedCourseXMLReader.getMarkers()) { + GPSCoordinate centre = marker.getAverageGPSCoordinate(); + assertTrue(centre.getLatitude() < bottomRight.getLatitude()); + assertTrue(centre.getLatitude() > topLeft.getLatitude()); + assertTrue(centre.getLongitude() > bottomRight.getLongitude()); + assertTrue(centre.getLongitude() < topLeft.getLongitude()); + } + } }