mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Merge branch 'issue#10_unifying_marks' into Issue#4_boat_movement
# Conflicts: # src/main/java/seng302/controllers/CanvasController.java # src/main/java/seng302/controllers/Controller.java # src/main/java/seng302/controllers/RaceViewController.java # src/main/java/seng302/models/stream/StreamPacket.java # src/main/java/seng302/models/stream/StreamParser.java
This commit is contained in:
@@ -5,8 +5,8 @@ import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import seng302.models.parsers.StreamParser;
|
||||
import seng302.models.parsers.StreamReceiver;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.StreamReceiver;
|
||||
import seng302.server.ServerThread;
|
||||
|
||||
public class App extends Application
|
||||
@@ -62,7 +62,7 @@ public class App extends Application
|
||||
}
|
||||
//Change the StreamReceiver in this else block to change the default data source.
|
||||
else{
|
||||
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||
sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
||||
}
|
||||
|
||||
sr.start();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package seng302.controllers;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.animation.*;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Point2D;
|
||||
@@ -14,18 +14,21 @@ import seng302.models.BoatGroup;
|
||||
import seng302.models.Colors;
|
||||
import seng302.models.RaceObject;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.*;
|
||||
import seng302.models.mark.*;
|
||||
import seng302.models.parsers.StreamParser;
|
||||
import seng302.models.parsers.XMLParser;
|
||||
import seng302.models.parsers.XMLParser.RaceXMLObject.CompoundMark;
|
||||
import seng302.models.parsers.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.packets.BoatPositionPacket;
|
||||
import seng302.models.stream.XMLParser;
|
||||
import seng302.models.stream.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.models.mark.Mark;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
|
||||
/**
|
||||
@@ -59,7 +62,6 @@ public class CanvasController {
|
||||
private Mark maxLonPoint;
|
||||
private double referencePointX;
|
||||
private double referencePointY;
|
||||
private double metersToPixels;
|
||||
private List<RaceObject> raceObjects = new ArrayList<>();
|
||||
private List<Mark> raceMarks = new ArrayList<>();
|
||||
|
||||
@@ -69,6 +71,7 @@ public class CanvasController {
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
private DecimalFormat decimalFormat2dp = new DecimalFormat("0.00");
|
||||
private double lastPacketTime = 0;
|
||||
|
||||
public AnimationTimer timer;
|
||||
|
||||
@@ -178,57 +181,6 @@ public class CanvasController {
|
||||
gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the course marks to the canvas, taken from the XMl file
|
||||
*
|
||||
* NOTE: This is quite confusing as objects are grabbed from the XMLParser such as Mark and CompoundMark which are
|
||||
* named the same as those in the model package but are, however not the same, so they do not have things such as
|
||||
* a type and must be derived from the number of marks in a compound mark etc..
|
||||
*/
|
||||
private void addCourseMarks() {
|
||||
XMLParser.RaceXMLObject raceXMLObject = StreamParser.getXmlObject().getRaceXML();
|
||||
ArrayList<CompoundMark> compoundMarks = raceXMLObject.getCompoundMarks();
|
||||
RaceObject markGroup;
|
||||
|
||||
for (CompoundMark compoundMark : compoundMarks) {
|
||||
|
||||
//If the compound mark has 2 marks then its a gate mark
|
||||
if (compoundMark.getMarks().size() == 2) {
|
||||
CompoundMark.Mark mark1 = compoundMark.getMarks().get(0);
|
||||
CompoundMark.Mark mark2 = compoundMark.getMarks().get(1);
|
||||
SingleMark singleMark1 = new SingleMark(mark1.getMarkName(), mark1.getTargetLat(), mark1.getTargetLng(), mark1.getSourceID());
|
||||
SingleMark singleMark2 = new SingleMark(mark1.getMarkName(), mark2.getTargetLat(), mark2.getTargetLng(), mark2.getSourceID());
|
||||
GateMark thisGateMark = new GateMark(compoundMark.getcMarkName(),
|
||||
(compoundMark.getMarkID().equals(1)) ? MarkType.OPEN_GATE : MarkType.CLOSED_GATE,
|
||||
singleMark1,
|
||||
singleMark2,
|
||||
singleMark1.getLatitude(),
|
||||
singleMark1.getLongitude());
|
||||
|
||||
markGroup = new MarkGroup(thisGateMark,
|
||||
latLonToXY(thisGateMark.getSingleMark1().getLatitude(), thisGateMark.getSingleMark1().getLongitude()),
|
||||
latLonToXY(thisGateMark.getSingleMark2().getLatitude(), thisGateMark.getSingleMark2().getLongitude()));
|
||||
|
||||
raceObjects.add(markGroup);
|
||||
raceMarks.add(thisGateMark);
|
||||
|
||||
//Otherwise its a single mark
|
||||
} else {
|
||||
CompoundMark.Mark singleMark = compoundMark.getMarks().get(0);
|
||||
Mark thisSingleMark = new SingleMark(singleMark.getMarkName(),
|
||||
singleMark.getTargetLat(),
|
||||
singleMark.getTargetLng(),
|
||||
singleMark.getSourceID());
|
||||
|
||||
markGroup = new MarkGroup(thisSingleMark, latLonToXY(thisSingleMark.getLatitude(), thisSingleMark.getLongitude()));
|
||||
raceObjects.add(markGroup);
|
||||
raceMarks.add(thisSingleMark);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRaceObjects(){
|
||||
for (RaceObject raceObject : raceObjects) {
|
||||
raceObject.updatePosition(1000 / 60);
|
||||
@@ -246,10 +198,10 @@ public class CanvasController {
|
||||
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatPositions.get(id);
|
||||
if (movementQueue.size() > 0){
|
||||
// BoatPositionPacket positionPacket = movementQueue.peek();
|
||||
|
||||
//this code adds a delay to reading from the movementQueue
|
||||
//in case things being put into the movement queue are slightly
|
||||
//out of order
|
||||
//
|
||||
// //this code adds a delay to reading from the movementQueue
|
||||
// //in case things being put into the movement queue are slightly
|
||||
// //out of order
|
||||
// int delayTime = 1000;
|
||||
// int loopTime = delayTime * 10;
|
||||
// long timeDiff = (System.currentTimeMillis()%loopTime - positionPacket.getTimeValid()%loopTime);
|
||||
@@ -344,9 +296,8 @@ public class CanvasController {
|
||||
findMinMaxPoint();
|
||||
double minLonToMaxLon = scaleRaceExtremities();
|
||||
calculateReferencePointLocation(minLonToMaxLon);
|
||||
givePointsXY();
|
||||
//givePointsXY();
|
||||
addRaceBorder();
|
||||
findMetersToPixels();
|
||||
}
|
||||
|
||||
|
||||
@@ -444,20 +395,17 @@ public class CanvasController {
|
||||
* are scaled according to the distanceScaleFactor variable.
|
||||
*/
|
||||
private void givePointsXY() {
|
||||
List<Mark> allPoints = new ArrayList<>(raceViewController.getRace().getCourse());
|
||||
List<Mark> processed = new ArrayList<>();
|
||||
RaceObject markGroup;
|
||||
List<XMLParser.RaceXMLObject.CompoundMark> allPoints = StreamParser.getXmlObject().getRaceXML().getCompoundMarks();
|
||||
List<XMLParser.RaceXMLObject.CompoundMark> processed = new ArrayList<>();
|
||||
RaceObject markGroup;
|
||||
|
||||
for (Mark mark : allPoints) {
|
||||
if (!processed.contains(mark)) {
|
||||
if (mark.getMarkType() != MarkType.SINGLE_MARK) {
|
||||
GateMark gateMark = (GateMark) mark;
|
||||
markGroup = new MarkGroup(mark,
|
||||
latLonToXY(gateMark.getSingleMark1().getLatitude(), gateMark.getSingleMark1().getLongitude()),
|
||||
latLonToXY(gateMark.getSingleMark2().getLatitude(), gateMark.getSingleMark2().getLongitude()));
|
||||
raceObjects.add(markGroup);
|
||||
for (XMLParser.RaceXMLObject.CompoundMark mark : allPoints) {
|
||||
if (!processed.contains(mark)) {
|
||||
if (mark.getMarkType() != MarkType.SINGLE_MARK) {
|
||||
markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)), findScaledXY(mark.getMarks().get(1)));
|
||||
raceObjects.add(markGroup);
|
||||
} else {
|
||||
markGroup = new MarkGroup(mark, latLonToXY(mark.getLatitude(), mark.getLongitude()));
|
||||
markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)));
|
||||
raceObjects.add(markGroup);
|
||||
}
|
||||
processed.add(mark);
|
||||
@@ -497,33 +445,8 @@ public class CanvasController {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the number of meters per pixel.
|
||||
*/
|
||||
private void findMetersToPixels () {
|
||||
Double angularDistance;
|
||||
Double angle;
|
||||
Double straightLineDistance;
|
||||
if (scaleDirection == ScaleDirection.HORIZONTAL) {
|
||||
angularDistance = Mark.calculateDistance(minLonPoint, maxLonPoint);
|
||||
angle = Mark.calculateHeadingRad(minLonPoint, maxLonPoint);
|
||||
if (angle > Math.PI / 2) {
|
||||
straightLineDistance = Math.cos(angle - Math.PI) * angularDistance;
|
||||
} else {
|
||||
straightLineDistance = Math.cos(angle) * angularDistance;
|
||||
}
|
||||
metersToPixels = (CANVAS_WIDTH - RHS_BUFFER - LHS_BUFFER) / straightLineDistance;
|
||||
} else {
|
||||
angularDistance = Mark.calculateDistance(minLatPoint, maxLatPoint);
|
||||
angle = Mark.calculateHeadingRad(minLatPoint, maxLatPoint);
|
||||
if (angle < Math.PI / 2) {
|
||||
straightLineDistance = Math.cos(angle) * angularDistance;
|
||||
} else {
|
||||
straightLineDistance = Math.cos(-angle + Math.PI * 2) * angularDistance;
|
||||
}
|
||||
metersToPixels = (CANVAS_HEIGHT - TOP_BUFFER - BOT_BUFFER) / straightLineDistance;
|
||||
}
|
||||
private Point2D latLonToXY (double latitude, double longitude) {
|
||||
return findScaledXY(minLatPoint.getLatitude(), minLatPoint.getLongitude(), latitude, longitude);
|
||||
}
|
||||
|
||||
List<RaceObject> getRaceObjects() {
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package seng302.controllers;
|
||||
|
||||
import seng302.models.Race;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.parsers.ConfigParser;
|
||||
import seng302.models.parsers.CourseParser;
|
||||
import seng302.models.parsers.StreamParser;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by zyt10 on 17/03/17.
|
||||
* run before CanvasController to initialize race events
|
||||
* the CanvasController then uses the event data to make the animations
|
||||
*/
|
||||
public class RaceController {
|
||||
Race race = null;
|
||||
|
||||
public void initializeRace() {
|
||||
String raceConfigFile = "/config/config.xml";
|
||||
String teamsConfigFile = "/config/teams.xml";
|
||||
|
||||
try {
|
||||
race = createRace(raceConfigFile, teamsConfigFile);
|
||||
} catch (Exception e) {
|
||||
System.out.println("There was an error creating the race.");
|
||||
}
|
||||
|
||||
if (race != null) {
|
||||
race.startRace();
|
||||
} else {
|
||||
System.out.println("There was an error creating the race. Exiting.");
|
||||
}
|
||||
}
|
||||
|
||||
public Race createRace(String configFile, String teamsConfigFile) throws Exception {
|
||||
Race race = new Race();
|
||||
// StreamParser.xmlObject
|
||||
// Read team names from file
|
||||
// TeamsParser tp = new TeamsParser(teamsConfigFile);
|
||||
|
||||
// Read course from file
|
||||
// ConfigParser config = new ConfigParser(configFile);
|
||||
|
||||
ArrayList<String> boatNames = new ArrayList<>();
|
||||
// ArrayList<Boat> teams = tp.getBoats();
|
||||
Map<Long, Yacht> teams = StreamParser.getBoatsPos();
|
||||
|
||||
//get race size
|
||||
int numberOfBoats = teams.size();
|
||||
|
||||
//get time scale
|
||||
// double timeScale = config.getTimeScale();
|
||||
// race.setTimeScale(timeScale);
|
||||
|
||||
for (Yacht boat : teams.values()) {
|
||||
boatNames.add(boat.getBoatName());
|
||||
race.addBoat(boat);
|
||||
}
|
||||
|
||||
// Shuffle team names
|
||||
long seed = System.nanoTime();
|
||||
Collections.shuffle(boatNames, new Random(seed));
|
||||
|
||||
if (numberOfBoats > Array.getLength(boatNames.toArray())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CourseParser course = new CourseParser("/config/course.xml");
|
||||
race.addCourse(course.getCourse());
|
||||
|
||||
return race;
|
||||
}
|
||||
|
||||
public Race getRace() {
|
||||
return race;
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package seng302.controllers;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import seng302.models.Race;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Created by ptg19 on 20/03/17.
|
||||
*/
|
||||
public class RaceResultController implements Initializable{
|
||||
@FXML private AnchorPane window;
|
||||
@FXML private VBox resultsVBox;
|
||||
private Race race;
|
||||
|
||||
RaceResultController(Race race){
|
||||
this.race = race;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
int boatPosition = this.race.getFinishedBoats().length;
|
||||
|
||||
for (int i = this.race.getFinishedBoats().length - 1; i >= 0; i--){
|
||||
resultsVBox.getChildren().add(0, new Text(boatPosition + ": " + this.race.getFinishedBoats()[i].getBoatName()));
|
||||
boatPosition--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
package seng302.models;
|
||||
|
||||
import seng302.models.mark.Mark;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Race class containing the boats and legs in the race
|
||||
* Created by mra106 on 8/3/2017.
|
||||
*/
|
||||
public class Race {
|
||||
|
||||
private ArrayList<Yacht> boats; // The boats in the race
|
||||
private ArrayList<Yacht> finishingOrder; // The order in which the boats finish the race
|
||||
private HashMap<Yacht, List> events = new HashMap<>(); // The events that occur in the race
|
||||
private List<Mark> course; // Marks in the race
|
||||
private long startTime = 0;
|
||||
private double timeScale = 1;
|
||||
private boolean raceFinished = false; // Race is finished
|
||||
private int raceTime = -2; // Current time in the race
|
||||
|
||||
/**
|
||||
* Race class containing the boats and legs in the race
|
||||
*/
|
||||
public Race() {
|
||||
this.boats = new ArrayList<>();
|
||||
this.finishingOrder = new ArrayList<>();
|
||||
this.course = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a boat to the race
|
||||
*
|
||||
* @param boat, the boat to add
|
||||
*/
|
||||
public void addBoat(Yacht boat) {
|
||||
boats.add(boat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of boats in a random order
|
||||
*
|
||||
* @return a list of boats
|
||||
*/
|
||||
public Yacht[] getShuffledBoats() {
|
||||
// Shuffle the list of boats
|
||||
long seed = System.nanoTime();
|
||||
Collections.shuffle(this.boats, new Random(seed));
|
||||
|
||||
return boats.toArray(new Yacht[boats.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of boats in the order that they
|
||||
* finished the race (position 0 is first place)
|
||||
*
|
||||
* @return a list of boats
|
||||
*/
|
||||
public Yacht[] getFinishedBoats() {
|
||||
return this.finishingOrder.toArray(new Yacht[this.finishingOrder.size()]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of boats in the race
|
||||
*
|
||||
* @return a list of the boats competing in the race
|
||||
*/
|
||||
public Yacht[] getBoats() {
|
||||
return boats.toArray(new Yacht[boats.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets time scale
|
||||
*
|
||||
* @param timeScale
|
||||
*/
|
||||
public void setTimeScale(double timeScale) {
|
||||
this.timeScale = timeScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate all events that will happen during the race.
|
||||
*/
|
||||
private void generateEvents() {
|
||||
|
||||
for (Yacht boat : this.boats) {
|
||||
double totalDistance = 0;
|
||||
int numberOfMarks = this.course.size();
|
||||
|
||||
for (int i = 0; i < numberOfMarks; i++) {
|
||||
Double time = (totalDistance / boat.getVelocity() / timeScale);
|
||||
|
||||
// If there are singleMarks after this event
|
||||
if (i < numberOfMarks - 1) {
|
||||
Event event = new Event(time, boat, course.get(i), course.get(i + 1), i);
|
||||
|
||||
try {
|
||||
events.get(boat).add(event);
|
||||
|
||||
} catch (NullPointerException e) {
|
||||
events.put(boat, new ArrayList<>(Arrays.asList(event)));
|
||||
}
|
||||
totalDistance += event.getDistanceBetweenMarks();
|
||||
//System.out.println(totalDistance);
|
||||
//System.out.println(boat.getVelocity());
|
||||
}
|
||||
|
||||
// There are no more marks after this event
|
||||
|
||||
else{
|
||||
Event event = new Event(time, boat, course.get(i), i);
|
||||
events.get(boat).add(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts a race and generates all events for the race.
|
||||
*/
|
||||
public void startRace() {
|
||||
// record start time.
|
||||
this.startTime = System.currentTimeMillis();
|
||||
generateEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the race course
|
||||
* @param course a list of marks in the course
|
||||
*/
|
||||
public void addCourse(List<Mark> course) {
|
||||
this.course = course;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of marks in the course
|
||||
* @return
|
||||
*/
|
||||
public List<Mark> getCourse() {
|
||||
return course;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of the events in the race
|
||||
* @return
|
||||
*/
|
||||
public HashMap<Yacht, List> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a boat as finished
|
||||
* @param boat The boat that has finished the race/home/cosc/student/wmu16
|
||||
*/
|
||||
public void setBoatFinished(Yacht boat){
|
||||
this.finishingOrder.add(boat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the race as finished
|
||||
*/
|
||||
public void setRaceFinished(){
|
||||
this.raceFinished = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether or not the race is finished
|
||||
* @return true if the race is finished
|
||||
*/
|
||||
public boolean isRaceFinished(){
|
||||
return this.raceFinished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the race time
|
||||
* @param raceTime the race time in seconds
|
||||
*/
|
||||
public void setRaceTime(int raceTime){
|
||||
this.raceTime = raceTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the race time
|
||||
* @return the race time in seconds
|
||||
*/
|
||||
public int getRaceTime(){
|
||||
return this.raceTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the race time by one second
|
||||
*/
|
||||
public void incrementRaceTime(){
|
||||
this.raceTime += this.timeScale;
|
||||
}
|
||||
}
|
||||
@@ -53,8 +53,8 @@ public class MarkGroup extends RaceObject {
|
||||
};
|
||||
super.getChildren().add(markCircle);
|
||||
} else {
|
||||
marks.add(((GateMark) mark).getSingleMark1());
|
||||
marks.add(((GateMark) mark).getSingleMark2());
|
||||
// marks.add(((GateMark) mark).getSingleMark1());
|
||||
// marks.add(((GateMark) mark).getSingleMark2());
|
||||
nodePixelVelocitiesX = new double[]{0d,0d};
|
||||
nodePixelVelocitiesY = new double[]{0d,0d};
|
||||
nodeDestinations = new Point2D[2];
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
package seng302.models.parsers;
|
||||
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import java.util.DoubleSummaryStatistics;
|
||||
|
||||
public class ConfigParser extends FileParser {
|
||||
|
||||
private Document doc;
|
||||
|
||||
public ConfigParser(String path) {
|
||||
super(path);
|
||||
this.doc = this.parseFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets wind direction from config file.
|
||||
*
|
||||
* @return a double type degree, or 0 if no value or invalid value is found
|
||||
*/
|
||||
public double getWindDirection() {
|
||||
return getDoubleByTagName("wind-direction", 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a non negative time scale for the race
|
||||
*
|
||||
* @return a double type scale, or 0 if no scale or invalid scale is found
|
||||
*/
|
||||
public double getTimeScale() {
|
||||
return getDoubleByTagName("time-scale", 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a double type number by given tag name found in xml file
|
||||
*
|
||||
* @param tagName a string of tag name
|
||||
* @param defaultVal value returned if no value or invalid value is found
|
||||
* @return value found
|
||||
*/
|
||||
public double getDoubleByTagName(String tagName, double defaultVal) {
|
||||
double val = defaultVal;
|
||||
try {
|
||||
Node node = this.doc.getElementsByTagName(tagName).item(0);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
val = Double.valueOf(element.getTextContent());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string by given tag name found in xml file
|
||||
*
|
||||
* @param tagName a string of tag name
|
||||
* @param defaultVal a string returned if no value or invalid value is found
|
||||
* @return string found
|
||||
*/
|
||||
public String getStringByTagName(String tagName, String defaultVal) {
|
||||
String string = defaultVal;
|
||||
try {
|
||||
Node node = this.doc.getElementsByTagName(tagName).item(0);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
string = element.getTextContent();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package seng302.models.parsers;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import seng302.models.mark.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* parse a course xml file
|
||||
* Created by Haoming Yin (hyi25) on 16/3/2017
|
||||
*/
|
||||
public class CourseParser extends FileParser {
|
||||
|
||||
private Document doc;
|
||||
private HashMap<String, Mark> marks = new HashMap<>();
|
||||
|
||||
public CourseParser(String path) {
|
||||
super(path);
|
||||
this.doc = this.parseFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* create a mark by given node
|
||||
*
|
||||
* @param node
|
||||
* @return a mark, or null if fails to create a mark
|
||||
*/
|
||||
private SingleMark generateSingleMark(Node node) {
|
||||
try {
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
String name = element.getElementsByTagName("name").item(0).getTextContent();
|
||||
double lat = Double.valueOf(element.getElementsByTagName("latitude").item(0).getTextContent());
|
||||
double lon = Double.valueOf(element.getElementsByTagName("longitude").item(0).getTextContent());
|
||||
int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
|
||||
SingleMark singleMark = new SingleMark(name, lat, lon, id);
|
||||
return singleMark;
|
||||
} else {
|
||||
throw new NoSuchElementException("Cannot generate a mark by given node.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an arrayList of gates
|
||||
*
|
||||
* @return an arrayList of gates, or null if no gate has been found.
|
||||
*/
|
||||
private void generateGateMarks() {
|
||||
ArrayList<GateMark> gateMarks = new ArrayList<>();
|
||||
|
||||
try {
|
||||
NodeList nodes = doc.getElementsByTagName("gate");
|
||||
|
||||
for (int i = 0; i < nodes.getLength(); i++) {
|
||||
Node node = nodes.item(i);
|
||||
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
String name = element.getElementsByTagName("name").item(0).getTextContent();
|
||||
SingleMark mark1 = generateSingleMark(element.getElementsByTagName("mark").item(0));
|
||||
SingleMark mark2 = generateSingleMark(element.getElementsByTagName("mark").item(1));
|
||||
GateMark gateMark;
|
||||
if (name.equals("Start") || name.equals("Finish"))
|
||||
gateMark = new GateMark(name, MarkType.CLOSED_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
|
||||
else
|
||||
gateMark = new GateMark(name, MarkType.OPEN_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
|
||||
marks.put(name, gateMark);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an arrayList of marks
|
||||
*
|
||||
* @return an arrayList of marks, or null if no gate has been found.
|
||||
*/
|
||||
private void generateSingleMarks() {
|
||||
ArrayList<SingleMark> singleMarks = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// find the "marks" tag
|
||||
Node node = doc.getElementsByTagName("marks").item(0);
|
||||
// iterate all "marks"'s children
|
||||
for (Node n = node.getFirstChild(); n != null; n = n.getNextSibling()) {
|
||||
// if node's tag name is "mark"
|
||||
if (n.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) n;
|
||||
if (element.getNodeName() == "mark") {
|
||||
Mark mark = generateSingleMark(n);
|
||||
marks.put(mark.getName(), mark);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the order of all the marks along a course
|
||||
*
|
||||
* @return an arrayList of the names of ordered course marks
|
||||
*/
|
||||
private ArrayList<String> getOrder() {
|
||||
ArrayList<String> markOrder = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Node orderNode = doc.getElementsByTagName("order").item(0);
|
||||
for (Node node = orderNode.getFirstChild(); node != null; node = node.getNextSibling()) {
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
String name = element.getTextContent();
|
||||
markOrder.add(name);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return markOrder;
|
||||
}
|
||||
|
||||
public ArrayList<Mark> getCourse() {
|
||||
generateSingleMarks();
|
||||
generateGateMarks();
|
||||
ArrayList<Mark> course = new ArrayList<>();
|
||||
try {
|
||||
for (String mark : getOrder()) {
|
||||
course.add(marks.get(mark));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return course;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package seng302.models.parsers;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
|
||||
/**
|
||||
* Created by Haoming Yin (hyi25) on 16/3/2017
|
||||
*/
|
||||
public abstract class FileParser {
|
||||
|
||||
private String filePath;
|
||||
|
||||
public FileParser() {}
|
||||
|
||||
public FileParser(String path) {
|
||||
this.filePath = path;
|
||||
}
|
||||
|
||||
protected Document parseFile() {
|
||||
try {
|
||||
InputStream is = getClass().getResourceAsStream(this.filePath);
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.parse(is);
|
||||
// optional, in order to recover info from broken line.
|
||||
doc.getDocumentElement().normalize();
|
||||
return doc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Document parseFile(String xmlString) {
|
||||
try {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
|
||||
// optional, in order to recover info from broken line.
|
||||
doc.getDocumentElement().normalize();
|
||||
return doc;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package seng302.models.parsers;
|
||||
|
||||
/**
|
||||
* Created by Kusal on 4/24/2017.
|
||||
*/
|
||||
public enum PacketType {
|
||||
HEARTBEAT,
|
||||
RACE_STATUS,
|
||||
DISPLAY_TEXT_MESSAGE,
|
||||
XML_MESSAGE,
|
||||
RACE_START_STATUS,
|
||||
YACHT_EVENT_CODE,
|
||||
YACHT_ACTION_CODE,
|
||||
CHATTER_TEXT,
|
||||
BOAT_LOCATION,
|
||||
MARK_ROUNDING,
|
||||
COURSE_WIND,
|
||||
AVG_WIND,
|
||||
OTHER;
|
||||
|
||||
static PacketType assignPacketType(int packetType){
|
||||
switch(packetType){
|
||||
case 1:
|
||||
return HEARTBEAT;
|
||||
case 12:
|
||||
return RACE_STATUS;
|
||||
case 20:
|
||||
return DISPLAY_TEXT_MESSAGE;
|
||||
case 26:
|
||||
return XML_MESSAGE;
|
||||
case 27:
|
||||
return RACE_START_STATUS;
|
||||
case 29:
|
||||
return YACHT_EVENT_CODE;
|
||||
case 31:
|
||||
return YACHT_ACTION_CODE;
|
||||
case 36:
|
||||
return CHATTER_TEXT;
|
||||
case 37:
|
||||
return BOAT_LOCATION;
|
||||
case 38:
|
||||
return MARK_ROUNDING;
|
||||
case 44:
|
||||
return COURSE_WIND;
|
||||
case 47:
|
||||
return AVG_WIND;
|
||||
default:
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
//package seng302.models.parsers;
|
||||
//
|
||||
//import org.w3c.dom.*;
|
||||
//import seng302.models.Yacht;
|
||||
//
|
||||
//import java.util.ArrayList;
|
||||
//import java.util.NoSuchElementException;
|
||||
//
|
||||
//public class TeamsParser extends FileParser {
|
||||
//
|
||||
// private Document doc;
|
||||
//
|
||||
// public TeamsParser(String path) {
|
||||
// super(path);
|
||||
// this.doc = this.parseFile();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Create a boat instance by a given team node
|
||||
// * @param node a boat node containing name, alias and velocity
|
||||
// * @return an instance of Boat
|
||||
// */
|
||||
// private Yacht parseBoat(Node node) {
|
||||
// try {
|
||||
// if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
// Element element = (Element) node;
|
||||
// String name = element.getElementsByTagName("name").item(0).getTextContent();
|
||||
// String alias = element.getElementsByTagName("alias").item(0).getTextContent();
|
||||
// double velocity = Double.valueOf(element.getElementsByTagName("velocity").item(0).getTextContent());
|
||||
// int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
|
||||
// Yacht boat = new Yacht(name, velocity, alias, id);
|
||||
// return boat;
|
||||
// } else {
|
||||
// throw new NoSuchElementException("Cannot generate a boat by given node");
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Create an arraylist of boats instance.
|
||||
// * @return an arraylist of boats in teams file
|
||||
// */
|
||||
// public ArrayList<Yacht> getBoats() {
|
||||
// ArrayList<Yacht> boats = new ArrayList<>();
|
||||
//
|
||||
// try {
|
||||
// NodeList nodes = this.doc.getElementsByTagName("team");
|
||||
// for (int i = 0; i < nodes.getLength(); i++) {
|
||||
// Node node = nodes.item(i);
|
||||
// boats.add(parseBoat(node));
|
||||
// }
|
||||
// return boats;
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
||||
//
|
||||
+3
-18
@@ -1,12 +1,12 @@
|
||||
package seng302.models.parsers;
|
||||
package seng302.models.stream;
|
||||
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||
import seng302.models.parsers.packets.StreamPacket;
|
||||
import seng302.models.stream.packets.BoatPositionPacket;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -66,24 +66,9 @@ public class StreamParser extends Thread{
|
||||
Thread.sleep(1);
|
||||
}
|
||||
while (appRunning){
|
||||
// StreamPacket packet = StreamReceiver.packetBuffer.peek();
|
||||
//this code adds a delay to reading from the packetBuffer so
|
||||
//out of order packets have time to order themselves in the queue
|
||||
// int delayTime = 1000;
|
||||
// int loopTime = delayTime * 10;
|
||||
// long transitTime = (System.currentTimeMillis()%loopTime - packet.getTimeStamp()%loopTime);
|
||||
// if (transitTime < 0){
|
||||
// transitTime = loopTime + transitTime;
|
||||
// }
|
||||
// if (transitTime < delayTime) {
|
||||
// long sleepTime = delayTime - (transitTime);
|
||||
// Thread.sleep(sleepTime);
|
||||
// }
|
||||
StreamPacket packet = StreamReceiver.packetBuffer.take();
|
||||
parsePacket(packet);
|
||||
Thread.sleep(1);
|
||||
while (StreamReceiver.packetBuffer.peek() == null) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
+2
-4
@@ -1,13 +1,11 @@
|
||||
package seng302.models.parsers;
|
||||
package seng302.models.stream;
|
||||
|
||||
import seng302.models.parsers.packets.StreamPacket;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.zip.CRC32;
|
||||
+10
-2
@@ -1,14 +1,14 @@
|
||||
package seng302.models.parsers;
|
||||
package seng302.models.stream;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.mark.MarkType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -301,6 +301,7 @@ public class XMLParser {
|
||||
public class CompoundMark {
|
||||
private Integer markID;
|
||||
private String cMarkName;
|
||||
private MarkType markType;
|
||||
private ArrayList<Mark> marks;
|
||||
|
||||
CompoundMark(Node compoundMark) {
|
||||
@@ -308,6 +309,12 @@ public class XMLParser {
|
||||
this.markID = getNodeAttributeInt(compoundMark, "CompoundMarkID");
|
||||
this.cMarkName = getNodeAttributeString(compoundMark, "Name");
|
||||
NodeList childMarks = compoundMark.getChildNodes();
|
||||
if (childMarks.getLength() > 1){
|
||||
markType = MarkType.OPEN_GATE;
|
||||
} else {
|
||||
markType = MarkType.SINGLE_MARK;
|
||||
}
|
||||
|
||||
for (int i = 0; i < childMarks.getLength(); i++) {
|
||||
Node markNode = childMarks.item(i);
|
||||
if (markNode.getNodeName().equals("Mark")) {
|
||||
@@ -319,6 +326,7 @@ public class XMLParser {
|
||||
|
||||
public Integer getMarkID() { return markID; }
|
||||
public String getcMarkName() { return cMarkName; }
|
||||
public MarkType getMarkType() { return markType; }
|
||||
public ArrayList<Mark> getMarks() { return marks; }
|
||||
|
||||
public class Mark {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.parsers.packets;
|
||||
package seng302.models.stream.packets;
|
||||
|
||||
public class BoatPositionPacket {
|
||||
private long boatId;
|
||||
+1
-3
@@ -1,4 +1,4 @@
|
||||
package seng302.models.parsers.packets;
|
||||
package seng302.models.stream.packets;
|
||||
|
||||
/**
|
||||
* Created by Kusal on 4/24/2017.
|
||||
@@ -48,6 +48,4 @@ public enum PacketType {
|
||||
}
|
||||
return OTHER;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.parsers.packets;
|
||||
package seng302.models.stream.packets;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 23/04/17.
|
||||
@@ -1,21 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.scene.shape.*?>
|
||||
<?import javafx.scene.text.*?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
<GridPane prefHeight="1080.0" prefWidth="1920.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.RaceViewController">
|
||||
<columnConstraints>
|
||||
|
||||
Reference in New Issue
Block a user