You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
12 KiB
353 lines
12 KiB
package seng302;
|
|
|
|
import javafx.scene.paint.Color;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.SAXException;
|
|
import seng302.Model.BoatInRace;
|
|
import seng302.Model.Leg;
|
|
import seng302.Model.Marker;
|
|
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Created by fwy13 on 26/03/2017.
|
|
*/
|
|
public class RaceXMLReader extends XMLReader implements RaceDataSource {
|
|
private String raceID;
|
|
private List<BoatInRace> 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 List<GPSCoordinate> boundary = new ArrayList<>();
|
|
private static double COORDINATEPADDING = 0.0005;
|
|
private List<Marker> markers = new ArrayList<>();
|
|
|
|
/**
|
|
* Constractor for Race XML
|
|
* @param filePath path of the file
|
|
* @throws IOException error
|
|
* @throws SAXException error
|
|
* @throws ParserConfigurationException error
|
|
*/
|
|
public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException {
|
|
this(filePath, true);
|
|
}
|
|
|
|
/**
|
|
* COnstructor for 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
|
|
*/
|
|
public RaceXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException {
|
|
super(filePath);
|
|
if (read) {
|
|
read();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read the files
|
|
*/
|
|
private void read() {
|
|
readID();
|
|
readCourse();
|
|
readLegs();
|
|
readMarkers();
|
|
readBoats();
|
|
}
|
|
|
|
public void readID() {
|
|
|
|
NodeList race = doc.getElementsByTagName("race");
|
|
|
|
raceID = getTextValueOfNode((Element) race.item(0), "raceId");
|
|
}
|
|
|
|
/**
|
|
* Read all the boats in the XML file
|
|
*/
|
|
public void readBoats() {
|
|
//get all boats
|
|
NodeList nBoats = doc.getElementsByTagName("boat");
|
|
|
|
for (int i = 0; i < nBoats.getLength(); i++) {
|
|
String name = getTextValueOfNode((Element) nBoats.item(i), "name");
|
|
String abbrev = getTextValueOfNode((Element) nBoats.item(i), "abbr");
|
|
double velo = Double.parseDouble(getTextValueOfNode((Element) nBoats.item(i), "speed"));
|
|
BoatInRace boat = new BoatInRace(name, velo, colors[i], abbrev);
|
|
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++) {
|
|
Marker marker = getMarker((Element) nMarkers.item(i));
|
|
if (marker.getName() != null) markers.add(marker);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read all the legs in the XML file
|
|
*/
|
|
public void readLegs() {
|
|
//get all legs
|
|
NodeList nLegs = doc.getElementsByTagName("leg");
|
|
|
|
for (int i = 0; i < nLegs.getLength(); i++) {
|
|
String label = getTextValueOfNode((Element) nLegs.item(i), "name");
|
|
NodeList start = ((Element) nLegs.item(i)).getElementsByTagName("start");
|
|
Marker startMarker = getMarker(start);
|
|
NodeList finish = ((Element) nLegs.item(i)).getElementsByTagName("finish");
|
|
Marker finishMarker = getMarker(finish);
|
|
legs.add(new Leg(label, startMarker, finishMarker, i));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read courses in XML file
|
|
*/
|
|
public void readCourse() {
|
|
NodeList nCourse = doc.getElementsByTagName("course");
|
|
|
|
NodeList nBounds = ((Element) nCourse.item(0)).getElementsByTagName("boundaries");
|
|
nBounds = ((Element) nBounds.item(0)).getElementsByTagName("coordinate");
|
|
int maxLatitudeIndex = 0;
|
|
double maxLatitude = -Double.MIN_VALUE;
|
|
int maxLongitudeIndex = 0;
|
|
double maxLongitude = -180;
|
|
int minLatitudeIndex = 0;
|
|
double minLatitude = Double.MAX_VALUE;
|
|
int minLongitudeIndex = 0;
|
|
double minLongitude = Double.MAX_VALUE;
|
|
for (int i = 0; i < nBounds.getLength(); i++) {
|
|
boundary.add(getCoordinates((Element) nBounds.item(i)));
|
|
if (boundary.get(i).getLatitude() > maxLatitude) {
|
|
maxLatitudeIndex = i;
|
|
maxLatitude = boundary.get(i).getLatitude();
|
|
}
|
|
if (boundary.get(i).getLatitude() < minLatitude) {
|
|
minLatitudeIndex = i;
|
|
minLatitude = boundary.get(i).getLatitude();
|
|
}
|
|
if (boundary.get(i).getLongitude() > maxLongitude) {
|
|
maxLongitudeIndex = i;
|
|
maxLongitude = boundary.get(i).getLongitude();
|
|
}
|
|
if (boundary.get(i).getLongitude() < minLongitude) {
|
|
minLongitudeIndex = i;
|
|
minLongitude = boundary.get(i).getLongitude();
|
|
}
|
|
}
|
|
|
|
double difference = 0;//this will hold the largest difference so we can make the map square.
|
|
double latitudeDiff = Math.abs(Math.abs(boundary.get(maxLatitudeIndex).getLatitude()) - Math.abs(boundary.get(minLatitudeIndex).getLatitude()));
|
|
double longitudeDiff = Math.abs(Math.abs(boundary.get(maxLongitudeIndex).getLongitude()) - Math.abs(boundary.get(minLongitudeIndex).getLongitude()));
|
|
if (latitudeDiff >= longitudeDiff) {
|
|
difference = latitudeDiff - longitudeDiff;
|
|
maxLongitude += difference / 2;
|
|
minLongitude -= difference / 2;
|
|
} else {
|
|
difference = longitudeDiff - latitudeDiff;
|
|
maxLatitude += difference / 2;
|
|
minLatitude -= difference / 2;
|
|
}
|
|
maxLatitude += COORDINATEPADDING;
|
|
minLatitude -= COORDINATEPADDING;
|
|
maxLongitude += COORDINATEPADDING;
|
|
minLongitude -= COORDINATEPADDING;
|
|
//now create map boundaries
|
|
//top left canvas point is min logitude, max latitude
|
|
//bottom right of canvas point is min longitude, max latitude.
|
|
mapTopLeft = new GPSCoordinate(minLatitude, minLongitude);
|
|
mapBottomRight = new GPSCoordinate(maxLatitude, maxLongitude);
|
|
|
|
NodeList nMarks = ((Element) nCourse.item(0)).getElementsByTagName("marker");
|
|
startPt1 = getCoordinates(nMarks, 0);
|
|
startPt2 = getCoordinates(nMarks, 0, 1);
|
|
mark = getCoordinates(nMarks, 1);
|
|
windwardPt1 = getCoordinates(nMarks, 2);
|
|
windwardPt2 = getCoordinates(nMarks, 2, 1);
|
|
leewardPt1 = getCoordinates(nMarks, 3);
|
|
leewardPt2 = getCoordinates(nMarks, 3, 1);
|
|
finishPt1 = getCoordinates(nMarks, 4);
|
|
finishPt2 = getCoordinates(nMarks, 4, 1);
|
|
}
|
|
|
|
/**
|
|
* gets a marker from the XML file
|
|
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
* @return
|
|
*/
|
|
private Marker getMarker(NodeList start) {
|
|
return getMarker(start, 0);
|
|
}
|
|
|
|
/**
|
|
* gets a marker from the XML file
|
|
* @param start base nodelist this should be the tag that contains <coordinate></coordinate>
|
|
* @param startIndex index in the node that has the coordinate tag
|
|
* @return
|
|
*/
|
|
private Marker getMarker(NodeList start, int startIndex) {
|
|
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 Marker 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 Marker 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 name.getLength() == 1 ? new Marker(getTextValueOfNode((Element) markerNode, "name"), side1, side2) : new Marker(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<BoatInRace> 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() {
|
|
return boundary;
|
|
}
|
|
|
|
public GPSCoordinate getMapTopLeft() {
|
|
return mapTopLeft;
|
|
}
|
|
|
|
public GPSCoordinate getMapBottomRight() {
|
|
return mapBottomRight;
|
|
}
|
|
|
|
public String getRaceId() { return raceID; }
|
|
|
|
public List<Marker> getMarkers() { return markers; }
|
|
}
|