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.

252 lines
8.7 KiB

package seng302;
import javafx.scene.paint.Color;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import seng302.Model.Boat;
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;
/**
* Created by fwy13 on 26/03/2017.
*/
public class RaceXMLReader extends XMLReader{
private ArrayList<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 ArrayList<Leg> legs = new ArrayList<>();
private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2;
private GPSCoordinate mapTopLeft, mapBottomRight;
private ArrayList<GPSCoordinate> boundary = new ArrayList<>();
private static double COORDINATEPADDING = 0.0005;
public RaceXMLReader(String filePath) throws IOException, SAXException, ParserConfigurationException {
this(filePath, true);
}
public RaceXMLReader(String filePath, boolean read) throws IOException, SAXException, ParserConfigurationException {
super(filePath);
if (read) {
read();
}
}
private void read(){
readCourse();
readLegs();
readBoats();
}
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);
}
}
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));
}
}
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);
}
private Marker getMarker(NodeList start) { return getMarker(start, 0); }
private Marker getMarker(NodeList start, int startIndex) {
return getMarker(start, startIndex, 0);
}
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);
}
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;
}
return new Marker(side1, side2);
}
private GPSCoordinate getCoordinates(NodeList start){
return getCoordinates(start, 0);
}
private GPSCoordinate getCoordinates(NodeList start, int startIndex){
return getCoordinates(start, startIndex, 0);
}
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 ArrayList<BoatInRace> getBoats() {
return boats;
}
public ArrayList<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 ArrayList<GPSCoordinate> getBoundary() {
return boundary;
}
public GPSCoordinate getMapTopLeft() {
return mapTopLeft;
}
public GPSCoordinate getMapBottomRight() {
return mapBottomRight;
}
}