Removed unneeded files, also fixed heading calculation

Tags #story[829]
This commit is contained in:
Michael Rausch
2017-04-30 23:29:15 +12:00
parent d07c660eb9
commit e7f9954970
21 changed files with 15 additions and 1292 deletions
-5
View File
@@ -6,7 +6,6 @@ import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import seng302.server.ServerThread; import seng302.server.ServerThread;
import seng302.server.simulator.Simulator;
public class App extends Application public class App extends Application
{ {
@@ -15,13 +14,9 @@ public class App extends Application
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml")); Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
primaryStage.setTitle("RaceVision"); primaryStage.setTitle("RaceVision");
primaryStage.setScene(new Scene(root)); primaryStage.setScene(new Scene(root));
// primaryStage.show();
} }
public static void main(String[] args) { public static void main(String[] args) {
new ServerThread("Racevision Test Server"); new ServerThread("Racevision Test Server");
//new Thread(new Simulator(1000)).run();
//launch(args);
} }
} }
@@ -1,176 +0,0 @@
package seng302.controllers;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.paint.Color;
import seng302.models.Boat;
import seng302.models.Course;
import seng302.models.Race;
import seng302.models.mark.Mark;
import seng302.models.mark.MarkType;
import seng302.models.parsers.ConfigParser;
import seng302.models.parsers.CourseParser;
import seng302.models.parsers.TeamsParser;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
/**
* Controller for main window for RaceVision
* Created by Kusal on 3/22/2017.
*/
public class Controller implements Initializable {
private static final int MARKER_WIDTH = 10;
private static final int MARKER_HEIGHT = 10;
private static final double ORIGINAL_LAT = 32.321504;
private static final double ORIGINAL_LON = -64.857063;
@FXML
private Canvas courseCanvas;
@FXML
private Group boatGroup;
@FXML
private Button playPauseButton;
private Course thisCourse;
private ArrayList<Boat> startingBoats;
private int raceDuration;
private Race race;
private boolean raceRunning = false;
private CourseParser cp;
private TeamsParser tp;
private ConfigParser cop;
@Override
public void initialize(URL location, ResourceBundle resources) {
cp = new CourseParser("/config/course.xml");
tp = new TeamsParser("/config/teams.xml");
cop = new ConfigParser("/config/config.xml");
thisCourse = new Course(cp.getCourse());
startingBoats = tp.getBoats();
race = new Race(thisCourse.getMarks(), startingBoats, cop.getTimeScale(), this);
init();
}
/**
* Initialises a race on the screen after it has been loaded
*/
private void init() {
initMap();
initBoats();
playPauseButton.setDisable(false);
}
/**
* Initialise the map by drawing it onto courseCanvas.
*/
private void initMap() {
//Create the boundary of the course displayed on the map
drawCourse();
}
/**
* Draw the markers and gates onto the courseCanvas.
*/
private void drawCourse() {
GraphicsContext gc = courseCanvas.getGraphicsContext2D();
gc.save();
for(Mark rp : thisCourse.getMarks()) {
if (rp.getMarkType().equals(MarkType.SINGLE_MARK)) {
gc.setFill(Color.GRAY);
gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT);
} else if (rp.getMarkType().equals(MarkType.GATE_MARK)) {
gc.setFill(Color.GRAY);
gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT);
// gc.fillOval(((OpenGate) rp).getDrawX2(), ((OpenGate) rp).getDrawY2(), MARKER_WIDTH, MARKER_HEIGHT);
gc.setLineWidth(2);
gc.setFill(Color.GREEN);
gc.setStroke(Color.GREEN);
}
gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT);
// gc.fillOval(((ClosedGate) rp).getDrawX2(), ((ClosedGate) rp).getDrawY2(), MARKER_WIDTH, MARKER_HEIGHT);
// gc.strokeLine(convertLongToX(rp.getLongitude()) + 5, convertLatToY(rp.getLatitude()) + 5, ((ClosedGate) rp).getDrawX2() + 5, ((ClosedGate) rp).getDrawY2() + 5);
}
gc.restore();
}
/**
* Places boats at starting line
*/
private void initBoats() {
// int startingX = (convertLongToX(thisCourse.getMarks().get(0).getLongitude())).intValue();
// int startingY = (convertLatToY(thisCourse.getMarks().get(0).getLongitude())).intValue();
int startingX = 50;
int startingY = 100;
for(Boat boat : startingBoats) {
boat.moveBoatTo(startingX, startingY);
boatGroup.getChildren().add(boat.getBoatObject());
boat.setCurrentLeg(race.getRaceLegs().get(0));
boat.setHeading(race.getRaceLegs().get(0).getHeading());
boat.setLegDistance(0d);
}
}
/**
* Starts and stops the race depending on whether or not it is already running
*/
public void playPause() {
if (!raceRunning) {
play();
} else {
pause();
}
}
/**
* Plays the race and updates the play / pause button
*/
private void play() {
race.run();
raceRunning = true;
playPauseButton.setText("Pause");
}
/**
* Pauses the race and updates the play / pause button
*/
private void pause() {
race.pause();
raceRunning = false;
playPauseButton.setText("Play");
}
private Double convertLongToX(Double lon) {
return (lon - ORIGINAL_LON) * thisCourse.getDistanceScaleFactor();
}
private Double convertLatToY(Double lat) {
return (ORIGINAL_LAT - lat) * thisCourse.getDistanceScaleFactor();
}
public Button getPlayPauseButton() {
return playPauseButton;
}
}
-174
View File
@@ -1,174 +0,0 @@
package seng302.models;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
/**
* Represents a boat in the race.
*/
public class Boat {
private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d;
private static final double VELOCITY_WAKE_RATIO = 1/2d; //Ratio for deciding how long the wake will be wrt velocity
private String teamName; // The name of the team, this is also the name of the boat
private Double velocity; // In meters/second
private Double lat; // Boats position
private Double lon; // -
private Double legDistance;
private Color color;
private Leg currentLeg;
private Double heading;
private String shortName;
private Polygon boatObject = new Polygon();
public Boat(String teamName) {
this.teamName = teamName;
this.velocity = 10d; // Default velocity
this.lat = 0.0;
this.lon = 0.0;
this.legDistance = 0.0;
this.shortName = "";
}
/**
* Represents a boat in the race.
*
* @param teamName The name of the team sailing the boat
* @param boatVelocity The speed of the boat in meters/second
* @param shortName A shorter version of the teams name
*/
public Boat(String teamName, double boatVelocity, String shortName) {
this.teamName = teamName;
this.velocity = boatVelocity;
this.legDistance = 0.0;
this.color = Colors.getColor();
this.shortName = shortName;
this.boatObject.getPoints().addAll(BOAT_WIDTH /2,0.0,
BOAT_WIDTH, BOAT_HEIGHT,
0.0, BOAT_HEIGHT);
}
/**
* Returns the name of the team sailing the boat
*
* @return The name of the team
*/
public String getTeamName() {
return this.teamName;
}
/**
* Sets the name of the team sailing the boat
*
* @param teamName The name of the team
*/
public void setTeamName(String teamName) {
this.teamName = teamName;
}
/**
* Gets velocity of the boat
*
* @return a float number of the boat velocity
*/
public double getVelocity() {
return this.velocity;
}
/**
* Sets velocity of the boat
*
* @param velocity The velocity of boat
*/
public void setVelocity(double velocity) {
this.velocity = velocity;
}
/**
* Sets the boats location
*
* @param lat, the boats latitude
* @param lon, the boats longitude
*/
public void setLocation(double lat, double lon) {
this.lat = lat;
this.lon = lon;
}
public Double getLegDistance() {
return legDistance;
}
public void setLegDistance(double legDistance){
this.legDistance = legDistance;
}
public double getLatitude(){
return this.lat;
}
public double getLongitude(){
return this.lon;
}
public Color getColor() {
return color;
}
public double getSpeedInKnots(){
return Math.round((this.velocity * 1.94384) * 100d) / 100d;
}
public Leg getCurrentLeg() {
return currentLeg;
}
public void setCurrentLeg(Leg currentLeg) {
this.currentLeg = currentLeg;
}
public void setHeading(double heading){
this.heading = heading;
}
public double getHeading(){
return this.heading;
}
public String getShortName(){
return this.shortName;
}
/**
* Moves the boat and its children annotations from its current coordinates by specified amounts.
* @param x The amount to move the X coordinate by
* @param y The amount to move the Y coordinate by
*/
void moveBoatBy(Double x, Double y) {
boatObject.setLayoutX(boatObject.getLayoutX() + x);
boatObject.setLayoutY(boatObject.getLayoutY() + y);
boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY());
}
/**
* Moves the boat and its children annotations to coordinates specified
* @param x The X coordinate to move the boat to
* @param y The Y coordinate to move the boat to
*/
public void moveBoatTo(int x, int y) {
boatObject.setLayoutX(x);
boatObject.setLayoutY(y);
boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY());
}
public Polygon getBoatObject() {
return boatObject;
}
}
-20
View File
@@ -1,20 +0,0 @@
package seng302.models;
import javafx.scene.paint.Color;
/**
* Created by ryan_ on 16/03/2017.
*/
public enum Colors {
RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE;
static Integer index = 0;
public static Color getColor() {
index++;
if (index > 6) {
index = 1;
}
return Color.valueOf(values()[index-1].toString());
}
}
-54
View File
@@ -1,54 +0,0 @@
package seng302.models;
/**
* Created by wmu16 on 4/8/17.
*/
import javafx.scene.canvas.Canvas;
import javafx.util.Pair;
import seng302.models.mark.Mark;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* Class for describing the course information for the canvas
* Created by wmu16 on 22/03/17.
*/
public class Course {
private ArrayList<Leg> Legs;
private ArrayList<Mark> marks;
public static final Integer SCALE = 160000;
public Course(ArrayList<Mark> marks) {
this.marks = marks;
this.Legs = makeLegs();
}
/**
* Makes the race legs out of all the marker marks for the course
* @return ArrayList of Legs
*/
private ArrayList<Leg> makeLegs() {
ArrayList<Leg> Legs = new ArrayList<>();
for (int i = 0; i < marks.size()-1; i++) {
Legs.add(new Leg(marks.get(i), marks.get(i+1)));
}
return Legs;
}
public ArrayList<Mark> getMarks() {
return marks;
}
public double getDistanceScaleFactor() {
return SCALE;
}
public ArrayList<Leg> getLegs() {
return Legs;
}
}
-97
View File
@@ -1,97 +0,0 @@
package seng302.models;
import seng302.models.mark.Mark;
/**
* Class for defining the leg of a race between two markers
* Created by cir27 on 3/03/17.
*/
public class Leg {
private final double ORIGIN_LAT = 32.320504;
private final double ORIGIN_LON = -64.857063;
private final double SCALE = 16000;
private Double distance;
private Double heading;
private Mark end;
private Mark start;
Leg(Mark start, Mark end) {
this.distance = calculateMarkerDistance(start, end);
this.heading = angleFromCoordinate(start, end);
this.start = start;
this.end = end;
}
/**
* Calculates the euclidian distance between two markers on the canvas using xy coordinates
*
* @param geoPointOne first geographical point
* @param geoPointTwo second geographical point
* @return the distance between two points in meters
*/
private Double calculateMarkerDistance(Mark geoPointOne, Mark geoPointTwo) {
double earth_radius = 6378.137;
double dLat = geoPointTwo.getLatitude() * Math.PI / 180 - geoPointOne.getLatitude() * Math.PI / 180;
double dLon = geoPointTwo.getLongitude() * Math.PI / 180 - geoPointOne.getLongitude() * Math.PI / 180;
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(geoPointOne.getLatitude() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = earth_radius * c;
return d * 1000;
}
/**
* Calculates the angle between to angular co-ordinates on a sphere.
*
* @param geoPointOne first geographical location
* @param geoPointTwo second geographical location
* @return the angle from point one to point two
*/
private Double angleFromCoordinate(Mark geoPointOne, Mark geoPointTwo) {
if (geoPointTwo == null){
return 0.0;
}
double x1 = (geoPointOne.getLongitude() - ORIGIN_LON) * SCALE;
double y1 = (ORIGIN_LAT - geoPointOne.getLatitude()) * SCALE;
double x2 = (geoPointTwo.getLongitude() - ORIGIN_LON) * SCALE;
double y2 = (ORIGIN_LAT - geoPointTwo.getLatitude()) * SCALE;
double headingRadians = Math.atan2(y2-y1, x2-x1);
if (headingRadians < 0){
headingRadians += 2 * Math.PI;
}
// Convert back to degrees, and flip 180 degrees
// return ((headingRadians) * 180) / Math.PI;
return (Math.toDegrees(headingRadians) + 90) % 360;
}
Double getDistance()
{
return this.distance;
}
Mark getEnd()
{
return this.end;
}
public Mark getStart() {
return start;
}
public Double getHeading()
{
return this.heading;
}
}
-236
View File
@@ -1,236 +0,0 @@
package seng302.models;
import javafx.animation.AnimationTimer;
import seng302.controllers.Controller;
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 extends Thread {
private static final double UPDATE_TIME = 0.016666; // 1 / 60 ie 60fps
private ArrayList<Boat> boats; // The boats in the race
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
private List<Mark> markers; // Marks in the race
private List<Leg> raceLegs;
private boolean raceFinished = false; // Race is finished
private int raceTime = -2; // Current time in the race
private Double timeScale = null;
private boolean raceStarted = false;
private Controller controller;
/**
* Race class containing the boats and legs in the race
*/
public Race(List<Mark> markers, ArrayList<Boat> boats, Double timescale, Controller controller) {
this.boats = boats;
this.markers = markers;
this.raceLegs = makeRaceLegs();
this.controller = controller;
this.timeScale = timescale;
this.finishingOrder = new ArrayList<>();
}
/**
* Makes the race legs out of all the marker points for the course
* @return ArrayList of raceLegs
*/
private ArrayList<Leg> makeRaceLegs() {
ArrayList<Leg> raceLegs = new ArrayList<>();
for (int i=0; i < markers.size()-1; i++) {
raceLegs.add(new Leg(markers.get(i), markers.get(i+1)));
}
return raceLegs;
}
/**
* A timer that is called every frame to call the action of moving the boats
*/
private AnimationTimer at = new AnimationTimer() {
@Override
public void handle(long now) {
//Updating Boat positions
if(finishingOrder.size() != boats.size()) {
// update the time
boats.stream().filter(boat -> !finishingOrder.contains(boat)).forEach(boat -> {
updateBoatPosition(boat);
});
} else {
at.stop();
}
}
};
/**
* Begins the race simulation
*/
@Override
public void run() {
if (!raceStarted) {
// controller.getPlayPauseButton().setDisable(true);
at.start();
}
}
/**
* Moves the coordinates of the boats.
* @param boat The boat to update the position of
*/
private void updateBoatPosition(Boat boat) {
Double thisHeading = boat.getHeading();
// TODO: 4/8/17 wmu16 - Add a distance scale factor from lat long distance in Metres to xy equivalent
Double hypMove = boat.getVelocity() * UPDATE_TIME * timeScale; //* distanceScaleFactor
boat.setLegDistance(boat.getLegDistance() + hypMove);
moveBoat(boat, thisHeading, hypMove);
}
/**
* Moves a boat along coordinates by breaking down the distance moved along the hypotenuse into x and y components
* @param boat The Boat to move
* @param heading The heading the boat is moving at
* @param hypMove The distance moved along the hypotenuse (absolute distance)
*/
private void moveBoat(Boat boat, Double heading, Double hypMove) {
//If the boat has not yet passed the marker at the end of the leg increase its (x,y) as per normal
// TODO: 4/8/17 wmu16 - Initialising boat positions and legs and headings etc.
if(boat.getLegDistance() <= boat.getCurrentLeg().getDistance()) {
Double xMove = hypMove * Math.sin(Math.toRadians(heading));
Double yMove = - hypMove * Math.cos(Math.toRadians(heading));
boat.moveBoatBy(xMove, yMove);
//If the boat has finished...
} else if (getNextRaceLeg(boat.getCurrentLeg()).equals(boat.getCurrentLeg())) {
finishingOrder.add(boat);
//Otherwise apply the overflow distance of the leg to the next leg
} else {
Double overflowDistance = boat.getLegDistance() - boat.getCurrentLeg().getDistance();
boat.setCurrentLeg(getNextRaceLeg(boat.getCurrentLeg()));
boat.setHeading(boat.getCurrentLeg().getHeading());
boat.setLegDistance(overflowDistance);
moveBoat(boat, boat.getHeading(), overflowDistance);
}
}
/**
* Returns the next leg in the race
* @param currentRaceLeg The leg that you are currently on
* @return The next race leg or the same race leg if it has reached the end
*/
private Leg getNextRaceLeg(Leg currentRaceLeg) {
Leg nextRaceLeg = currentRaceLeg;
for(int i = 0; i< raceLegs.size() - 1; i++) {
if (raceLegs.get(i).equals(currentRaceLeg)) {
nextRaceLeg = raceLegs.get(i + 1);
}
}
return nextRaceLeg;
}
/**
* Returns a list of boats in the order that they
* finished the race (position 0 is first place)
*
* @return a list of boats
*/
public Boat[] getFinishedBoats() {
return this.finishingOrder.toArray(new Boat[this.finishingOrder.size()]);
}
/**
* Returns a list of boats in the race
*
* @return a list of the boats competing in the race
*/
public Boat[] getBoats() {
return boats.toArray(new Boat[boats.size()]);
}
/**
* Starts a race and generates all events for the race.
*/
public void startRace() {
// record start time.
}
public void pause() {
at.stop();
}
/**
* Get a list of marks in the markers
* @return
*/
public List<Mark> getMarkers() {
return markers;
}
/**
* Set a boat as finished
* @param boat The boat that has finished the race
*/
public void setBoatFinished(Boat 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;
}
public List<Leg> getRaceLegs() {
return raceLegs;
}
}
@@ -1,50 +0,0 @@
package seng302.models.mark;
/**
* To represent a gate mark which contains two single marks.
* Created by ptg19 on 16/03/17.
* Modified by Haoming Yin (hyi25) on 17/3/2017.
*/
public class GateMark extends Mark {
private SingleMark singleMark1;
private SingleMark singleMark2;
/**
* Create an instance of Gate Mark which contains two single mark
* @param name the name of the gate mark
* @param singleMark1 one single mark inside of the gate mark
* @param singleMark2 the second mark inside of the gate mark
*/
public GateMark(String name, SingleMark singleMark1, SingleMark singleMark2, double latitude, double longitude) {
super(name, MarkType.GATE_MARK, latitude, longitude);
this.singleMark1 = singleMark1;
this.singleMark2 = singleMark2;
}
public SingleMark getSingleMark1() {
return singleMark1;
}
public void setSingleMark1(SingleMark singleMark1) {
this.singleMark1 = singleMark1;
}
public SingleMark getSingleMark2() {
return singleMark2;
}
public void setSingleMark2(SingleMark singleMark2) {
this.singleMark2 = singleMark2;
}
public double getLatitude(){
//return (this.getSingleMark1().getLatitude() + this.getSingleMark2().getLatitude()) / 2;
return (this.getSingleMark1().getLatitude());
}
public double getLongitude(){
//return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2;
return (this.getSingleMark1().getLongitude());
}
}
@@ -1,54 +0,0 @@
package seng302.models.mark;
/**
* An abstract class to represent general marks
* Created by Haoming Yin (hyi25) on 17/3/17.
*/
public abstract class Mark {
private String name;
private MarkType markType;
private double latitude;
private double longitude;
/**
* Create a mark instance by passing its name and type
* @param name the name of the mark
* @param markType the type of mark. either GATE_MARK or SINGLE_MARK.
*/
public Mark (String name, MarkType markType) {
this.name = name;
this.markType = markType;
}
public Mark(String name, MarkType markType, double latitude, double longitude) {
this.name = name;
this.markType = markType;
this.latitude = latitude;
this.longitude = longitude;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public MarkType getMarkType() {
return markType;
}
public void setMarkType(MarkType markType) {
this.markType = markType;
}
public double getLatitude() {
return latitude;
}
public double getLongitude() {
return longitude;
}
}
@@ -1,36 +0,0 @@
package seng302.models.mark;
/**
* To represent two types of mark
* Created by Haoming Yin (hyi25) on 17/3/17.
*/
public enum MarkType {
UNKNOWN(0),
ROUNDING_MARK(1),
GATE_MARK(2),
// above mark types are from AC35 spec.
// more specific types for gate mark
WINDWARD(201),
LEEWARD(202),
START(203),
FINISH(204),
// single_mark is from old team-13 code base, for compatibility, it has not
// been removed yet
SINGLE_MARK(5);
private int type;
MarkType(int markType) {
this.type = markType;
}
public int getType() {
return this.type;
}
}
@@ -1,45 +0,0 @@
package seng302.models.mark;
/**
* Represents the marker as a single mark
*
* Created by Haoming Yin (hyi25) on 17/3/2017
*/
public class SingleMark extends Mark {
private double lat;
private double lon;
private String name;
/**
* Represents a marker
*
* @param name, the name of the marker*
* @param lat, the latitude of the marker
* @param lon, the longitude of the marker
*/
public SingleMark(String name, double lat, double lon) {
super(name, MarkType.SINGLE_MARK);
this.lat = lat;
this.lon = lon;
}
/**
* Represents the marker at the beginning of a leg
*
* @param name, the name of the marker
*/
public SingleMark(String name) {
super(name, MarkType.SINGLE_MARK);
this.lat = 0;
this.lon = 0;
}
public double getLatitude() {
return this.lat;
}
public double getLongitude() {
return this.lon;
}
}
@@ -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,140 +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());
SingleMark singleMark = new SingleMark(name, lat, lon);
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 = new GateMark(name, 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,37 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public abstract class FileParser {
private String filePath;
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;
}
}
}
@@ -1,63 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.*;
import seng302.models.Boat;
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 Boat 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());
Boat boat = new Boat(name, velocity, alias);
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<Boat> getBoats() {
ArrayList<Boat> 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;
}
}
}
@@ -17,14 +17,13 @@ public class ServerThread implements Runnable, Observer {
private StreamingServerSocket server; private StreamingServerSocket server;
private long startTime; private long startTime;
boolean raceStarted = false; boolean raceStarted = false;
boolean raceFinished = false;
Map<Integer,Boolean> boatsFinished = new HashMap<>(); Map<Integer,Boolean> boatsFinished = new HashMap<>();
private List<Boat> boats; private List<Boat> boats;
private Simulator raceSimulator; private Simulator raceSimulator;
private final int HEARTBEAT_PERIOD = 5000; private final int HEARTBEAT_PERIOD = 5000;
private final int RACE_STATUS_PERIOD = 1000/2; private final int RACE_STATUS_PERIOD = 1000;
private final int RACE_START_STATUS_PERIOD = 1000/2; private final int RACE_START_STATUS_PERIOD = 1000;
private final int BOAT_LOCATION_PERIOD = 1000/5; private final int BOAT_LOCATION_PERIOD = 1000/5;
private final int PORT_NUMBER = 8085; private final int PORT_NUMBER = 8085;
private final int TIME_TILL_RACE_START = 20*1000; private final int TIME_TILL_RACE_START = 20*1000;
@@ -188,6 +187,7 @@ public class ServerThread implements Runnable, Observer {
* Start sending race start status messages until race starts * Start sending race start status messages until race starts
*/ */
private void startSendingRaceStatusMessages(){ private void startSendingRaceStatusMessages(){
serverLog("Sending race status messages", 0);
Timer t = new Timer(); Timer t = new Timer();
t.schedule(new TimerTask() { t.schedule(new TimerTask() {
@Override @Override
@@ -248,9 +248,6 @@ public class ServerThread implements Runnable, Observer {
sendXml(); sendXml();
startSendingRaceStartStatusMessages(); startSendingRaceStartStatusMessages();
startSendingRaceStatusMessages(); startSendingRaceStatusMessages();
//serverLog("Sending Race Status Messages", 0);
} }
/** /**
@@ -267,16 +264,15 @@ public class ServerThread implements Runnable, Observer {
for (Boat b : ((Simulator) o).getBoats()){ for (Boat b : ((Simulator) o).getBoats()){
try { try {
Message m = new BoatLocationMessage(b.getSourceID(), 1, b.getLat(), Message m = new BoatLocationMessage(b.getSourceID(), 1, b.getLat(),
b.getLng(), b.getHeadingCorner().getBearingToNextCorner(), b.getLng(), b.getHeadingCorner().getBearingToNextCorner(),
((long) b.getSpeed())); ((long) b.getSpeed()));
server.send(m); server.send(m);
} catch (IOException e) { } catch (IOException e) {
serverLog("Couldn't send a boat status message", 1); serverLog("Couldn't send a boat status message", 3);
return;
} }
catch (NullPointerException e){ catch (NullPointerException e){
//raceFinished = true;
serverLog("Boat " + b.getSourceID() + " finished the race", 1); serverLog("Boat " + b.getSourceID() + " finished the race", 1);
boatsFinished.put(b.getSourceID(), true); boatsFinished.put(b.getSourceID(), true);
} }
@@ -16,14 +16,12 @@ import java.util.List;
class StreamingServerSocket { class StreamingServerSocket {
private ServerSocketChannel socket; private ServerSocketChannel socket;
private SocketChannel client; private SocketChannel client;
private List<Socket> clients;
private short seqNum; private short seqNum;
private boolean isServerStarted; private boolean isServerStarted;
StreamingServerSocket(int port) throws IOException{ StreamingServerSocket(int port) throws IOException{
socket = ServerSocketChannel.open(); socket = ServerSocketChannel.open();
socket.socket().bind(new InetSocketAddress("localhost", port)); socket.socket().bind(new InetSocketAddress("localhost", port));
clients = new ArrayList<>();
//socket.setSoTimeout(10000); //socket.setSoTimeout(10000);
seqNum = 0; seqNum = 0;
isServerStarted = false; isServerStarted = false;
@@ -50,11 +48,8 @@ class StreamingServerSocket {
return; return;
} }
//DataOutputStream outputStream = new DataOutputStream(client.getOutputStream());
//System.out.println(client);
message.send(client); message.send(client);
seqNum++; seqNum++;
} }
@@ -133,9 +133,7 @@ public class BoatLocationMessage extends Message {
allocateBuffer(); allocateBuffer();
writeHeaderToBuffer(); writeHeaderToBuffer();
heading = (heading + 180.0) % 360.0; long headingToSend = (long)((heading/360.0) * 65535.0);
long headingToSend = (long)((heading/360.0)*49152.0);
putByte((byte) messageVersionNumber); putByte((byte) messageVersionNumber);
putInt(time, 6); putInt(time, 6);
@@ -3,6 +3,7 @@ package seng302.server.messages;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
@@ -170,7 +171,6 @@ public abstract class Message {
return buffer; return buffer;
} }
/** /**
* Rewind the buffer to the beginning * Rewind the buffer to the beginning
*/ */
@@ -185,11 +185,13 @@ public abstract class Message {
* @return * @return
*/ */
public static byte[] intToByteArray(long val, int len){ public static byte[] intToByteArray(long val, int len){
long vor = val;
int index = 0; int index = 0;
byte[] data = new byte[len]; byte[] data = new byte[len];
for (int i = 0; i < len; i++){ for (int i = 0; i < len; i++){
data[len - index - 1] = (byte) ((val >>> (8 * index))); data[len - index - 1] = (byte) (val & 0xFF);
val >>>= 8;
index++; index++;
} }
@@ -202,9 +204,9 @@ public abstract class Message {
*/ */
public static void reverse(byte[] data) { public static void reverse(byte[] data) {
for (int left = 0, right = data.length - 1; left < right; left++, right--) { for (int left = 0, right = data.length - 1; left < right; left++, right--) {
byte temp = data[left]; byte temp = (byte) (data[left] & 0xff);
data[left] = data[right]; data[left] = (byte) (data[right] & 0xff);
data[right] = temp; data[right] = (byte) (temp & 0xff);
} }
} }
@@ -1,11 +1,7 @@
package seng302.server.messages; package seng302.server.messages;
import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List; import java.util.List;
import java.util.zip.CRC32; import java.util.zip.CRC32;
@@ -7,6 +7,7 @@ import seng302.server.simulator.parsers.RaceParser;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import java.util.concurrent.ThreadLocalRandom;
public class Simulator extends Observable implements Runnable { public class Simulator extends Observable implements Runnable {
@@ -34,7 +35,7 @@ public class Simulator extends Observable implements Runnable {
boat.setLng(startLng); boat.setLng(startLng);
boat.setLastPassedCorner(course.get(0)); boat.setLastPassedCorner(course.get(0));
boat.setHeadingCorner(course.get(1)); boat.setHeadingCorner(course.get(1));
boat.setSpeed(50000); boat.setSpeed(ThreadLocalRandom.current().nextInt(40000, 60000 + 1));
} }
} }