From 1653003cf071a96280b20677e82af143fa8396d8 Mon Sep 17 00:00:00 2001 From: cbt24 Date: Tue, 25 Apr 2017 15:51:44 +1200 Subject: [PATCH] Implemented Leg generation from Race.xml format - StreamedCourse now utilises StreamedCourseXMLReader as data source #story[758] --- .../java/seng302/Mock/StreamedCourse.java | 34 ++---- .../Mock/StreamedCourseXMLException.java | 7 ++ .../seng302/Mock/StreamedCourseXMLReader.java | 110 ++++++++++++++---- .../java/seng302/Mock/StreamedRaceTest.java | 23 +++- 4 files changed, 118 insertions(+), 56 deletions(-) create mode 100644 visualiser/src/main/java/seng302/Mock/StreamedCourseXMLException.java diff --git a/visualiser/src/main/java/seng302/Mock/StreamedCourse.java b/visualiser/src/main/java/seng302/Mock/StreamedCourse.java index 9bf01ab7..984529cd 100644 --- a/visualiser/src/main/java/seng302/Mock/StreamedCourse.java +++ b/visualiser/src/main/java/seng302/Mock/StreamedCourse.java @@ -14,44 +14,23 @@ import java.util.List; * Created by jjg64 on 21/04/17. */ public class StreamedCourse implements RaceDataSource { - StreamedCourseXMLReader streamedCourseXMLReader = null; - BoatXMLReader boatXMLReader = null; + StreamedCourseXMLReader streamedCourseXMLReader; List boundary = new ArrayList<>(); public StreamedCourse(StreamedCourseXMLReader streamedCourseXMLReader) { this.streamedCourseXMLReader = streamedCourseXMLReader; } - public StreamedCourse(BoatXMLReader boatXMLReader) { - this.boatXMLReader = boatXMLReader; - } - - public void setBoatXMLReader(BoatXMLReader boatXMLReader) { - this.boatXMLReader = boatXMLReader; - if (streamedCourseXMLReader != null) { - boatXMLReader.setParticipants(streamedCourseXMLReader.getParticipants()); - boatXMLReader.read(); - } - } - - public void setStreamedCourseXMLReader(StreamedCourseXMLReader streamedCourseXMLReader) { - this.streamedCourseXMLReader = streamedCourseXMLReader; - if (streamedCourseXMLReader != null) { - boatXMLReader.setParticipants(streamedCourseXMLReader.getParticipants()); - boatXMLReader.read(); - } - } - public List getBoats() { return null; } public List getLegs() { - return null; + return streamedCourseXMLReader.getLegs(); } public List getBoundary() { - return null; + return streamedCourseXMLReader.getBoundary(); } public ZonedDateTime getZonedDateTime() { @@ -59,10 +38,13 @@ public class StreamedCourse implements RaceDataSource { } public GPSCoordinate getMapTopLeft() { - return null; + return streamedCourseXMLReader.getMapTopLeft(); } public GPSCoordinate getMapBottomRight() { - return null; + return streamedCourseXMLReader.getMapBottomRight(); } + + + } diff --git a/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLException.java b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLException.java new file mode 100644 index 00000000..5bebaa09 --- /dev/null +++ b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLException.java @@ -0,0 +1,7 @@ +package seng302.Mock; + +/** + * Created by cbt24 on 25/04/17. + */ +public class StreamedCourseXMLException extends Throwable { +} diff --git a/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java index 949be304..56998f47 100644 --- a/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java +++ b/visualiser/src/main/java/seng302/Mock/StreamedCourseXMLReader.java @@ -3,8 +3,11 @@ package seng302.Mock; 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.GPSCoordinate; +import seng302.Model.Leg; +import seng302.Model.Marker; import seng302.XMLReader; import javax.xml.parsers.ParserConfigurationException; @@ -21,7 +24,8 @@ public class StreamedCourseXMLReader extends XMLReader { private static double COORDINATEPADDING = 0.0005; private GPSCoordinate mapTopLeft, mapBottomRight; private List boundary = new ArrayList<>(); - private Map participants = new HashMap<>(); + private Map marks = new HashMap<>(); + private List legs = new ArrayList<>(); Date creationTimeDate; Date raceStartTime; int raceID; @@ -35,7 +39,7 @@ public class StreamedCourseXMLReader extends XMLReader { * @throws SAXException error * @throws ParserConfigurationException error */ - public StreamedCourseXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException, ParseException { + public StreamedCourseXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException { this(filePath, true); } @@ -47,14 +51,14 @@ public class StreamedCourseXMLReader extends XMLReader { * @throws SAXException error * @throws ParserConfigurationException error */ - public StreamedCourseXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException, ParseException { + public StreamedCourseXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException, ParseException, StreamedCourseXMLException { super(filePath); if (read) { read(); } } - private void read() throws ParseException { + private void read() throws ParseException, StreamedCourseXMLException { readRace(); readParticipants(); readCourse(); @@ -73,32 +77,90 @@ public class StreamedCourseXMLReader extends XMLReader { } private void readParticipants() { - Element nParticipants = (Element) doc.getElementsByTagName("Participants").item(0); - 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, new StreamedBoat(sourceID)); - } - } - } + //TODO Modify BoatInRace to take in a sourceID + //TODO Produce list of BoatInRace } - private void readCourse() { + private void readCourse() throws StreamedCourseXMLException { readCompoundMarks(); readCompoundMarkSequence(); readCourseLimit(); } + /** + * Indexes CompoundMark elements by their ID for use in generating the course. + */ private void readCompoundMarks() { - // TODO Produce map of sequence id to compound mark nodes (in xml) - // TODO Populate list of markers + 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); + } + } } - private void readCompoundMarkSequence() { - // TODO Produce list of legs according to mark sequence ids + /** + * 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 + * @see seng302.Model.Marker + */ + private Marker getMarker(int compoundMarkID) throws StreamedCourseXMLException { + Element compoundMark = marks.get(compoundMarkID); + NodeList nMarks = compoundMark.getElementsByTagName("Mark"); + Marker marker; + + switch(nMarks.getLength()) { + case 1: marker = new Marker(getCoordinate((Element)nMarks.item(0))); break; + case 2: marker = new Marker(getCoordinate((Element)nMarks.item(0)), getCoordinate((Element)nMarks.item(1))); break; + default: throw new StreamedCourseXMLException(); + } + + return marker; + } + + private GPSCoordinate getCoordinate(Element mark) { + double lat = Double.parseDouble(mark.getAttribute("TargetLat")); + double lon = Double.parseDouble(mark.getAttribute("TargetLng")); + return new GPSCoordinate(lat,lon); + } + + /** + * 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 marks.get(compoundMarkID).getAttribute("Name"); + } + + /** + * Populates list of legs given CompoundMarkSequence element and referenced CompoundMark elements. + * @throws StreamedCourseXMLException if markers cannot be resolved from CompoundMark + */ + private void readCompoundMarkSequence() throws StreamedCourseXMLException { + Element nCompoundMarkSequence = (Element) doc.getElementsByTagName("CompoundMarkSequence").item(0); + NodeList nCorners = nCompoundMarkSequence.getElementsByTagName("Corner"); + Marker lastMarker = getMarker(getCompoundMarkID((Element)nCorners.item(0))); + String legName = getCompoundMarkName(getCompoundMarkID((Element)nCorners.item(0))); + for(int i = 1; i < nCorners.getLength(); i++) { + Element markXML = (Element)nCorners.item(i); + Marker currentMarker = getMarker(getCompoundMarkID(markXML)); + legs.add(new Leg(legName, lastMarker, currentMarker, i-1)); + lastMarker = currentMarker; + legName = getCompoundMarkName(getCompoundMarkID(markXML)); + } } private void readCourseLimit() { @@ -133,6 +195,10 @@ public class StreamedCourseXMLReader extends XMLReader { return mapBottomRight; } + public List getLegs() { + return legs; + } + public Double getPadding() { return COORDINATEPADDING; } @@ -156,8 +222,4 @@ public class StreamedCourseXMLReader extends XMLReader { public boolean isPostpone() { return postpone; } - - public Map getParticipants() { - return participants; - } } diff --git a/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java b/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java index 1a475290..c7ddb3d3 100644 --- a/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java +++ b/visualiser/src/test/java/seng302/Mock/StreamedRaceTest.java @@ -3,12 +3,11 @@ package seng302.Mock; import org.junit.Before; import org.junit.Test; import seng302.GPSCoordinate; +import seng302.Model.Leg; import java.util.List; -import java.util.Map; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** @@ -26,6 +25,8 @@ public class StreamedRaceTest { } catch (Exception e) { e.printStackTrace(); //fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder"); + } catch (StreamedCourseXMLException e) { + e.printStackTrace(); } } @@ -59,9 +60,19 @@ public class StreamedRaceTest { } @Test - public void testParticipants() { - Map participants = streamedCourseXMLReader.getParticipants(); - assertTrue(participants.containsKey(107)); - assertTrue(participants.containsKey(108)); + public void testRaceSettings() { + + } + + @Test + public void correctLegSequence() { + List legs = streamedCourseXMLReader.getLegs(); + String[] expectedNames = { + "StartLine", + "M1", + "M2", + "Gate" + }; + for(int i = 0; i < legs.size(); i++) assertEquals(expectedNames[i], legs.get(i).getName()); } }