mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -16,4 +16,12 @@
|
|||||||
# https://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html
|
# https://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html
|
||||||
# http://stacktoheap.com/blog/2013/01/06/using-mailmap-to-fix-authors-list-in-git/
|
# http://stacktoheap.com/blog/2013/01/06/using-mailmap-to-fix-authors-list-in-git/
|
||||||
|
|
||||||
Michael Rausch <mra106@uclive.ac.nz> <me@michaelrausch.nz> <michael@michaelrausch.net>
|
Michael Rausch <mra106@uclive.ac.nz> <me@michaelrausch.nz>
|
||||||
|
Michael Rausch <mra106@uclive.ac.nz> <michael@michaelrausch.net>
|
||||||
|
Kusal Ekanayake <kre39@uclive.ac.nz> kre39 <kre39@uclive.ac.nz>
|
||||||
|
Haoming Yin <hyi25@uclive.ac.nz> <haoming.y@icloud.com>
|
||||||
|
Peter Galloway <ptg19@uclive.ac.nz> Peter <ptg19@uclive.ac.nz>
|
||||||
|
Zhi You Tan <zyt10@uclive.ac.nz> zyt10 <zyt10@uclive.ac.nz>
|
||||||
|
Zhi You Tan <zyt10@uclive.ac.nz> Ryan Tan <ryan_zhiyou@hotmail.com>
|
||||||
|
Alistair McIntyre <ajm412@uclive.ac.nz> alistairjmcintyre <alistairjmcintyre@gmail.com>
|
||||||
|
Calum <cir27@uclive.ac.nz> cir27 <cir27@uclive.ac.nz>
|
||||||
@@ -16,34 +16,63 @@ 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.setMaximized(true);
|
||||||
|
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
|
primaryStage.setOnCloseRequest(e -> {
|
||||||
|
StreamParser.appClose();
|
||||||
|
StreamReceiver.noMoreBytes();
|
||||||
|
System.out.println("[CLIENT] Exiting program");
|
||||||
|
System.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
StreamReceiver sr;
|
StreamReceiver sr = null;
|
||||||
|
|
||||||
new ServerThread("Racevision Test Server");
|
new ServerThread("Racevision Test Server");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length > 1){
|
if (args.length == 1 && args[0].equals("-standalone")){
|
||||||
sr = new StreamReceiver("localhost", 8085, "TestThread1");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.length == 3 && args[0].equals("-server")){
|
||||||
|
|
||||||
|
sr = new StreamReceiver(args[1], Integer.valueOf(args[2]), "RaceStream");
|
||||||
|
|
||||||
|
} else if(args.length == 2 && args[0].equals("-server")){
|
||||||
|
switch (args[1]) {
|
||||||
|
case "internal":
|
||||||
|
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
|
break;
|
||||||
|
case "staffserver":
|
||||||
|
sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941, "RaceStream");
|
||||||
|
break;
|
||||||
|
case "official":
|
||||||
|
sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Change the StreamReceiver in this else block to change the default data source.
|
||||||
else{
|
else{
|
||||||
sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1");
|
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
// sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread1");
|
|
||||||
// sr = new StreamReceiver("localhost", 8085, "TestThread1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.start();
|
sr.start();
|
||||||
StreamParser streamParser = new StreamParser("TestThread2");
|
StreamParser streamParser = new StreamParser("StreamParser");
|
||||||
streamParser.start();
|
streamParser.start();
|
||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,19 @@ import javafx.beans.property.SimpleDoubleProperty;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
|
import javafx.scene.Node;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
import javafx.scene.canvas.GraphicsContext;
|
import javafx.scene.canvas.GraphicsContext;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Polygon;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
import seng302.models.Boat;
|
import javafx.stage.Stage;
|
||||||
import seng302.models.BoatGroup;
|
import seng302.models.*;
|
||||||
import seng302.models.Colors;
|
|
||||||
import seng302.models.RaceObject;
|
|
||||||
import seng302.models.mark.*;
|
import seng302.models.mark.*;
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.parsers.StreamParser;
|
||||||
|
import seng302.models.parsers.StreamReceiver;
|
||||||
import seng302.models.parsers.packets.BoatPositionPacket;
|
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||||
import seng302.models.parsers.XMLParser;
|
import seng302.models.parsers.XMLParser;
|
||||||
import seng302.models.parsers.XMLParser.RaceXMLObject.CompoundMark;
|
import seng302.models.parsers.XMLParser.RaceXMLObject.CompoundMark;
|
||||||
@@ -41,9 +43,9 @@ public class CanvasController {
|
|||||||
private GraphicsContext gc;
|
private GraphicsContext gc;
|
||||||
|
|
||||||
private final int MARK_SIZE = 10;
|
private final int MARK_SIZE = 10;
|
||||||
private final int BUFFER_SIZE = 150;
|
private final int BUFFER_SIZE = 50;
|
||||||
private final int CANVAS_WIDTH = 1000;
|
private final int CANVAS_WIDTH = 720;
|
||||||
private final int CANVAS_HEIGHT = 1000;
|
private final int CANVAS_HEIGHT = 720;
|
||||||
private final int LHS_BUFFER = BUFFER_SIZE;
|
private final int LHS_BUFFER = BUFFER_SIZE;
|
||||||
private final int RHS_BUFFER = BUFFER_SIZE + MARK_SIZE / 2;
|
private final int RHS_BUFFER = BUFFER_SIZE + MARK_SIZE / 2;
|
||||||
private final int TOP_BUFFER = BUFFER_SIZE;
|
private final int TOP_BUFFER = BUFFER_SIZE;
|
||||||
@@ -128,13 +130,11 @@ public class CanvasController {
|
|||||||
// TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay.
|
// TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay.
|
||||||
elapsedNanos = 1000 / 60;
|
elapsedNanos = 1000 / 60;
|
||||||
updateRaceObjects();
|
updateRaceObjects();
|
||||||
|
if (StreamParser.isRaceFinished()) {
|
||||||
|
this.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (Mark m : raceViewController.getRace().getCourse()) {
|
|
||||||
System.out.println(m.getName());
|
|
||||||
}
|
|
||||||
//timer.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,9 +148,10 @@ public class CanvasController {
|
|||||||
private void addRaceBorder() {
|
private void addRaceBorder() {
|
||||||
XMLParser.RaceXMLObject raceXMLObject = StreamParser.getXmlObject().getRaceXML();
|
XMLParser.RaceXMLObject raceXMLObject = StreamParser.getXmlObject().getRaceXML();
|
||||||
ArrayList<Limit> courseLimits = raceXMLObject.getCourseLimit();
|
ArrayList<Limit> courseLimits = raceXMLObject.getCourseLimit();
|
||||||
gc.setStroke(Color.DARKRED);
|
gc.setStroke(Color.DARKBLUE);
|
||||||
gc.setLineWidth(3);
|
gc.setLineWidth(3);
|
||||||
|
double[] xBoundaryPoints = new double[courseLimits.size()];
|
||||||
|
double[] yBoundaryPoints = new double[courseLimits.size()];
|
||||||
for (int i = 0; i < courseLimits.size() - 1; i++) {
|
for (int i = 0; i < courseLimits.size() - 1; i++) {
|
||||||
Limit thisPoint1 = courseLimits.get(i);
|
Limit thisPoint1 = courseLimits.get(i);
|
||||||
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
||||||
@@ -160,18 +161,21 @@ public class CanvasController {
|
|||||||
Point2D borderPoint2 = findScaledXY(thisMark2);
|
Point2D borderPoint2 = findScaledXY(thisMark2);
|
||||||
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
||||||
borderPoint2.getX(), borderPoint2.getY());
|
borderPoint2.getX(), borderPoint2.getY());
|
||||||
|
xBoundaryPoints[i] = borderPoint1.getX();
|
||||||
|
yBoundaryPoints[i] = borderPoint1.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
Limit thisPoint1 = courseLimits.get(courseLimits.size()-1);
|
Limit thisPoint1 = courseLimits.get(courseLimits.size()-1);
|
||||||
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
||||||
Limit thisPoint2 = courseLimits.get(0);
|
Limit thisPoint2 = courseLimits.get(0);
|
||||||
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
||||||
Point2D borderPoint1 = findScaledXY(thisMark1);
|
Point2D borderPoint1 = findScaledXY(thisMark1);
|
||||||
Point2D borderPoint2 = findScaledXY(thisMark2);
|
Point2D borderPoint2 = findScaledXY(thisMark2);
|
||||||
|
|
||||||
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
||||||
borderPoint2.getX(), borderPoint2.getY());
|
borderPoint2.getX(), borderPoint2.getY());
|
||||||
|
xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX();
|
||||||
|
yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY();
|
||||||
|
gc.setFill(Color.LIGHTBLUE);
|
||||||
|
gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -300,6 +304,8 @@ public class CanvasController {
|
|||||||
private void drawFps(int fps){
|
private void drawFps(int fps){
|
||||||
if (raceViewController.isDisplayFps()){
|
if (raceViewController.isDisplayFps()){
|
||||||
gc.clearRect(5,5,50,20);
|
gc.clearRect(5,5,50,20);
|
||||||
|
gc.setFill(Color.SKYBLUE);
|
||||||
|
gc.fillRect(4,4,51,21);
|
||||||
gc.setFill(Color.BLACK);
|
gc.setFill(Color.BLACK);
|
||||||
gc.setFont(new Font(14));
|
gc.setFont(new Font(14));
|
||||||
gc.setLineWidth(3);
|
gc.setLineWidth(3);
|
||||||
@@ -316,15 +322,18 @@ public class CanvasController {
|
|||||||
*/
|
*/
|
||||||
private void drawBoats() {
|
private void drawBoats() {
|
||||||
// Map<Boat, TimelineInfo> timelineInfos = raceViewController.getTimelineInfos();
|
// Map<Boat, TimelineInfo> timelineInfos = raceViewController.getTimelineInfos();
|
||||||
List<Boat> boats = raceViewController.getStartingBoats();
|
// List<Boat> boats = raceViewController.getStartingBoats();
|
||||||
|
Map<Integer, Yacht> boats = StreamParser.getBoats();
|
||||||
Double startingX = raceObjects.get(0).getLayoutX();
|
Double startingX = raceObjects.get(0).getLayoutX();
|
||||||
Double startingY = raceObjects.get(0).getLayoutY();
|
Double startingY = raceObjects.get(0).getLayoutY();
|
||||||
Group boatAnnotations = new Group();
|
Group boatAnnotations = new Group();
|
||||||
|
|
||||||
for (Boat boat : boats) {
|
for (Yacht boat : boats.values()) {
|
||||||
BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor());
|
// for (Boat boat : boats) {
|
||||||
|
boat.setColour(Colors.getColor());
|
||||||
|
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
||||||
boatGroup.moveTo(startingX, startingY, 0d);
|
boatGroup.moveTo(startingX, startingY, 0d);
|
||||||
boatGroup.forceRotation();
|
//boatGroup.setStage(raceViewController.getStage());
|
||||||
raceObjects.add(boatGroup);
|
raceObjects.add(boatGroup);
|
||||||
boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations());
|
boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package seng302.controllers;
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.concurrent.Task;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
@@ -15,22 +14,20 @@ import javafx.scene.control.cell.PropertyValueFactory;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import seng302.models.Boat;
|
import seng302.models.Yacht;
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.parsers.StreamParser;
|
||||||
import seng302.models.parsers.XMLParser;
|
import seng302.models.parsers.XMLParser;
|
||||||
|
|
||||||
|
|
||||||
import javax.xml.crypto.dsig.XMLObject;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.*;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by michaelrausch on 21/03/17.
|
|
||||||
*/
|
|
||||||
public class Controller implements Initializable {
|
public class Controller implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane contentPane;
|
private AnchorPane contentPane;
|
||||||
@@ -41,13 +38,19 @@ public class Controller implements Initializable {
|
|||||||
@FXML
|
@FXML
|
||||||
private Button switchToRaceViewButton;
|
private Button switchToRaceViewButton;
|
||||||
@FXML
|
@FXML
|
||||||
private TableView teamList;
|
private TableView<Yacht> teamList;
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn boatNameCol;
|
private TableColumn<Yacht, String> boatNameCol;
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn shortNameCol;
|
private TableColumn<Yacht, String> shortNameCol;
|
||||||
@FXML
|
@FXML
|
||||||
private TableColumn countryCol;
|
private TableColumn<Yacht, String> countryCol;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Yacht, String> posCol;
|
||||||
|
@FXML
|
||||||
|
private Label realTime;
|
||||||
|
|
||||||
|
private XMLParser xmlParser;
|
||||||
|
|
||||||
private void setContentPane(String jfxUrl){
|
private void setContentPane(String jfxUrl){
|
||||||
try{
|
try{
|
||||||
@@ -65,7 +68,9 @@ public class Controller implements Initializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
//DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
||||||
|
//format.setTimeZone(TimeZone.getTimeZone("GMT-8"));
|
||||||
|
//realTime.setText(format.format(new Date()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,8 +78,9 @@ public class Controller implements Initializable {
|
|||||||
*/
|
*/
|
||||||
public void startStream() {
|
public void startStream() {
|
||||||
if (StreamParser.isStreamStatus()) {
|
if (StreamParser.isStreamStatus()) {
|
||||||
XMLParser xmlParser = StreamParser.getXmlObject();
|
xmlParser = StreamParser.getXmlObject();
|
||||||
streamButton.setVisible(false);
|
streamButton.setVisible(false);
|
||||||
|
realTime.setVisible(true);
|
||||||
timeTillLive.setVisible(true);
|
timeTillLive.setVisible(true);
|
||||||
timeTillLive.setTextFill(Color.GREEN);
|
timeTillLive.setTextFill(Color.GREEN);
|
||||||
timeTillLive.setText("Connecting...");
|
timeTillLive.setText("Connecting...");
|
||||||
@@ -83,11 +89,17 @@ public class Controller implements Initializable {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
|
if (StreamParser.isRaceStarted()) {
|
||||||
|
switchToRaceView();
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
if (StreamParser.isRaceFinished()) {
|
if (StreamParser.isRaceFinished()) {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
timeTillLive.setTextFill(Color.RED);
|
timeTillLive.setTextFill(Color.RED);
|
||||||
timeTillLive.setText("Race finished! Waiting for new race...");
|
timeTillLive.setText("Race finished! Waiting for new race...");
|
||||||
switchToRaceViewButton.setDisable(true);
|
switchToRaceViewButton.setDisable(true);
|
||||||
} else if (StreamParser.getTimeSinceStart() > 0) {
|
} else if (StreamParser.getTimeSinceStart() > 0) {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
updateTeamList();
|
updateTeamList();
|
||||||
timeTillLive.setTextFill(Color.RED);
|
timeTillLive.setTextFill(Color.RED);
|
||||||
switchToRaceViewButton.setDisable(false);
|
switchToRaceViewButton.setDisable(false);
|
||||||
@@ -96,9 +108,10 @@ public class Controller implements Initializable {
|
|||||||
if (timerSecond.length() == 1) {
|
if (timerSecond.length() == 1) {
|
||||||
timerSecond = "0" + timerSecond;
|
timerSecond = "0" + timerSecond;
|
||||||
}
|
}
|
||||||
String timerString = "-" + timerMinute + ":" + timerSecond + " minutes";
|
String timerString = "-" + timerMinute + ":" + timerSecond;
|
||||||
timeTillLive.setText(timerString);
|
timeTillLive.setText(timerString);
|
||||||
} else {
|
} else {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
updateTeamList();
|
updateTeamList();
|
||||||
timeTillLive.setTextFill(Color.BLACK);
|
timeTillLive.setTextFill(Color.BLACK);
|
||||||
switchToRaceViewButton.setDisable(false);
|
switchToRaceViewButton.setDisable(false);
|
||||||
@@ -107,7 +120,7 @@ public class Controller implements Initializable {
|
|||||||
if (timerSecond.length() == 1) {
|
if (timerSecond.length() == 1) {
|
||||||
timerSecond = "0" + timerSecond;
|
timerSecond = "0" + timerSecond;
|
||||||
}
|
}
|
||||||
String timerString = timerMinute + ":" + timerSecond + " minutes";
|
String timerString = timerMinute + ":" + timerSecond;
|
||||||
timeTillLive.setText(timerString);
|
timeTillLive.setText(timerString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -124,19 +137,32 @@ public class Controller implements Initializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTeamList() {
|
private void updateTeamList() {
|
||||||
ObservableList<Boat> data = FXCollections.observableArrayList();
|
ObservableList<Yacht> data = FXCollections.observableArrayList();
|
||||||
teamList.setItems(data);
|
teamList.setItems(data);
|
||||||
boatNameCol.setCellValueFactory(
|
boatNameCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<Boat,String>("boatName")
|
new PropertyValueFactory<>("boatName")
|
||||||
);
|
);
|
||||||
shortNameCol.setCellValueFactory(
|
shortNameCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<Boat,String>("shortName")
|
new PropertyValueFactory<>("shortName")
|
||||||
);
|
);
|
||||||
countryCol.setCellValueFactory(
|
countryCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<Boat,String>("country")
|
new PropertyValueFactory<>("country")
|
||||||
);
|
);
|
||||||
for (Boat boat : StreamParser.getBoats()) {
|
posCol.setCellValueFactory(
|
||||||
data.add(boat);
|
new PropertyValueFactory<>("position")
|
||||||
}
|
);
|
||||||
|
// if (StreamParser.isRaceStarted()) {
|
||||||
|
data.addAll(StreamParser.getBoatsPos().values());
|
||||||
|
// } else {
|
||||||
|
// for (Yacht boat : StreamParser.getBoats().values()) {
|
||||||
|
// boat.setPosition("-");
|
||||||
|
// data.add(boat);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
teamList.refresh();
|
||||||
|
|
||||||
|
// posCol.setSortType(TableColumn.SortType.ASCENDING);
|
||||||
|
// teamList.getSortOrder().add(posCol);
|
||||||
|
// posCol.setSortable(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import seng302.models.Boat;
|
|
||||||
import seng302.models.Race;
|
import seng302.models.Race;
|
||||||
|
import seng302.models.Yacht;
|
||||||
import seng302.models.parsers.ConfigParser;
|
import seng302.models.parsers.ConfigParser;
|
||||||
import seng302.models.parsers.CourseParser;
|
import seng302.models.parsers.CourseParser;
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.parsers.StreamParser;
|
||||||
import seng302.models.parsers.TeamsParser;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,23 +41,24 @@ public class RaceController {
|
|||||||
Race race = new Race();
|
Race race = new Race();
|
||||||
// StreamParser.xmlObject
|
// StreamParser.xmlObject
|
||||||
// Read team names from file
|
// Read team names from file
|
||||||
TeamsParser tp = new TeamsParser(teamsConfigFile);
|
// TeamsParser tp = new TeamsParser(teamsConfigFile);
|
||||||
|
|
||||||
// Read course from file
|
// Read course from file
|
||||||
ConfigParser config = new ConfigParser(configFile);
|
// ConfigParser config = new ConfigParser(configFile);
|
||||||
|
|
||||||
ArrayList<String> boatNames = new ArrayList<>();
|
ArrayList<String> boatNames = new ArrayList<>();
|
||||||
ArrayList<Boat> teams = tp.getBoats();
|
// ArrayList<Boat> teams = tp.getBoats();
|
||||||
|
Map<Long, Yacht> teams = StreamParser.getBoatsPos();
|
||||||
|
|
||||||
//get race size
|
//get race size
|
||||||
int numberOfBoats = teams.size();
|
int numberOfBoats = teams.size();
|
||||||
|
|
||||||
//get time scale
|
//get time scale
|
||||||
double timeScale = config.getTimeScale();
|
// double timeScale = config.getTimeScale();
|
||||||
race.setTimeScale(timeScale);
|
// race.setTimeScale(timeScale);
|
||||||
|
|
||||||
for (Boat boat : teams) {
|
for (Yacht boat : teams.values()) {
|
||||||
boatNames.add(boat.getTeamName());
|
boatNames.add(boat.getBoatName());
|
||||||
race.addBoat(boat);
|
race.addBoat(boat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class RaceResultController implements Initializable{
|
|||||||
int boatPosition = this.race.getFinishedBoats().length;
|
int boatPosition = this.race.getFinishedBoats().length;
|
||||||
|
|
||||||
for (int i = this.race.getFinishedBoats().length - 1; i >= 0; i--){
|
for (int i = this.race.getFinishedBoats().length - 1; i >= 0; i--){
|
||||||
resultsVBox.getChildren().add(0, new Text(boatPosition + ": " + this.race.getFinishedBoats()[i].getTeamName()));
|
resultsVBox.getChildren().add(0, new Text(boatPosition + ": " + this.race.getFinishedBoats()[i].getBoatName()));
|
||||||
boatPosition--;
|
boatPosition--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
|
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
|
||||||
import javafx.animation.Animation;
|
import javafx.animation.Animation;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
@@ -15,6 +16,7 @@ import javafx.scene.layout.Pane;
|
|||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
import seng302.models.*;
|
import seng302.models.*;
|
||||||
@@ -43,19 +45,20 @@ public class RaceViewController extends Thread{
|
|||||||
@FXML
|
@FXML
|
||||||
private CanvasController includedCanvasController;
|
private CanvasController includedCanvasController;
|
||||||
|
|
||||||
private ArrayList<Boat> startingBoats = new ArrayList<>();
|
private ArrayList<Yacht> startingBoats = new ArrayList<>();
|
||||||
private boolean displayFps;
|
private boolean displayFps;
|
||||||
private Timeline timerTimeline;
|
private Timeline timerTimeline;
|
||||||
private Map<Boat, TimelineInfo> timelineInfos = new HashMap<>();
|
private Map<Yacht, TimelineInfo> timelineInfos = new HashMap<>();
|
||||||
private ArrayList<Boat> boatOrder = new ArrayList<>();
|
private ArrayList<Yacht> boatOrder = new ArrayList<>();
|
||||||
private Race race;
|
private Race race;
|
||||||
|
private Stage stage;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
RaceController raceController = new RaceController();
|
RaceController raceController = new RaceController();
|
||||||
raceController.initializeRace();
|
raceController.initializeRace();
|
||||||
race = raceController.getRace();
|
race = raceController.getRace();
|
||||||
for (Boat boat : race.getBoats()) {
|
for (Yacht boat : race.getBoats()) {
|
||||||
startingBoats.add(boat);
|
startingBoats.add(boat);
|
||||||
}
|
}
|
||||||
// try{
|
// try{
|
||||||
@@ -69,11 +72,12 @@ public class RaceViewController extends Thread{
|
|||||||
includedCanvasController.initializeCanvas();
|
includedCanvasController.initializeCanvas();
|
||||||
initializeTimer();
|
initializeTimer();
|
||||||
initializeSettings();
|
initializeSettings();
|
||||||
|
initialiseWindDirection();
|
||||||
|
initialisePositionVBox();
|
||||||
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
||||||
double windDirection = new ConfigParser("/config/config.xml").getWindDirection();
|
// double windDirection = new ConfigParser("/config/config.xml").getWindDirection();
|
||||||
windDirectionText.setText(String.format("%.1f°", windDirection));
|
// windDirectionText.setText(String.format("%.1f°", windDirection));
|
||||||
windArrowText.setRotate(windDirection);
|
// windArrowText.setRotate(windDirection);
|
||||||
includedCanvasController.timer.start();
|
includedCanvasController.timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,12 +149,39 @@ public class RaceViewController extends Thread{
|
|||||||
timerTimeline.playFromStart();
|
timerTimeline.playFromStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initialiseWindDirection() {
|
||||||
|
Timeline windDirTimeline = new Timeline();
|
||||||
|
windDirTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
|
windDirTimeline.getKeyFrames().add(
|
||||||
|
new KeyFrame(Duration.seconds(1),
|
||||||
|
event -> {
|
||||||
|
windDirectionText.setText(String.format("%.1f°", StreamParser.getWindDirection()));
|
||||||
|
windArrowText.setRotate(StreamParser.getWindDirection());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
windDirTimeline.playFromStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initialisePositionVBox() {
|
||||||
|
|
||||||
|
Timeline posVBoxTimeline = new Timeline();
|
||||||
|
posVBoxTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
|
posVBoxTimeline.getKeyFrames().add(
|
||||||
|
new KeyFrame(Duration.seconds(1),
|
||||||
|
event -> {
|
||||||
|
showOrder();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
posVBoxTimeline.playFromStart();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates time line for each boat, and stores time time into timelineInfos hash map
|
* Generates time line for each boat, and stores time time into timelineInfos hash map
|
||||||
*/
|
*/
|
||||||
private void initializeTimelines() {
|
private void initializeTimelines() {
|
||||||
HashMap<Boat, List> boat_events = race.getEvents();
|
HashMap<Yacht, List> boat_events = race.getEvents();
|
||||||
for (Boat boat : boat_events.keySet()) {
|
for (Yacht boat : boat_events.keySet()) {
|
||||||
startingBoats.add(boat);
|
startingBoats.add(boat);
|
||||||
// // x, y are the real time coordinates
|
// // x, y are the real time coordinates
|
||||||
// DoubleProperty x = new SimpleDoubleProperty();
|
// DoubleProperty x = new SimpleDoubleProperty();
|
||||||
@@ -256,13 +287,13 @@ public class RaceViewController extends Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void handleEvent(Event event) {
|
public void handleEvent(Event event) {
|
||||||
Boat boat = event.getBoat();
|
Yacht boat = event.getBoat();
|
||||||
boatOrder.remove(boat);
|
boatOrder.remove(boat);
|
||||||
boat.setMarkLastPast(event.getMarkPosInRace());
|
boat.setMarkLastPast(event.getMarkPosInRace());
|
||||||
boatOrder.add(boat);
|
boatOrder.add(boat);
|
||||||
boatOrder.sort(new Comparator<Boat>() {
|
boatOrder.sort(new Comparator<Yacht>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(Boat b1, Boat b2) {
|
public int compare(Yacht b1, Yacht b2) {
|
||||||
return b2.getMarkLastPast() - b1.getMarkLastPast();
|
return b2.getMarkLastPast() - b1.getMarkLastPast();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -273,8 +304,19 @@ public class RaceViewController extends Thread{
|
|||||||
positionVbox.getChildren().clear();
|
positionVbox.getChildren().clear();
|
||||||
positionVbox.getChildren().removeAll();
|
positionVbox.getChildren().removeAll();
|
||||||
|
|
||||||
for (Boat boat : boatOrder) {
|
// for (Boat boat : boatOrder) {
|
||||||
positionVbox.getChildren().add(new Text(boat.getShortName() + " " + boat.getSpeedInKnots() + " Knots"));
|
// positionVbox.getChildren().add(new Text(boat.getShortName() + " " + boat.getSpeedInKnots() + " Knots"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (Yacht boat : StreamParser.getBoatsPos().values()) {
|
||||||
|
if (boat.getBoatStatus() == 3) { // 3 is finish status
|
||||||
|
positionVbox.getChildren().add(new Text(boat.getPosition() + ". " +
|
||||||
|
boat.getShortName() + " (Finished)"));
|
||||||
|
} else {
|
||||||
|
positionVbox.getChildren().add(new Text(boat.getPosition() + ". " +
|
||||||
|
boat.getShortName() + " "));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,21 +334,21 @@ public class RaceViewController extends Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String currentTimer() {
|
private String currentTimer() {
|
||||||
String timerString = "0:00 minutes";
|
String timerString = "0:00";
|
||||||
if (StreamParser.getTimeSinceStart() > 0) {
|
if (StreamParser.getTimeSinceStart() > 0) {
|
||||||
String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60);
|
String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60);
|
||||||
String timerSecond = Long.toString(StreamParser.getTimeSinceStart() % 60);
|
String timerSecond = Long.toString(StreamParser.getTimeSinceStart() % 60);
|
||||||
if (timerSecond.length() == 1) {
|
if (timerSecond.length() == 1) {
|
||||||
timerSecond = "0" + timerSecond;
|
timerSecond = "0" + timerSecond;
|
||||||
}
|
}
|
||||||
timerString = "-" + timerMinute + ":" + timerSecond + " minutes";
|
timerString = "-" + timerMinute + ":" + timerSecond;
|
||||||
} else {
|
} else {
|
||||||
String timerMinute = Long.toString(-1 * StreamParser.getTimeSinceStart() / 60);
|
String timerMinute = Long.toString(-1 * StreamParser.getTimeSinceStart() / 60);
|
||||||
String timerSecond = Long.toString(-1 * StreamParser.getTimeSinceStart() % 60);
|
String timerSecond = Long.toString(-1 * StreamParser.getTimeSinceStart() % 60);
|
||||||
if (timerSecond.length() == 1) {
|
if (timerSecond.length() == 1) {
|
||||||
timerSecond = "0" + timerSecond;
|
timerSecond = "0" + timerSecond;
|
||||||
}
|
}
|
||||||
timerString = timerMinute + ":" + timerSecond + " minutes";
|
timerString = timerMinute + ":" + timerSecond;
|
||||||
}
|
}
|
||||||
return timerString;
|
return timerString;
|
||||||
}
|
}
|
||||||
@@ -326,11 +368,11 @@ public class RaceViewController extends Thread{
|
|||||||
return race;
|
return race;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Boat, TimelineInfo> getTimelineInfos() {
|
public Map<Yacht, TimelineInfo> getTimelineInfos() {
|
||||||
return timelineInfos;
|
return timelineInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Boat> getStartingBoats(){
|
public ArrayList<Yacht> getStartingBoats(){
|
||||||
return startingBoats;
|
return startingBoats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,4 +426,11 @@ public class RaceViewController extends Thread{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setStage (Stage stage) {
|
||||||
|
this.stage = stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stage getStage () {
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
package seng302.models;
|
|
||||||
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.scene.shape.Polygon;
|
|
||||||
import javafx.scene.text.Text;
|
|
||||||
import javafx.scene.transform.Rotate;
|
|
||||||
import javafx.scene.transform.Translate;
|
|
||||||
import javafx.util.Pair;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a boat in the race.
|
|
||||||
*/
|
|
||||||
public class Boat {
|
|
||||||
|
|
||||||
private String teamName;
|
|
||||||
private double velocity;
|
|
||||||
private double lat;
|
|
||||||
private double lon;
|
|
||||||
private double heading;
|
|
||||||
private int markLastPast;
|
|
||||||
private String shortName;
|
|
||||||
private int id;
|
|
||||||
// new attributes to boat
|
|
||||||
private int sourceID;
|
|
||||||
private String boatName;
|
|
||||||
private String country;
|
|
||||||
|
|
||||||
public Boat(String teamName) {
|
|
||||||
this.teamName = teamName;
|
|
||||||
this.velocity = 10; // Default velocity
|
|
||||||
this.lat = 0.0;
|
|
||||||
this.lon = 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, int id) {
|
|
||||||
this.teamName = teamName;
|
|
||||||
this.velocity = boatVelocity;
|
|
||||||
this.shortName = shortName;
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* New instance created by BoatsParser.
|
|
||||||
*
|
|
||||||
* @param sourceID source ID of the boat
|
|
||||||
* @param boatName full name of the boat
|
|
||||||
* @param shortName short name of the boat
|
|
||||||
* @param country country of the boat
|
|
||||||
*/
|
|
||||||
public Boat(int sourceID, String boatName, String shortName, String country) {
|
|
||||||
this.sourceID = sourceID;
|
|
||||||
this.boatName = boatName;
|
|
||||||
this.shortName = shortName;
|
|
||||||
this.country = country;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 Pair<Double, Double> getLocation ()
|
|
||||||
{
|
|
||||||
return new Pair<>(this.lat, this.lon);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLatitude(){
|
|
||||||
return this.lat;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLongitude(){
|
|
||||||
return this.lon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLatitude (double latitude) {
|
|
||||||
this.lat = latitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setlongitude (double longitude) {
|
|
||||||
this.lon =longitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getSpeedInKnots(){
|
|
||||||
return Math.round((this.velocity * 1.94384) * 100d) / 100d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMarkLastPast(int markLastPast) {
|
|
||||||
this.markLastPast = markLastPast;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMarkLastPast() {
|
|
||||||
return markLastPast;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHeading(){
|
|
||||||
return this.heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeading(double heading) {
|
|
||||||
this.heading = heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShortName(){
|
|
||||||
return this.shortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSourceID() {
|
|
||||||
return sourceID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBoatName() {
|
|
||||||
return boatName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCountry() {
|
|
||||||
return country;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,33 +7,46 @@ import javafx.scene.shape.Line;
|
|||||||
import javafx.scene.shape.Polygon;
|
import javafx.scene.shape.Polygon;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.scene.transform.Rotate;
|
import javafx.scene.transform.Rotate;
|
||||||
import seng302.models.parsers.StreamParser;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 dimensional boat.
|
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 dimensional boat.
|
||||||
* It contains a single polygon for the boat, a group of lines to show it's path, a wake object and two text labels to
|
* It contains a single polygon for the boat, a group of lines to show it's path, a wake object and two text labels to
|
||||||
* annotate the boat teams name and the boats velocity.
|
* annotate the boat teams name and the boats velocity. The boat will update it's position onscreen everytime
|
||||||
|
* UpdatePosition is called unless the window is minimized in which case it attempts to store animations and apply them
|
||||||
|
* when the window is maximised.
|
||||||
*/
|
*/
|
||||||
public class BoatGroup extends RaceObject{
|
public class BoatGroup extends RaceObject{
|
||||||
|
|
||||||
|
//Constants for drawing
|
||||||
private static final double TEAMNAME_X_OFFSET = 10d;
|
private static final double TEAMNAME_X_OFFSET = 10d;
|
||||||
private static final double TEAMNAME_Y_OFFSET = -15d;
|
private static final double TEAMNAME_Y_OFFSET = -15d;
|
||||||
private static final double VELOCITY_X_OFFSET = 10d;
|
private static final double VELOCITY_X_OFFSET = 10d;
|
||||||
private static final double VELOCITY_Y_OFFSET = -5d;
|
private static final double VELOCITY_Y_OFFSET = -5d;
|
||||||
private static final double BOAT_HEIGHT = 15d;
|
private static final double BOAT_HEIGHT = 15d;
|
||||||
private static final double BOAT_WIDTH = 10d;
|
private static final double BOAT_WIDTH = 10d;
|
||||||
private static double expectedUpdateInterval = 200;
|
//Variables for boat logic.
|
||||||
private boolean destinationSet;
|
|
||||||
private Point2D lastPoint;
|
private Point2D lastPoint;
|
||||||
private int wakeGenerationDelay = 10;
|
private int wakeGenerationDelay = 10;
|
||||||
private double distanceTravelled;
|
private double distanceTravelled;
|
||||||
|
//Graphical objects
|
||||||
private Boat boat;
|
private Yacht boat;
|
||||||
private Group lineGroup = new Group();
|
private Group lineGroup = new Group();
|
||||||
private Polygon boatPoly;
|
private Polygon boatPoly;
|
||||||
private Text teamNameObject;
|
private Text teamNameObject;
|
||||||
private Text velocityObject;
|
private Text velocityObject;
|
||||||
private Wake wake;
|
private Wake wake;
|
||||||
|
//Handles boat moving when connecting to a stream
|
||||||
|
private boolean setToInitialLocation = false;
|
||||||
|
private boolean destinationSet;
|
||||||
|
//Variables for handling minimization
|
||||||
|
private Stage stage;
|
||||||
|
private boolean isMaximized= true;
|
||||||
|
private List<Line> lineStorage = new ArrayList<>();
|
||||||
|
private int setCallCount = 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BoatGroup with the default triangular boat polygon.
|
* Creates a BoatGroup with the default triangular boat polygon.
|
||||||
@@ -41,7 +54,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
* BoatGroup to update.
|
* BoatGroup to update.
|
||||||
* @param color The colour of the boat polygon and the trailing line.
|
* @param color The colour of the boat polygon and the trailing line.
|
||||||
*/
|
*/
|
||||||
public BoatGroup (Boat boat, Color color){
|
public BoatGroup (Yacht boat, Color color){
|
||||||
this.boat = boat;
|
this.boat = boat;
|
||||||
initChildren(color);
|
initChildren(color);
|
||||||
}
|
}
|
||||||
@@ -53,7 +66,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
* @param color The colour of the boat polygon and the trailing line.
|
* @param color The colour of the boat polygon and the trailing line.
|
||||||
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat polygon.
|
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat polygon.
|
||||||
*/
|
*/
|
||||||
public BoatGroup (Boat boat, Color color, double... points)
|
public BoatGroup (Yacht boat, Color color, double... points)
|
||||||
{
|
{
|
||||||
this.boat = boat;
|
this.boat = boat;
|
||||||
initChildren(color, points);
|
initChildren(color, points);
|
||||||
@@ -146,6 +159,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
*/
|
*/
|
||||||
public void updatePosition (long timeInterval) {
|
public void updatePosition (long timeInterval) {
|
||||||
//Calculate the movement of the boat.
|
//Calculate the movement of the boat.
|
||||||
|
if (isMaximized) {
|
||||||
double dx = pixelVelocityX * timeInterval;
|
double dx = pixelVelocityX * timeInterval;
|
||||||
double dy = pixelVelocityY * timeInterval;
|
double dy = pixelVelocityY * timeInterval;
|
||||||
double rotation = rotationalVelocity * timeInterval;
|
double rotation = rotationalVelocity * timeInterval;
|
||||||
@@ -165,64 +179,78 @@ public class BoatGroup extends RaceObject{
|
|||||||
l.setStroke(boatPoly.getFill());
|
l.setStroke(boatPoly.getFill());
|
||||||
lineGroup.getChildren().add(l);
|
lineGroup.getChildren().add(l);
|
||||||
}
|
}
|
||||||
if (destinationSet){ //Only begin drawing after the first destination is set
|
if (destinationSet) { //Only begin drawing after the first destination is set
|
||||||
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wake.updatePosition(timeInterval);
|
wake.updatePosition(timeInterval);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the destination of the boat and the headng it should have once it reaches
|
* Sets the destination of the boat and the headng it should have once it reaches
|
||||||
* @param newXValue
|
* @param newXValue The X co-ordinate the boat needs to move to.
|
||||||
* @param newYValue
|
* @param newYValue The Y co-ordinate the boat needs to move to.
|
||||||
* @param rotation Rotation to move graphics to.
|
* @param rotation Rotation to move graphics to.
|
||||||
* @param raceIds RaceID of the object to move.
|
* @param raceIds RaceID of the object to move.
|
||||||
*/
|
*/
|
||||||
public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, int... raceIds) {
|
public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, int... raceIds) {
|
||||||
if (hasRaceId(raceIds)) {
|
if (hasRaceId(raceIds)) {
|
||||||
|
if (setToInitialLocation) {
|
||||||
destinationSet = true;
|
destinationSet = true;
|
||||||
boat.setVelocity(groundSpeed);
|
boat.setVelocity(groundSpeed);
|
||||||
if (currentRotation < 0)
|
if (currentRotation < 0)
|
||||||
currentRotation = 360 - currentRotation;
|
currentRotation = 360 - currentRotation;
|
||||||
double dx = newXValue - boatPoly.getLayoutX();
|
double dx = newXValue - boatPoly.getLayoutX();
|
||||||
if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) {
|
|
||||||
pixelVelocityX = 0;
|
|
||||||
} else {
|
|
||||||
pixelVelocityX = dx / expectedUpdateInterval;
|
|
||||||
}
|
|
||||||
double dy = newYValue - boatPoly.getLayoutY();
|
double dy = newYValue - boatPoly.getLayoutY();
|
||||||
//Check movement is reasonable. Assumes a 1000 * 1000 canvas
|
//Check movement is reasonable. Assumes a 1000 * 1000 canvas
|
||||||
if (Math.abs(dx) > 50 || Math.abs(dy) > 50) {
|
if (Math.abs(dx) > 50 || Math.abs(dy) > 50) {
|
||||||
// System.out.println("dx = " + dx);
|
|
||||||
// System.out.println("dy = " + dy);
|
|
||||||
dx = 0;
|
dx = 0;
|
||||||
dy = 0;
|
dy = 0;
|
||||||
moveTo(newXValue, newYValue);
|
moveTo(newXValue, newYValue);
|
||||||
}
|
}
|
||||||
//Slight delay on changing X/Y direction that could help jitter. Disabled since there was an issue with
|
|
||||||
//packets that might be causing it.
|
|
||||||
// if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) {
|
|
||||||
// pixelVelocityX = 0;
|
|
||||||
// } else {
|
|
||||||
// pixelVelocityX = dx / expectedUpdateInterval;
|
|
||||||
// }
|
|
||||||
// if ((dy > 0 && pixelVelocityY < 0) || (dy < 0 && pixelVelocityY > 0)) {
|
|
||||||
// pixelVelocityY = 0;
|
|
||||||
// } else {
|
|
||||||
// pixelVelocityY = dy / expectedUpdateInterval;
|
|
||||||
// }
|
|
||||||
pixelVelocityX = dx / expectedUpdateInterval;
|
pixelVelocityX = dx / expectedUpdateInterval;
|
||||||
pixelVelocityY = dy / expectedUpdateInterval;
|
pixelVelocityY = dy / expectedUpdateInterval;
|
||||||
rotationalGoal = rotation;
|
rotationalGoal = rotation;
|
||||||
calculateRotationalVelocity();
|
calculateRotationalVelocity();
|
||||||
|
|
||||||
if (wakeGenerationDelay > 0) {
|
if (wakeGenerationDelay > 0) {
|
||||||
wake.rotate(rotationalGoal);
|
wake.rotate(rotationalGoal);
|
||||||
|
rotateTo(rotationalGoal); //Need to test with this removed.
|
||||||
|
rotationalVelocity = 0;
|
||||||
wakeGenerationDelay--;
|
wakeGenerationDelay--;
|
||||||
} else {
|
} else {
|
||||||
wake.setRotationalVelocity(rotationalVelocity, currentRotation, boat.getVelocity());
|
wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, boat.getVelocity());
|
||||||
}
|
}
|
||||||
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
|
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
|
||||||
|
} else {
|
||||||
|
setToInitialLocation = true;
|
||||||
|
rotationalGoal = rotation;
|
||||||
|
moveTo(newXValue, newYValue, rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If minimized generate lines every 5 calls to set destination.
|
||||||
|
if (!isMaximized) {
|
||||||
|
setToInitialLocation = false;
|
||||||
|
wakeGenerationDelay = 2;
|
||||||
|
if(setCallCount-- == 0) {
|
||||||
|
setCallCount = 5;
|
||||||
|
if (lastPoint != null) {
|
||||||
|
Line l = new Line(
|
||||||
|
lastPoint.getX(),
|
||||||
|
lastPoint.getY(),
|
||||||
|
newXValue,
|
||||||
|
newYValue
|
||||||
|
);
|
||||||
|
l.getStrokeDashArray().setAll(3d, 7d);
|
||||||
|
l.setStroke(boatPoly.getFill());
|
||||||
|
lineStorage.add(l);
|
||||||
|
}
|
||||||
|
if (destinationSet) { //Only begin drawing after the first destination is set
|
||||||
|
lastPoint = new Point2D(newXValue, newYValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,8 +271,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
|
|
||||||
public void rotateTo (double rotation) {
|
public void rotateTo (double rotation) {
|
||||||
currentRotation = rotation;
|
currentRotation = rotation;
|
||||||
boatPoly.getTransforms().clear();
|
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
||||||
boatPoly.getTransforms().add(new Rotate(rotation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forceRotation () {
|
public void forceRotation () {
|
||||||
@@ -268,7 +295,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
wake.setVisible(visible);
|
wake.setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boat getBoat() {
|
public Yacht getBoat() {
|
||||||
return boat;
|
return boat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +307,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
*/
|
*/
|
||||||
public boolean hasRaceId (int... raceIds) {
|
public boolean hasRaceId (int... raceIds) {
|
||||||
for (int id : raceIds) {
|
for (int id : raceIds) {
|
||||||
if (id == boat.getId())
|
if (id == boat.getSourceID())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -292,7 +319,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
* @return An array containing all ID's associated with this RaceObject.
|
* @return An array containing all ID's associated with this RaceObject.
|
||||||
*/
|
*/
|
||||||
public int[] getRaceIds () {
|
public int[] getRaceIds () {
|
||||||
return new int[] {boat.getId()};
|
return new int[] {boat.getSourceID()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,4 +334,25 @@ public class BoatGroup extends RaceObject{
|
|||||||
group.getChildren().addAll(wake, lineGroup);
|
group.getChildren().addAll(wake, lineGroup);
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this function to let the BoatGroup know about the stage it is in. If it knows about it's stage then it will
|
||||||
|
* listen to the iconified property of that stage and change it's behaviour upon minimization. Without setting the
|
||||||
|
* Stage there is guarantee that the BoatGroup will draw properly when the stage is minimized.
|
||||||
|
*
|
||||||
|
* @param stage The stage that the BoatGroup is added to.
|
||||||
|
*/
|
||||||
|
public void setStage (Stage stage) {
|
||||||
|
/* TODO: 4/05/17 cir27 - Find a way to get the stage to this point. Need to pass it through multiple controllers.
|
||||||
|
App.start() -> Controller.setContentPane -> RaceViewController -> CanvasController
|
||||||
|
*/
|
||||||
|
this.stage = stage;
|
||||||
|
this.stage.iconifiedProperty().addListener(e -> {
|
||||||
|
isMaximized = !stage.isIconified();
|
||||||
|
if (!lineStorage.isEmpty()) {
|
||||||
|
lineGroup.getChildren().addAll(lineStorage);
|
||||||
|
lineStorage.clear();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.Date;
|
|||||||
*/
|
*/
|
||||||
public class Event {
|
public class Event {
|
||||||
private Double time; // Time the event occurs
|
private Double time; // Time the event occurs
|
||||||
private Boat boat;
|
private Yacht boat;
|
||||||
private boolean isFinishingEvent = false; // This event occurs when a boat finishes the race
|
private boolean isFinishingEvent = false; // This event occurs when a boat finishes the race
|
||||||
private Mark mark1; // This mark
|
private Mark mark1; // This mark
|
||||||
private Mark mark2; // Next mark
|
private Mark mark2; // Next mark
|
||||||
@@ -21,8 +21,6 @@ public class Event {
|
|||||||
private final double ORIGIN_LON = -64.857063;
|
private final double ORIGIN_LON = -64.857063;
|
||||||
private final double SCALE = 16000;
|
private final double SCALE = 16000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event class containing the time of specific event, related team/boat, and
|
* Event class containing the time of specific event, related team/boat, and
|
||||||
* event location such as leg.
|
* event location such as leg.
|
||||||
@@ -30,7 +28,7 @@ public class Event {
|
|||||||
* @param eventTime, what time the event happens
|
* @param eventTime, what time the event happens
|
||||||
* @param eventBoat, the boat that the event belongs to
|
* @param eventBoat, the boat that the event belongs to
|
||||||
*/
|
*/
|
||||||
public Event(Double eventTime, Boat eventBoat, Mark mark1, Mark mark2, int markPosInRace) {
|
public Event(Double eventTime, Yacht eventBoat, Mark mark1, Mark mark2, int markPosInRace) {
|
||||||
this.time = eventTime;
|
this.time = eventTime;
|
||||||
this.boat = eventBoat;
|
this.boat = eventBoat;
|
||||||
this.mark1 = mark1;
|
this.mark1 = mark1;
|
||||||
@@ -47,7 +45,7 @@ public class Event {
|
|||||||
* @param eventTime, what time the event happens
|
* @param eventTime, what time the event happens
|
||||||
* @param eventBoat, the boat that the event belongs to
|
* @param eventBoat, the boat that the event belongs to
|
||||||
*/
|
*/
|
||||||
public Event(Double eventTime, Boat eventBoat, Mark mark1, int markPosInRace) {
|
public Event(Double eventTime, Yacht eventBoat, Mark mark1, int markPosInRace) {
|
||||||
this.time = eventTime;
|
this.time = eventTime;
|
||||||
this.boat = eventBoat;
|
this.boat = eventBoat;
|
||||||
this.mark1 = mark1;
|
this.mark1 = mark1;
|
||||||
@@ -72,11 +70,11 @@ public class Event {
|
|||||||
return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time.longValue()));
|
return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time.longValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boat getBoat() {
|
public Yacht getBoat() {
|
||||||
return this.boat;
|
return this.boat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBoat(Boat eventBoat) {
|
public void setBoat(Yacht eventBoat) {
|
||||||
this.boat = eventBoat;
|
this.boat = eventBoat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,10 +90,10 @@ public class Event {
|
|||||||
public String getEventString() {
|
public String getEventString() {
|
||||||
// This event is a boat finishing the race
|
// This event is a boat finishing the race
|
||||||
if (this.isFinishingEvent) {
|
if (this.isFinishingEvent) {
|
||||||
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " finished the race");
|
return (this.getTimeString() + ", " + this.getBoat().getBoatName() + " finished the race");
|
||||||
}
|
}
|
||||||
// System.out.println(this.getDistanceBetweenMarks());
|
// System.out.println(this.getDistanceBetweenMarks());
|
||||||
return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " passed " + this.mark1.getName() + " going heading " + this.getBoatHeading() + "°");
|
return (this.getTimeString() + ", " + this.getBoat().getBoatName() + " passed " + this.mark1.getName() + " going heading " + this.getBoatHeading() + "°");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class Race {
|
public class Race {
|
||||||
|
|
||||||
private ArrayList<Boat> boats; // The boats in the race
|
private ArrayList<Yacht> boats; // The boats in the race
|
||||||
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
|
private ArrayList<Yacht> finishingOrder; // The order in which the boats finish the race
|
||||||
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in 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 List<Mark> course; // Marks in the race
|
||||||
private long startTime = 0;
|
private long startTime = 0;
|
||||||
private double timeScale = 1;
|
private double timeScale = 1;
|
||||||
@@ -33,7 +33,7 @@ public class Race {
|
|||||||
*
|
*
|
||||||
* @param boat, the boat to add
|
* @param boat, the boat to add
|
||||||
*/
|
*/
|
||||||
public void addBoat(Boat boat) {
|
public void addBoat(Yacht boat) {
|
||||||
boats.add(boat);
|
boats.add(boat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,12 +42,12 @@ public class Race {
|
|||||||
*
|
*
|
||||||
* @return a list of boats
|
* @return a list of boats
|
||||||
*/
|
*/
|
||||||
public Boat[] getShuffledBoats() {
|
public Yacht[] getShuffledBoats() {
|
||||||
// Shuffle the list of boats
|
// Shuffle the list of boats
|
||||||
long seed = System.nanoTime();
|
long seed = System.nanoTime();
|
||||||
Collections.shuffle(this.boats, new Random(seed));
|
Collections.shuffle(this.boats, new Random(seed));
|
||||||
|
|
||||||
return boats.toArray(new Boat[boats.size()]);
|
return boats.toArray(new Yacht[boats.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,8 +56,8 @@ public class Race {
|
|||||||
*
|
*
|
||||||
* @return a list of boats
|
* @return a list of boats
|
||||||
*/
|
*/
|
||||||
public Boat[] getFinishedBoats() {
|
public Yacht[] getFinishedBoats() {
|
||||||
return this.finishingOrder.toArray(new Boat[this.finishingOrder.size()]);
|
return this.finishingOrder.toArray(new Yacht[this.finishingOrder.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -66,8 +66,8 @@ public class Race {
|
|||||||
*
|
*
|
||||||
* @return a list of the boats competing in the race
|
* @return a list of the boats competing in the race
|
||||||
*/
|
*/
|
||||||
public Boat[] getBoats() {
|
public Yacht[] getBoats() {
|
||||||
return boats.toArray(new Boat[boats.size()]);
|
return boats.toArray(new Yacht[boats.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +84,7 @@ public class Race {
|
|||||||
*/
|
*/
|
||||||
private void generateEvents() {
|
private void generateEvents() {
|
||||||
|
|
||||||
for (Boat boat : this.boats) {
|
for (Yacht boat : this.boats) {
|
||||||
double totalDistance = 0;
|
double totalDistance = 0;
|
||||||
int numberOfMarks = this.course.size();
|
int numberOfMarks = this.course.size();
|
||||||
|
|
||||||
@@ -102,8 +102,8 @@ public class Race {
|
|||||||
events.put(boat, new ArrayList<>(Arrays.asList(event)));
|
events.put(boat, new ArrayList<>(Arrays.asList(event)));
|
||||||
}
|
}
|
||||||
totalDistance += event.getDistanceBetweenMarks();
|
totalDistance += event.getDistanceBetweenMarks();
|
||||||
System.out.println(totalDistance);
|
//System.out.println(totalDistance);
|
||||||
System.out.println(boat.getVelocity());
|
//System.out.println(boat.getVelocity());
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are no more marks after this event
|
// There are no more marks after this event
|
||||||
@@ -146,7 +146,7 @@ public class Race {
|
|||||||
* Get a map of the events in the race
|
* Get a map of the events in the race
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public HashMap<Boat, List> getEvents() {
|
public HashMap<Yacht, List> getEvents() {
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ public class Race {
|
|||||||
* Set a boat as finished
|
* Set a boat as finished
|
||||||
* @param boat The boat that has finished the race/home/cosc/student/wmu16
|
* @param boat The boat that has finished the race/home/cosc/student/wmu16
|
||||||
*/
|
*/
|
||||||
public void setBoatFinished(Boat boat){
|
public void setBoatFinished(Yacht boat){
|
||||||
this.finishingOrder.add(boat);
|
this.finishingOrder.add(boat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class Wake extends Group {
|
|||||||
//Default triangle is -110 deg out of phase with a default wake and has angle of 40 deg.
|
//Default triangle is -110 deg out of phase with a default wake and has angle of 40 deg.
|
||||||
arc = new Arc(0,0,0,0,-110,40);
|
arc = new Arc(0,0,0,0,-110,40);
|
||||||
//Opacity increases from 0.5 -> 0 evenly over the 5 wake arcs.
|
//Opacity increases from 0.5 -> 0 evenly over the 5 wake arcs.
|
||||||
arc.setFill(new Color(0.18, 0.7, 1.0, 0.50 + -0.1 * i));
|
arc.setFill(new Color(0.18, 0.7, 1.0, 1.0 + -0.175 * i));
|
||||||
arc.setType(ArcType.ROUND);
|
arc.setType(ArcType.ROUND);
|
||||||
arcs[i] = arc;
|
arcs[i] = arc;
|
||||||
}
|
}
|
||||||
@@ -52,17 +52,18 @@ class Wake extends Group {
|
|||||||
* @param velocity The real world velocity of the boat in m/s.
|
* @param velocity The real world velocity of the boat in m/s.
|
||||||
*/
|
*/
|
||||||
void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocity) {
|
void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocity) {
|
||||||
// if (Math.abs(rotationalVelocity) > 0.5) {
|
|
||||||
// rotationalVelocity = 0;
|
|
||||||
// }
|
|
||||||
sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]);
|
sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]);
|
||||||
sum += Math.abs(rotationalVelocity);
|
sum += Math.abs(rotationalVelocity);
|
||||||
// System.out.println("sum = " + sum);
|
|
||||||
max = Math.max(max, rotationalVelocity);
|
max = Math.max(max, rotationalVelocity);
|
||||||
if (sum < max)
|
if (sum < (max / 3))
|
||||||
rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position.
|
rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position.
|
||||||
//This stops the wake from eventually becoming out of sync with the boat.
|
//This stops the wake from eventually becoming out of sync with the boat.
|
||||||
|
//This accounts for rogue rotations that are greater than what would be realistic. Value is kinda rough.
|
||||||
|
//Basically just for our internal mock.
|
||||||
|
if (Math.abs(rotationalVelocity) > 0.05) {
|
||||||
|
rotationalVelocity = 0;
|
||||||
|
rotate(rotationGoal);
|
||||||
|
}
|
||||||
//Update the index of the array of recent velocities that each wake uses. Each wake is 3 velocities behind the
|
//Update the index of the array of recent velocities that each wake uses. Each wake is 3 velocities behind the
|
||||||
//next smallest wake.
|
//next smallest wake.
|
||||||
velocityIndices[0] = (13 + (velocityIndices[0] - 1) % 13) % 13;
|
velocityIndices[0] = (13 + (velocityIndices[0] - 1) % 13) % 13;
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package seng302.models;
|
||||||
|
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yacht class for the racing boat.
|
||||||
|
*
|
||||||
|
* Class created to store more variables (eg. boat statuses) compared to the XMLParser boat class,
|
||||||
|
* also done outside Boat class because some old variables are not used anymore.
|
||||||
|
*/
|
||||||
|
public class Yacht {
|
||||||
|
private Color colour;
|
||||||
|
private double velocity;
|
||||||
|
private Integer markLastPast;
|
||||||
|
|
||||||
|
private String boatType;
|
||||||
|
private Integer sourceID;
|
||||||
|
private String hullID; //matches HullNum in the XML spec.
|
||||||
|
private String shortName;
|
||||||
|
private String boatName;
|
||||||
|
private String country;
|
||||||
|
// Boat status
|
||||||
|
private Integer boatStatus;
|
||||||
|
private Integer legNumber;
|
||||||
|
private Integer penaltiesAwarded;
|
||||||
|
private Integer penaltiesServed;
|
||||||
|
private Long estimateTimeAtNextMark;
|
||||||
|
private Long estimateTimeAtFinish;
|
||||||
|
private String position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in EventTest and RaceTest.
|
||||||
|
*
|
||||||
|
* @param boatName Create a yacht object with name.
|
||||||
|
*/
|
||||||
|
public Yacht (String boatName) {
|
||||||
|
this.boatName = boatName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in BoatGroupTest.
|
||||||
|
*
|
||||||
|
* @param boatName 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 Yacht(String boatName, double boatVelocity, String shortName, int id) {
|
||||||
|
this.boatName = boatName;
|
||||||
|
this.velocity = boatVelocity;
|
||||||
|
this.shortName = shortName;
|
||||||
|
this.sourceID = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Yacht(String boatType, Integer sourceID, String hullID, String shortName, String boatName, String country) {
|
||||||
|
this.boatType = boatType;
|
||||||
|
this.sourceID = sourceID;
|
||||||
|
this.hullID = hullID;
|
||||||
|
this.shortName = shortName;
|
||||||
|
this.boatName = boatName;
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBoatType() {
|
||||||
|
return boatType;
|
||||||
|
}
|
||||||
|
public Integer getSourceID() {
|
||||||
|
return sourceID;
|
||||||
|
}
|
||||||
|
public String getHullID() {
|
||||||
|
return hullID;
|
||||||
|
}
|
||||||
|
public String getShortName() {
|
||||||
|
return shortName;
|
||||||
|
}
|
||||||
|
public String getBoatName() {
|
||||||
|
return boatName;
|
||||||
|
}
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getBoatStatus() {
|
||||||
|
return boatStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoatStatus(Integer boatStatus) {
|
||||||
|
this.boatStatus = boatStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLegNumber() {
|
||||||
|
return legNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLegNumber(Integer legNumber) {
|
||||||
|
this.legNumber = legNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPenaltiesAwarded() {
|
||||||
|
return penaltiesAwarded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPenaltiesAwarded(Integer penaltiesAwarded) {
|
||||||
|
this.penaltiesAwarded = penaltiesAwarded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPenaltiesServed() {
|
||||||
|
return penaltiesServed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPenaltiesServed(Integer penaltiesServed) {
|
||||||
|
this.penaltiesServed = penaltiesServed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getEstimateTimeAtNextMark() {
|
||||||
|
// DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
||||||
|
// return format.format(estimateTimeAtNextMark);
|
||||||
|
return estimateTimeAtNextMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEstimateTimeAtNextMark(Long estimateTimeAtNextMark) {
|
||||||
|
this.estimateTimeAtNextMark = estimateTimeAtNextMark;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEstimateTimeAtFinish() {
|
||||||
|
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
||||||
|
return format.format(estimateTimeAtFinish);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEstimateTimeAtFinish(Long estimateTimeAtFinish) {
|
||||||
|
this.estimateTimeAtFinish = estimateTimeAtFinish;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(String position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColour() {
|
||||||
|
return colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColour(Color colour) {
|
||||||
|
this.colour = colour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getVelocity() {
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVelocity(double velocity) {
|
||||||
|
this.velocity = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getMarkLastPast() {
|
||||||
|
return markLastPast;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMarkLastPast(Integer markLastPast) {
|
||||||
|
this.markLastPast = markLastPast;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,12 +58,7 @@ public class MarkGroup extends RaceObject {
|
|||||||
nodePixelVelocitiesX = new double[]{0d,0d};
|
nodePixelVelocitiesX = new double[]{0d,0d};
|
||||||
nodePixelVelocitiesY = new double[]{0d,0d};
|
nodePixelVelocitiesY = new double[]{0d,0d};
|
||||||
nodeDestinations = new Point2D[2];
|
nodeDestinations = new Point2D[2];
|
||||||
// markCircle = new Circle(
|
|
||||||
// (points[1].getX() - points[0].getX()) / 2d,
|
|
||||||
// (points[1].getY() - points[0].getY()) / 2d,
|
|
||||||
// MARK_RADIUS,
|
|
||||||
// color
|
|
||||||
//
|
|
||||||
markCircle = new Circle(
|
markCircle = new Circle(
|
||||||
points[0].getX(),
|
points[0].getX(),
|
||||||
points[0].getY(),
|
points[0].getY(),
|
||||||
@@ -72,12 +67,7 @@ public class MarkGroup extends RaceObject {
|
|||||||
);
|
);
|
||||||
nodeDestinations[0] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
|
nodeDestinations[0] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
|
||||||
super.getChildren().add(markCircle);
|
super.getChildren().add(markCircle);
|
||||||
// markCircle = new Circle(
|
|
||||||
// -(points[1].getX() - points[0].getX()) / 2d,
|
|
||||||
// -(points[1].getY() - points[0].getY()) / 2d,
|
|
||||||
// MARK_RADIUS,
|
|
||||||
// color
|
|
||||||
// );
|
|
||||||
markCircle = new Circle(
|
markCircle = new Circle(
|
||||||
points[1].getX(),
|
points[1].getX(),
|
||||||
points[1].getY(),
|
points[1].getY(),
|
||||||
@@ -99,7 +89,6 @@ public class MarkGroup extends RaceObject {
|
|||||||
}
|
}
|
||||||
super.getChildren().add(line);
|
super.getChildren().add(line);
|
||||||
}
|
}
|
||||||
//moveTo(points[0].getX(), points[0].getY());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestination (double x, double y, double rotation, double groundSpeed, int... raceIds) {
|
public void setDestination (double x, double y, double rotation, double groundSpeed, int... raceIds) {
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package seng302.models.parsers;
|
|
||||||
|
|
||||||
import org.w3c.dom.*;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import seng302.models.Boat;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.StringBufferInputStream;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by ryan_ on 30/04/2017.
|
|
||||||
*/
|
|
||||||
public class BoatsParser extends FileParser {
|
|
||||||
private Document doc;
|
|
||||||
|
|
||||||
public BoatsParser(String xmlString) {
|
|
||||||
this.doc = this.parseFile(xmlString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a boat instance from a given node if 'Type' is 'Yacht'
|
|
||||||
*
|
|
||||||
* @param node a boat node
|
|
||||||
* @return an instance of Boat
|
|
||||||
*/
|
|
||||||
private Boat parseBoat(Node node) {
|
|
||||||
try {
|
|
||||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
|
||||||
Element element = (Element) node;
|
|
||||||
if (element.getAttribute("Type").equals("Yacht")) {
|
|
||||||
String sourceID = element.getAttribute("SourceID");
|
|
||||||
String boatName = element.getAttribute("BoatName");
|
|
||||||
String shortName = element.getAttribute("ShortName");
|
|
||||||
String stoweName = element.getAttribute("StoweName");
|
|
||||||
String country = element.getAttribute("Country");
|
|
||||||
Boat boat = new Boat(Integer.parseInt(sourceID), boatName, shortName, country);
|
|
||||||
return boat;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new NoSuchElementException("Cannot generate a boat by given node");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of boats from the xml.
|
|
||||||
*
|
|
||||||
* @return a list of boats
|
|
||||||
*/
|
|
||||||
public List<Boat> getBoats() {
|
|
||||||
ArrayList<Boat> boats = new ArrayList<>();
|
|
||||||
|
|
||||||
try {
|
|
||||||
NodeList nodes = this.doc.getElementsByTagName("Boat");
|
|
||||||
for (int i = 0; i < nodes.getLength(); i++) {
|
|
||||||
Node node = nodes.item(i);
|
|
||||||
Boat boat = parseBoat(node);
|
|
||||||
if (!(boat == null)) {
|
|
||||||
boats.add(boat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return boats;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
package seng302.models.parsers;
|
package seng302.models.parsers;
|
||||||
|
|
||||||
|
|
||||||
import javafx.geometry.Point3D;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import seng302.models.Boat;
|
import seng302.models.Yacht;
|
||||||
import seng302.models.parsers.packets.BoatPositionPacket;
|
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||||
import seng302.models.parsers.packets.StreamPacket;
|
import seng302.models.parsers.packets.StreamPacket;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
@@ -34,11 +32,15 @@ public class StreamParser extends Thread{
|
|||||||
private String threadName;
|
private String threadName;
|
||||||
private Thread t;
|
private Thread t;
|
||||||
private static boolean raceStarted = false;
|
private static boolean raceStarted = false;
|
||||||
public static XMLParser xmlObject;
|
private static XMLParser xmlObject;
|
||||||
private static boolean raceFinished = false;
|
private static boolean raceFinished = false;
|
||||||
private static boolean streamStatus = false;
|
private static boolean streamStatus = false;
|
||||||
private static long timeSinceStart = -1;
|
private static long timeSinceStart = -1;
|
||||||
private static List<Boat> boats = new ArrayList<>();
|
private static Map<Integer, Yacht> boats = new HashMap<>();
|
||||||
|
private static Map<Long, Yacht> boatsPos = new TreeMap<>();
|
||||||
|
private static double windDirection = 0;
|
||||||
|
private static String currentTimeString;
|
||||||
|
private static boolean appRunning;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to initialise the thread name and stream parser object so a thread can be executed
|
* Used to initialise the thread name and stream parser object so a thread can be executed
|
||||||
@@ -55,14 +57,15 @@ public class StreamParser extends Thread{
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void run(){
|
public void run(){
|
||||||
|
appRunning = true;
|
||||||
try {
|
try {
|
||||||
System.out.println("START OF STREAM");
|
System.out.println("[CLIENT] Start of stream");
|
||||||
streamStatus = true;
|
streamStatus = true;
|
||||||
xmlObject = new XMLParser();
|
xmlObject = new XMLParser();
|
||||||
while (StreamReceiver.packetBuffer == null || StreamReceiver.packetBuffer.size() < 1) {
|
while (StreamReceiver.packetBuffer == null || StreamReceiver.packetBuffer.size() < 1) {
|
||||||
Thread.sleep(1);
|
Thread.sleep(1);
|
||||||
}
|
}
|
||||||
while (true){
|
while (appRunning){
|
||||||
StreamPacket packet = StreamReceiver.packetBuffer.peek();
|
StreamPacket packet = StreamReceiver.packetBuffer.peek();
|
||||||
//this code adds a delay to reading from the packetBuffer so
|
//this code adds a delay to reading from the packetBuffer so
|
||||||
//out of order packets have time to order themselves in the queue
|
//out of order packets have time to order themselves in the queue
|
||||||
@@ -93,7 +96,7 @@ public class StreamParser extends Thread{
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void start () {
|
public void start () {
|
||||||
System.out.println("Starting " + threadName );
|
System.out.println("[CLIENT] Starting " + threadName );
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
t = new Thread (this, threadName);
|
t = new Thread (this, threadName);
|
||||||
t.start ();
|
t.start ();
|
||||||
@@ -104,9 +107,10 @@ public class StreamParser extends Thread{
|
|||||||
* Looks at the type of the packet then sends it to the appropriate parser to extract the
|
* Looks at the type of the packet then sends it to the appropriate parser to extract the
|
||||||
* specific data associated with that packet type
|
* specific data associated with that packet type
|
||||||
*
|
*
|
||||||
* @param packet the packet to be looked at
|
* @param packet the packet to be looked at and processed
|
||||||
*/
|
*/
|
||||||
private static void parsePacket(StreamPacket packet) {
|
private static void parsePacket(StreamPacket packet) {
|
||||||
|
try{
|
||||||
switch (packet.getType()){
|
switch (packet.getType()){
|
||||||
case HEARTBEAT:
|
case HEARTBEAT:
|
||||||
extractHeartBeat(packet);
|
extractHeartBeat(packet);
|
||||||
@@ -149,6 +153,10 @@ public class StreamParser extends Thread{
|
|||||||
//System.out.println(packet.getType().toString());
|
//System.out.println(packet.getType().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (NullPointerException e){
|
||||||
|
System.out.println("Error parsing packet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the seq num used in the heartbeat packet
|
* Extracts the seq num used in the heartbeat packet
|
||||||
@@ -159,6 +167,22 @@ public class StreamParser extends Thread{
|
|||||||
long heartbeat = bytesToLong(packet.getPayload());
|
long heartbeat = bytesToLong(packet.getPayload());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getTimeZoneString() {
|
||||||
|
|
||||||
|
Integer offset = xmlObject.getRegattaXML().getUtcOffset();
|
||||||
|
StringBuilder utcOffset = new StringBuilder();
|
||||||
|
utcOffset.append("GMT");
|
||||||
|
if (offset > 0) {
|
||||||
|
utcOffset.append("+");
|
||||||
|
utcOffset.append(offset);
|
||||||
|
} else if (offset < 0) {
|
||||||
|
utcOffset.append("-");
|
||||||
|
utcOffset.append(offset);
|
||||||
|
}
|
||||||
|
return utcOffset.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the useful race status data from race status type packets. This method will also print to the
|
* Extracts the useful race status data from race status type packets. This method will also print to the
|
||||||
* console the current state of the race (if it has started/finished or is about to start), along side
|
* console the current state of the race (if it has started/finished or is about to start), along side
|
||||||
@@ -174,39 +198,70 @@ public class StreamParser extends Thread{
|
|||||||
int raceStatus = payload[11];
|
int raceStatus = payload[11];
|
||||||
// System.out.println("raceStatus = " + raceStatus);
|
// System.out.println("raceStatus = " + raceStatus);
|
||||||
long expectedStartTime = bytesToLong(Arrays.copyOfRange(payload,12,18));
|
long expectedStartTime = bytesToLong(Arrays.copyOfRange(payload,12,18));
|
||||||
|
|
||||||
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
||||||
format.setTimeZone(TimeZone.getTimeZone("UTC"));
|
if (xmlObject.getRegattaXML() != null) {
|
||||||
|
format.setTimeZone(TimeZone.getTimeZone(getTimeZoneString()));
|
||||||
|
currentTimeString = format.format((new Date (currentTime)).getTime());
|
||||||
|
}
|
||||||
long timeTillStart = ((new Date (expectedStartTime)).getTime() - (new Date (currentTime)).getTime())/1000;
|
long timeTillStart = ((new Date (expectedStartTime)).getTime() - (new Date (currentTime)).getTime())/1000;
|
||||||
|
|
||||||
|
|
||||||
if (timeTillStart > 0) {
|
if (timeTillStart > 0) {
|
||||||
timeSinceStart = timeTillStart;
|
timeSinceStart = timeTillStart;
|
||||||
System.out.println("Time till start: " + timeTillStart + " Seconds");
|
//System.out.println("Time till start: " + timeTillStart + " Seconds");
|
||||||
} else {
|
} else {
|
||||||
if (raceStatus == 4 || raceStatus == 8){
|
if (raceStatus == 4 || raceStatus == 8){
|
||||||
raceFinished = true;
|
raceFinished = true;
|
||||||
raceStarted = false;
|
raceStarted = false;
|
||||||
System.out.println("RACE HAS FINISHED");
|
System.out.println("[CLIENT] Race has finished");
|
||||||
} else if (!raceStarted){
|
} else if (!raceStarted){
|
||||||
raceStarted = true;
|
raceStarted = true;
|
||||||
raceFinished = false;
|
raceFinished = false;
|
||||||
System.out.println("RACE HAS STARTED");
|
System.out.println("[CLIENT] Race has started");
|
||||||
}
|
}
|
||||||
System.out.println("Time since start: " + -1 * timeTillStart + " Seconds");
|
//System.out.println("Time since start: " + -1 * timeTillStart + " Seconds");
|
||||||
timeSinceStart = timeTillStart;
|
timeSinceStart = timeTillStart;
|
||||||
}
|
}
|
||||||
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
||||||
|
double windDirFactor = 0x4000 / 90; //0x4000 is 90 degrees, 0x8000 is 180 degrees, etc...
|
||||||
|
windDirection = windDir / windDirFactor;
|
||||||
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
||||||
int noBoats = payload[22];
|
int noBoats = payload[22];
|
||||||
int raceType = payload[23];
|
int raceType = payload[23];
|
||||||
ArrayList<String> boatStatuses = new ArrayList<>();
|
// ArrayList<String> boatStatuses = new ArrayList<>();
|
||||||
|
boatsPos = new TreeMap<>();
|
||||||
for (int i = 0; i < noBoats; i++){
|
for (int i = 0; i < noBoats; i++){
|
||||||
String boatStatus = "SourceID: " + bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
||||||
boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)];
|
Yacht boat = boats.get((int)(long) boatStatusSourceID);
|
||||||
boatStatus += "\nLegNumber: " + (int)payload[29 + (i * 20)];
|
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
||||||
boatStatus += "\nPenaltiesAwarded: " + (int)payload[29 + (i * 20)];
|
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
||||||
boatStatus += "\nPenaltiesServed: " + (int)payload[30 + (i * 20)];
|
boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
|
||||||
boatStatus += "\nEstTimeAtNextMark: " + bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
boat.setPenaltiesServed((int)payload[30 + (i * 20)]);
|
||||||
boatStatus += "\nEstTimeAtFinish: " + bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
|
Long estTimeAtNextMark = bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
||||||
boatStatuses.add(boatStatus);
|
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
||||||
|
Long estTimeAtFinish = bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
|
||||||
|
boat.setEstimateTimeAtFinish(estTimeAtFinish);
|
||||||
|
boatsPos.put(estTimeAtFinish, boat);
|
||||||
|
// String boatStatus = "SourceID: " + boatStatusSourceID;
|
||||||
|
// boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)];
|
||||||
|
// boatStatus += "\nLegNumber: " + (int)payload[29 + (i * 20)];
|
||||||
|
// boatStatus += "\nPenaltiesAwarded: " + (int)payload[29 + (i * 20)];
|
||||||
|
// boatStatus += "\nPenaltiesServed: " + (int)payload[30 + (i * 20)];
|
||||||
|
// boatStatus += "\nEstTimeAtNextMark: " + bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
||||||
|
// boatStatus += "\nEstTimeAtFinish: " + bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
|
||||||
|
// boatStatuses.add(boatStatus);
|
||||||
|
}
|
||||||
|
if (isRaceStarted()) {
|
||||||
|
int pos = 1;
|
||||||
|
for (Yacht yacht : boatsPos.values()) {
|
||||||
|
yacht.setPosition(String.valueOf(pos));
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (Yacht yacht : boatsPos.values()) {
|
||||||
|
yacht.setPosition("-");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,6 +310,9 @@ public class StreamParser extends Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
xmlObject.constructXML(doc, messageType);
|
xmlObject.constructXML(doc, messageType);
|
||||||
|
if (messageType == 7) { //7 is the boat XML
|
||||||
|
boats = xmlObject.getBoatXML().getCompetingBoats();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -341,6 +399,7 @@ public class StreamParser extends Thread{
|
|||||||
//type 1 is a racing yacht and type 3 is a mark, needed for updating positions of the mark and boat
|
//type 1 is a racing yacht and type 3 is a mark, needed for updating positions of the mark and boat
|
||||||
if (deviceType == 1 || deviceType == 3){
|
if (deviceType == 1 || deviceType == 3){
|
||||||
BoatPositionPacket boatPacket = new BoatPositionPacket(boatId, timeValid, lat, lon, heading, groundSpeed);
|
BoatPositionPacket boatPacket = new BoatPositionPacket(boatId, timeValid, lat, lon, heading, groundSpeed);
|
||||||
|
|
||||||
//add a new priority que to the boatPositions HashMap
|
//add a new priority que to the boatPositions HashMap
|
||||||
if (!boatPositions.containsKey(boatId)){
|
if (!boatPositions.containsKey(boatId)){
|
||||||
boatPositions.put(boatId, new PriorityBlockingQueue<BoatPositionPacket>(256, new Comparator<BoatPositionPacket>() {
|
boatPositions.put(boatId, new PriorityBlockingQueue<BoatPositionPacket>(256, new Comparator<BoatPositionPacket>() {
|
||||||
@@ -350,6 +409,7 @@ public class StreamParser extends Thread{
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
//Adding the boatPacket to the priority que
|
||||||
boatPositions.get(boatId).put(boatPacket);
|
boatPositions.get(boatId).put(boatPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,11 +530,11 @@ public class StreamParser extends Thread{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return list of boats from the server
|
* return a map of boats with sourceID and the boat
|
||||||
*
|
*
|
||||||
* @return list of boats
|
* @return map of boats
|
||||||
*/
|
*/
|
||||||
public static List<Boat> getBoats() {
|
public static Map<Integer, Yacht> getBoats() {
|
||||||
return boats;
|
return boats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,5 +547,37 @@ public class StreamParser extends Thread{
|
|||||||
public static XMLParser getXmlObject() {
|
public static XMLParser getXmlObject() {
|
||||||
return xmlObject;
|
return xmlObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the wind direction in degrees
|
||||||
|
*
|
||||||
|
* @return a double wind direction value
|
||||||
|
*/
|
||||||
|
public static double getWindDirection() {
|
||||||
|
return windDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns stream time in formatted string format
|
||||||
|
*
|
||||||
|
* @return String of stream time
|
||||||
|
*/
|
||||||
|
public static String getCurrentTimeString() {
|
||||||
|
return currentTimeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used in boat position since tree map can sort position efficiently.
|
||||||
|
*
|
||||||
|
* @return a map of time to finish and boat.
|
||||||
|
*/
|
||||||
|
public static Map<Long, Yacht> getBoatsPos() {
|
||||||
|
return boatsPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void appClose(){
|
||||||
|
appRunning = false;
|
||||||
|
System.out.println("[CLIENT] Shutting down stream parser");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,11 @@ public class StreamReceiver extends Thread {
|
|||||||
private Thread t;
|
private Thread t;
|
||||||
private String threadName;
|
private String threadName;
|
||||||
public static PriorityBlockingQueue<StreamPacket> packetBuffer;
|
public static PriorityBlockingQueue<StreamPacket> packetBuffer;
|
||||||
|
private static boolean moreBytes;
|
||||||
|
|
||||||
public StreamReceiver(String hostAddress, int hostPort, String threadName) {
|
public StreamReceiver(String hostAddress, int hostPort, String threadName) {
|
||||||
this.threadName = threadName;
|
this.threadName = threadName;
|
||||||
|
this.setDaemon(true);
|
||||||
try {
|
try {
|
||||||
host = new Socket(hostAddress, hostPort);
|
host = new Socket(hostAddress, hostPort);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -44,7 +46,7 @@ public class StreamReceiver extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void start () {
|
public void start () {
|
||||||
System.out.println("Starting " + threadName );
|
System.out.println("[CLIENT] Starting " + threadName );
|
||||||
if (t == null) {
|
if (t == null) {
|
||||||
t = new Thread (this, threadName);
|
t = new Thread (this, threadName);
|
||||||
t.start ();
|
t.start ();
|
||||||
@@ -68,7 +70,7 @@ public class StreamReceiver extends Thread {
|
|||||||
|
|
||||||
int sync1;
|
int sync1;
|
||||||
int sync2;
|
int sync2;
|
||||||
boolean moreBytes = true;
|
moreBytes = true;
|
||||||
while(moreBytes) {
|
while(moreBytes) {
|
||||||
try {
|
try {
|
||||||
crcBuffer = new ByteArrayOutputStream();
|
crcBuffer = new ByteArrayOutputStream();
|
||||||
@@ -95,7 +97,6 @@ public class StreamReceiver extends Thread {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
moreBytes = false;
|
moreBytes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +122,6 @@ public class StreamReceiver extends Thread {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void skipBytes(long n) throws Exception{
|
private void skipBytes(long n) throws Exception{
|
||||||
for (int i=0; i < n; i++){
|
for (int i=0; i < n; i++){
|
||||||
readByte();
|
readByte();
|
||||||
@@ -147,7 +147,6 @@ public class StreamReceiver extends Thread {
|
|||||||
return partialLong;
|
return partialLong;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1");
|
StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1");
|
||||||
@@ -155,4 +154,9 @@ public class StreamReceiver extends Thread {
|
|||||||
sr.start();
|
sr.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void noMoreBytes(){
|
||||||
|
moreBytes = false;
|
||||||
|
System.out.println("[CLIENT] Shutting down stream receiver");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
package seng302.models.parsers;
|
//package seng302.models.parsers;
|
||||||
|
//
|
||||||
import org.w3c.dom.*;
|
//import org.w3c.dom.*;
|
||||||
import seng302.models.Boat;
|
//import seng302.models.Yacht;
|
||||||
|
//
|
||||||
import java.util.ArrayList;
|
//import java.util.ArrayList;
|
||||||
import java.util.NoSuchElementException;
|
//import java.util.NoSuchElementException;
|
||||||
|
//
|
||||||
public class TeamsParser extends FileParser {
|
//public class TeamsParser extends FileParser {
|
||||||
|
//
|
||||||
private Document doc;
|
// private Document doc;
|
||||||
|
//
|
||||||
public TeamsParser(String path) {
|
// public TeamsParser(String path) {
|
||||||
super(path);
|
// super(path);
|
||||||
this.doc = this.parseFile();
|
// this.doc = this.parseFile();
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Create a boat instance by a given team node
|
// * Create a boat instance by a given team node
|
||||||
* @param node a boat node containing name, alias and velocity
|
// * @param node a boat node containing name, alias and velocity
|
||||||
* @return an instance of Boat
|
// * @return an instance of Boat
|
||||||
*/
|
// */
|
||||||
private Boat parseBoat(Node node) {
|
// private Yacht parseBoat(Node node) {
|
||||||
try {
|
// try {
|
||||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
// if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
Element element = (Element) node;
|
// Element element = (Element) node;
|
||||||
String name = element.getElementsByTagName("name").item(0).getTextContent();
|
// String name = element.getElementsByTagName("name").item(0).getTextContent();
|
||||||
String alias = element.getElementsByTagName("alias").item(0).getTextContent();
|
// String alias = element.getElementsByTagName("alias").item(0).getTextContent();
|
||||||
double velocity = Double.valueOf(element.getElementsByTagName("velocity").item(0).getTextContent());
|
// double velocity = Double.valueOf(element.getElementsByTagName("velocity").item(0).getTextContent());
|
||||||
int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
|
// int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
|
||||||
Boat boat = new Boat(name, velocity, alias, id);
|
// Yacht boat = new Yacht(name, velocity, alias, id);
|
||||||
return boat;
|
// return boat;
|
||||||
} else {
|
// } else {
|
||||||
throw new NoSuchElementException("Cannot generate a boat by given node");
|
// throw new NoSuchElementException("Cannot generate a boat by given node");
|
||||||
}
|
// }
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/**
|
// /**
|
||||||
* Create an arraylist of boats instance.
|
// * Create an arraylist of boats instance.
|
||||||
* @return an arraylist of boats in teams file
|
// * @return an arraylist of boats in teams file
|
||||||
*/
|
// */
|
||||||
public ArrayList<Boat> getBoats() {
|
// public ArrayList<Yacht> getBoats() {
|
||||||
ArrayList<Boat> boats = new ArrayList<>();
|
// ArrayList<Yacht> boats = new ArrayList<>();
|
||||||
|
//
|
||||||
try {
|
// try {
|
||||||
NodeList nodes = this.doc.getElementsByTagName("team");
|
// NodeList nodes = this.doc.getElementsByTagName("team");
|
||||||
for (int i = 0; i < nodes.getLength(); i++) {
|
// for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
Node node = nodes.item(i);
|
// Node node = nodes.item(i);
|
||||||
boats.add(parseBoat(node));
|
// boats.add(parseBoat(node));
|
||||||
}
|
// }
|
||||||
return boats;
|
// return boats;
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import org.w3c.dom.Document;
|
|||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
import seng302.models.Yacht;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to create an XML object from the XML Packet Messages.
|
* Class to create an XML object from the XML Packet Messages.
|
||||||
@@ -391,7 +395,9 @@ public class XMLParser {
|
|||||||
private ArrayList<Double> zoneLimits;// will only contain 5 elements. Limits 1-5
|
private ArrayList<Double> zoneLimits;// will only contain 5 elements. Limits 1-5
|
||||||
|
|
||||||
//Boats
|
//Boats
|
||||||
ArrayList<Boat> boats;
|
ArrayList<Yacht> boats;
|
||||||
|
//Competing boats
|
||||||
|
Map<Integer, Yacht> competingBoats = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a BoatXMLObject.
|
* Constructor for a BoatXMLObject.
|
||||||
@@ -424,8 +430,17 @@ public class XMLParser {
|
|||||||
for (int i = 0; i < boatsList.getLength(); i++) {
|
for (int i = 0; i < boatsList.getLength(); i++) {
|
||||||
Node currentBoat = boatsList.item(i);
|
Node currentBoat = boatsList.item(i);
|
||||||
if (currentBoat.getNodeName().equals("Boat")) {
|
if (currentBoat.getNodeName().equals("Boat")) {
|
||||||
Boat boat = new Boat(currentBoat);
|
// Boat boat = new Boat(currentBoat);
|
||||||
|
Yacht boat = new Yacht(getNodeAttributeString(currentBoat, "Type"),
|
||||||
|
getNodeAttributeInt(currentBoat, "SourceID"),
|
||||||
|
getNodeAttributeString(currentBoat, "HullNum"),
|
||||||
|
getNodeAttributeString(currentBoat, "ShortName"),
|
||||||
|
getNodeAttributeString(currentBoat, "BoatName"),
|
||||||
|
getNodeAttributeString(currentBoat, "Country"));
|
||||||
this.boats.add(boat);
|
this.boats.add(boat);
|
||||||
|
if (boat.getBoatType().equals("Yacht")) {
|
||||||
|
competingBoats.put(boat.getSourceID(), boat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//System.out.println(this.getBoats());
|
//System.out.println(this.getBoats());
|
||||||
}
|
}
|
||||||
@@ -440,34 +455,37 @@ public class XMLParser {
|
|||||||
public Double getMarkZoneSize() { return markZoneSize; }
|
public Double getMarkZoneSize() { return markZoneSize; }
|
||||||
public Double getCourseZoneSize() { return courseZoneSize; }
|
public Double getCourseZoneSize() { return courseZoneSize; }
|
||||||
public ArrayList<Double> getZoneLimits() { return zoneLimits; }
|
public ArrayList<Double> getZoneLimits() { return zoneLimits; }
|
||||||
public ArrayList<Boat> getBoats() { return boats; }
|
public ArrayList<Yacht> getBoats() { return boats; }
|
||||||
|
public Map<Integer, Yacht> getCompetingBoats() {
|
||||||
public class Boat {
|
return competingBoats;
|
||||||
|
|
||||||
private String boatType;
|
|
||||||
private Integer sourceID;
|
|
||||||
private String hullID; //matches HullNum in the XML spec.
|
|
||||||
private String shortName;
|
|
||||||
private String boatName;
|
|
||||||
private String country;
|
|
||||||
|
|
||||||
Boat(Node boatNode) {
|
|
||||||
this.boatType = getNodeAttributeString(boatNode, "Type");
|
|
||||||
this.sourceID = getNodeAttributeInt(boatNode, "SourceID");
|
|
||||||
this.hullID = getNodeAttributeString(boatNode, "HullNum");
|
|
||||||
this.shortName = getNodeAttributeString(boatNode, "ShortName");
|
|
||||||
this.boatName = getNodeAttributeString(boatNode, "BoatName");
|
|
||||||
this.country = getNodeAttributeString(boatNode, "Country");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBoatType() { return boatType; }
|
// public class Boat {
|
||||||
public Integer getSourceID() { return sourceID; }
|
//
|
||||||
public String getHullID() { return hullID; }
|
// private String boatType;
|
||||||
public String getShortName() { return shortName; }
|
// private Integer sourceID;
|
||||||
public String getBoatName() { return boatName; }
|
// private String hullID; //matches HullNum in the XML spec.
|
||||||
public String getCountry() { return country; }
|
// private String shortName;
|
||||||
|
// private String boatName;
|
||||||
}
|
// private String country;
|
||||||
|
//
|
||||||
|
// Boat(Node boatNode) {
|
||||||
|
// this.boatType = getNodeAttributeString(boatNode, "Type");
|
||||||
|
// this.sourceID = getNodeAttributeInt(boatNode, "SourceID");
|
||||||
|
// this.hullID = getNodeAttributeString(boatNode, "HullNum");
|
||||||
|
// this.shortName = getNodeAttributeString(boatNode, "ShortName");
|
||||||
|
// this.boatName = getNodeAttributeString(boatNode, "BoatName");
|
||||||
|
// this.country = getNodeAttributeString(boatNode, "Country");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public String getBoatType() { return boatType; }
|
||||||
|
// public Integer getSourceID() { return sourceID; }
|
||||||
|
// public String getHullID() { return hullID; }
|
||||||
|
// public String getShortName() { return shortName; }
|
||||||
|
// public String getBoatName() { return boatName; }
|
||||||
|
// public String getCountry() { return country; }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,36 +3,39 @@ package seng302.server;
|
|||||||
import seng302.server.messages.*;
|
import seng302.server.messages.*;
|
||||||
import seng302.server.simulator.Boat;
|
import seng302.server.simulator.Boat;
|
||||||
import seng302.server.simulator.Simulator;
|
import seng302.server.simulator.Simulator;
|
||||||
import sun.misc.IOUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class ServerThread implements Runnable, Observer {
|
public class ServerThread implements Runnable, Observer {
|
||||||
private Thread runner;
|
|
||||||
private StreamingServerSocket server;
|
private StreamingServerSocket server;
|
||||||
private long startTime;
|
private long startTime;
|
||||||
boolean raceStarted = false;
|
private boolean raceStarted = false;
|
||||||
Map<Integer,Boolean> boatsFinished = new HashMap<>();
|
private Map<Integer,Boolean> boatsFinished = new HashMap<>();
|
||||||
private List<Boat> boats;
|
private List<Boat> boats;
|
||||||
private Simulator raceSimulator;
|
private Simulator raceSimulator;
|
||||||
|
private boolean sendingRaceFinishedLocationMessages = true;
|
||||||
|
|
||||||
private final int HEARTBEAT_PERIOD = 5000;
|
private final int HEARTBEAT_PERIOD = 5000;
|
||||||
private final int RACE_STATUS_PERIOD = 1000;
|
private final int RACE_STATUS_PERIOD = 1000/2;
|
||||||
private final int RACE_START_STATUS_PERIOD = 1000;
|
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 = 4949;
|
||||||
private final int TIME_TILL_RACE_START = 20*1000;
|
private final int TIME_TILL_RACE_START = 20*1000;
|
||||||
private static final int LOG_LEVEL = 1;
|
private static final int LOG_LEVEL = 1;
|
||||||
|
|
||||||
public ServerThread(String threadName){
|
public ServerThread(String threadName){
|
||||||
runner = new Thread(this, threadName);
|
Thread runner = new Thread(this, threadName);
|
||||||
|
runner.setDaemon(true);
|
||||||
|
|
||||||
serverLog("Spawning Server", 0);
|
serverLog("Spawning Server", 0);
|
||||||
|
|
||||||
raceSimulator = new Simulator(BOAT_LOCATION_PERIOD);
|
raceSimulator = new Simulator(BOAT_LOCATION_PERIOD);
|
||||||
|
raceSimulator.addObserver(this);
|
||||||
|
// run race simulator, so it can send boats' static location.
|
||||||
|
Thread raceSimulatorThread = new Thread(raceSimulator, "Race Simulator");
|
||||||
|
|
||||||
boats = raceSimulator.getBoats();
|
boats = raceSimulator.getBoats();
|
||||||
|
|
||||||
for (Boat b : boats){
|
for (Boat b : boats){
|
||||||
@@ -40,9 +43,10 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runner.start();
|
runner.start();
|
||||||
|
raceSimulatorThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void serverLog(String message, int logLevel){
|
static void serverLog(String message, int logLevel){
|
||||||
if(logLevel <= LOG_LEVEL){
|
if(logLevel <= LOG_LEVEL){
|
||||||
System.out.println("[SERVER] " + message);
|
System.out.println("[SERVER] " + message);
|
||||||
}
|
}
|
||||||
@@ -54,7 +58,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
* @param type The XML Message type
|
* @param type The XML Message type
|
||||||
* @return The XML Message
|
* @return The XML Message
|
||||||
*/
|
*/
|
||||||
public Message getXmlMessage(String fileName, XMLMessageSubType type){
|
private Message getXmlMessage(String fileName, XMLMessageSubType type){
|
||||||
String fileContents = null;
|
String fileContents = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -76,8 +80,8 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
/**
|
/**
|
||||||
* @return Get a race status message for the current race
|
* @return Get a race status message for the current race
|
||||||
*/
|
*/
|
||||||
public Message getRaceStatusMessage(){
|
private Message getRaceStatusMessage(){
|
||||||
List<BoatSubMessage> boatSubMessages = new ArrayList<BoatSubMessage>();
|
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
||||||
BoatStatus boatStatus;
|
BoatStatus boatStatus;
|
||||||
RaceStatus raceStatus;
|
RaceStatus raceStatus;
|
||||||
boolean thereAreBoatsNotFinished = false;
|
boolean thereAreBoatsNotFinished = false;
|
||||||
@@ -95,7 +99,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
thereAreBoatsNotFinished = true;
|
thereAreBoatsNotFinished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoatSubMessage m = new BoatSubMessage(b.getSourceID(), boatStatus, b.getLastPassedCorner().getSeqID(), 0, 0, 0, 0);
|
BoatSubMessage m = new BoatSubMessage(b.getSourceID(), boatStatus, b.getLastPassedCorner().getSeqID(), 0, 0, b.getEstimatedTimeTillFinish(), b.getEstimatedTimeTillFinish());
|
||||||
boatSubMessages.add(m);
|
boatSubMessages.add(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +126,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
raceStatus = RaceStatus.TERMINATED;
|
raceStatus = RaceStatus.TERMINATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RaceStatusMessage(1, raceStatus, startTime, WindDirection.EAST,
|
return new RaceStatusMessage(1, raceStatus, startTime, WindDirection.SOUTH,
|
||||||
100, boats.size(), RaceType.MATCH_RACE, 1, boatSubMessages);
|
100, boats.size(), RaceType.MATCH_RACE, 1, boatSubMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +134,9 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
* Starts an instance of the race simulator
|
* Starts an instance of the race simulator
|
||||||
*/
|
*/
|
||||||
private void startRaceSim(){
|
private void startRaceSim(){
|
||||||
serverLog("Starting Race Simulator", 0);
|
serverLog("Starting Running Race Simulator", 0);
|
||||||
raceSimulator.addObserver(this);
|
// set race started to true, so the simulator will start moving boats
|
||||||
new Thread(raceSimulator).start();
|
raceSimulator.setRaceStarted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,32 +254,70 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
startSendingRaceStatusMessages();
|
startSendingRaceStatusMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start sending static boat position updates when race has finished
|
||||||
|
*/
|
||||||
|
private void startSendingRaceFinishedBoatPostions(){
|
||||||
|
Timer t = new Timer();
|
||||||
|
t.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
for (Boat b : raceSimulator.getBoats()){
|
||||||
|
Message m = new BoatLocationMessage(b.getSourceID(), server.getSequenceNumber(), b.getLat(),
|
||||||
|
b.getLng(), b.getLastPassedCorner().getBearingToNextCorner(),
|
||||||
|
((long) 0));
|
||||||
|
|
||||||
|
server.send(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.print("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0, BOAT_LOCATION_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a boat location message when they are updated by the simulator
|
* Send a boat location message when they are updated by the simulator
|
||||||
* @param o .
|
* @param o .
|
||||||
* @param arg .
|
* @param arg .
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
// Only send if server started
|
// Only send if server started
|
||||||
if(!server.isStarted()){
|
// TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17
|
||||||
|
if(server == null || !server.isStarted()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Boat b : ((Simulator) o).getBoats()){
|
int numOfBoatsFinished = 0;
|
||||||
|
for (Boat boat : (List<Boat>) arg){
|
||||||
try {
|
try {
|
||||||
Message m = new BoatLocationMessage(b.getSourceID(), 1, b.getLat(),
|
if (boat.isFinished()) {
|
||||||
b.getLng(), b.getLastPassedCorner().getBearingToNextCorner(),
|
numOfBoatsFinished ++;
|
||||||
((long) b.getSpeed()));
|
if (!boatsFinished.get(boat.getSourceID())) {
|
||||||
|
boatsFinished.put(boat.getSourceID(), true);
|
||||||
|
serverLog("Boat " + boat.getSourceID() + " finished the race", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message m = new BoatLocationMessage(boat.getSourceID(), 1, boat.getLat(),
|
||||||
|
boat.getLng(), boat.getLastPassedCorner().getBearingToNextCorner(),
|
||||||
|
((long) boat.getSpeed()));
|
||||||
server.send(m);
|
server.send(m);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
serverLog("Couldn't send a boat status message", 3);
|
serverLog("Couldn't send a boat status message", 3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (NullPointerException e){
|
catch (NullPointerException e){
|
||||||
serverLog("Boat " + b.getSourceID() + " finished the race", 1);
|
e.printStackTrace();
|
||||||
boatsFinished.put(b.getSourceID(), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
||||||
|
startSendingRaceFinishedBoatPostions();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public class BoatLocationMessage extends Message {
|
|||||||
* @param boatSpeed The boats speed
|
* @param boatSpeed The boats speed
|
||||||
*/
|
*/
|
||||||
public BoatLocationMessage(int sourceId, int sequenceNum, double latitude, double longitude, double heading, long boatSpeed){
|
public BoatLocationMessage(int sourceId, int sequenceNum, double latitude, double longitude, double heading, long boatSpeed){
|
||||||
|
boatSpeed /= 10;
|
||||||
messageVersionNumber = 1;
|
messageVersionNumber = 1;
|
||||||
time = System.currentTimeMillis() / 1000L;
|
time = System.currentTimeMillis() / 1000L;
|
||||||
this.sourceId = sourceId;
|
this.sourceId = sourceId;
|
||||||
@@ -54,8 +55,8 @@ public class BoatLocationMessage extends Message {
|
|||||||
this.pitch = 0;
|
this.pitch = 0;
|
||||||
this.roll = 0;
|
this.roll = 0;
|
||||||
this.boatSpeed = boatSpeed;
|
this.boatSpeed = boatSpeed;
|
||||||
this.COG = 0;
|
this.COG = 2;
|
||||||
this.SOG = 0;
|
this.SOG = boatSpeed ;
|
||||||
this.apparentWindSpeed = 0;
|
this.apparentWindSpeed = 0;
|
||||||
this.apparentWindAngle = 0;
|
this.apparentWindAngle = 0;
|
||||||
this.trueWindSpeed = 0;
|
this.trueWindSpeed = 0;
|
||||||
@@ -146,7 +147,7 @@ public class BoatLocationMessage extends Message {
|
|||||||
putInt(headingToSend, 2);
|
putInt(headingToSend, 2);
|
||||||
putInt((int) pitch, 2);
|
putInt((int) pitch, 2);
|
||||||
putInt((int) roll, 2);
|
putInt((int) roll, 2);
|
||||||
putUnsignedInt((int) boatSpeed, 2);
|
putInt((int) boatSpeed, 2);
|
||||||
putUnsignedInt((int) COG, 2);
|
putUnsignedInt((int) COG, 2);
|
||||||
putUnsignedInt((int) SOG, 2);
|
putUnsignedInt((int) SOG, 2);
|
||||||
putUnsignedInt((int) apparentWindSpeed, 2);
|
putUnsignedInt((int) apparentWindSpeed, 2);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package seng302.server.messages;
|
package seng302.server.messages;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,6 +15,8 @@ public class BoatSubMessage{
|
|||||||
private long numberPenaltiesServed;
|
private long numberPenaltiesServed;
|
||||||
private long estimatedTimeAtNextMark;
|
private long estimatedTimeAtNextMark;
|
||||||
private long estimatedTimeAtFinish;
|
private long estimatedTimeAtFinish;
|
||||||
|
private ByteBuffer buff = ByteBuffer.allocate(getSize());
|
||||||
|
private int buffPos = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boat Sub message from section 4.2 of the AC35 streaming data interface spec
|
* Boat Sub message from section 4.2 of the AC35 streaming data interface spec
|
||||||
@@ -45,47 +46,39 @@ public class BoatSubMessage{
|
|||||||
return MESSAGE_SIZE;
|
return MESSAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void putInBuffer(byte[] bytes, long val){
|
||||||
|
byte[] tmp = bytes.clone();
|
||||||
|
Message.reverse(tmp);
|
||||||
|
|
||||||
|
buff.put(tmp);
|
||||||
|
buffPos += tmp.length;
|
||||||
|
buff.position(buffPos);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a ByteBuffer containing this boat status message
|
* @return a ByteBuffer containing this boat status message
|
||||||
*/
|
*/
|
||||||
public ByteBuffer getByteBuffer(){
|
public ByteBuffer getByteBuffer(){
|
||||||
ByteBuffer buff = ByteBuffer.allocate(getSize());
|
|
||||||
int buffPos = 0;
|
|
||||||
|
|
||||||
// Source ID, 4 bytes
|
// Source ID, 4 bytes
|
||||||
buff.put(ByteBuffer.allocate(4).putInt((int) sourceId).array());
|
putInBuffer(Message.intToByteArray(sourceId, 4), 4);
|
||||||
buffPos += 4;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Boat Status, 1 byte
|
// Boat Status, 1 byte
|
||||||
buff.put(ByteBuffer.allocate(1).put((byte) (boatStatus.getCode() & 0xff)).array());
|
putInBuffer(ByteBuffer.allocate(1).put((byte) (boatStatus.getCode() & 0xff)).array(), 1);
|
||||||
buffPos += 1;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Leg number, 1 byte
|
// Leg number, 1 byte
|
||||||
buff.put(ByteBuffer.allocate(1).put((byte) (legNumber & 0xff)).array());
|
putInBuffer(ByteBuffer.allocate(1).put((byte) (legNumber & 0xff)).array(), 1);
|
||||||
buffPos += 1;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Number of penalties awarded, 1 byte
|
// Number of penalties awarded, 1 byte
|
||||||
buff.put(ByteBuffer.allocate(1).put((byte) (numberPenaltiesAwarded & 0xff)).array());
|
putInBuffer(ByteBuffer.allocate(1).put((byte) (numberPenaltiesAwarded & 0xff)).array(), 1);
|
||||||
buffPos += 1;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Number of penalties served, 1 byte
|
// Number of penalties served, 1 byte
|
||||||
buff.put(ByteBuffer.allocate(1).put((byte) (numberPenaltiesServed & 0xff)).array());
|
putInBuffer(ByteBuffer.allocate(1).put((byte) (numberPenaltiesServed & 0xff)).array(), 1);
|
||||||
buffPos += 1;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Estimated time at next mark, 6 bytes
|
// Estimated time at next mark, 6 bytes
|
||||||
buff.put(ByteBuffer.allocate(6).putInt((int) estimatedTimeAtNextMark).array());
|
putInBuffer(Message.intToByteArray((int) estimatedTimeAtNextMark, 6),6);
|
||||||
buffPos += 6;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
// Estimated time at finish, 6 bytes
|
// Estimated time at finish, 6 bytes
|
||||||
buff.put(ByteBuffer.allocate(6).putInt((int) estimatedTimeAtFinish).array());
|
putInBuffer(Message.intToByteArray((int) estimatedTimeAtFinish, 6), 6);
|
||||||
buffPos += 6;
|
|
||||||
buff.position(buffPos);
|
|
||||||
|
|
||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
package seng302.server.messages;
|
package seng302.server.messages;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
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;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
@@ -144,7 +140,7 @@ public abstract class Message {
|
|||||||
* @param size number of bytes
|
* @param size number of bytes
|
||||||
*/
|
*/
|
||||||
void putBytes(ByteBuffer bytes, int size){
|
void putBytes(ByteBuffer bytes, int size){
|
||||||
buffer.put(bytes);
|
buffer.put(bytes.array());
|
||||||
moveBufferPositionBy(size);
|
moveBufferPositionBy(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +181,6 @@ 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];
|
||||||
|
|
||||||
@@ -209,5 +204,4 @@ public abstract class Message {
|
|||||||
data[right] = (byte) (temp & 0xff);
|
data[right] = (byte) (temp & 0xff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,16 @@ public class Boat {
|
|||||||
private double lng;
|
private double lng;
|
||||||
private double speed; // in mm/sec
|
private double speed; // in mm/sec
|
||||||
private String boatName, shortName, shorterName;
|
private String boatName, shortName, shorterName;
|
||||||
|
private boolean isFinished;
|
||||||
|
private long estimatedTimeTillFinish;
|
||||||
|
|
||||||
private Corner lastPassedCorner, headingCorner;
|
private Corner lastPassedCorner, headingCorner;
|
||||||
|
|
||||||
public Boat(int sourceID, String boatName) {
|
public Boat(int sourceID, String boatName) {
|
||||||
this.sourceID = sourceID;
|
this.sourceID = sourceID;
|
||||||
this.boatName = boatName;
|
this.boatName = boatName;
|
||||||
|
this.isFinished = false;
|
||||||
|
estimatedTimeTillFinish = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,4 +110,16 @@ public class Boat {
|
|||||||
public void setHeadingCorner(Corner headingCorner) {
|
public void setHeadingCorner(Corner headingCorner) {
|
||||||
this.headingCorner = headingCorner;
|
this.headingCorner = headingCorner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isFinished() {
|
||||||
|
return isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFinished(boolean finished) {
|
||||||
|
isFinished = finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getEstimatedTimeTillFinish(){
|
||||||
|
return (long) (-getSpeed()) + System.currentTimeMillis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
private List<Corner> course;
|
private List<Corner> course;
|
||||||
private List<Boat> boats;
|
private List<Boat> boats;
|
||||||
private long lapse;
|
private long lapse;
|
||||||
|
private boolean isRaceStarted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a simulator instance with given time lapse.
|
* Creates a simulator instance with given time lapse.
|
||||||
@@ -24,6 +25,7 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
course = rp.getCourse();
|
course = rp.getCourse();
|
||||||
boats = rp.getBoats();
|
boats = rp.getBoats();
|
||||||
this.lapse = lapse;
|
this.lapse = lapse;
|
||||||
|
isRaceStarted = false;
|
||||||
|
|
||||||
setLegs();
|
setLegs();
|
||||||
|
|
||||||
@@ -45,26 +47,30 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
int numOfFinishedBoats = 0;
|
int numOfFinishedBoats = 0;
|
||||||
|
|
||||||
while (numOfFinishedBoats < boats.size()) {
|
while (numOfFinishedBoats < boats.size()) {
|
||||||
|
|
||||||
|
// if race has started, then boat should start to move.
|
||||||
|
if (isRaceStarted) {
|
||||||
for (Boat boat : boats) {
|
for (Boat boat : boats) {
|
||||||
numOfFinishedBoats += moveBoat(boat, lapse);
|
numOfFinishedBoats += moveBoat(boat, lapse);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//System.out.println(boats.get(0));
|
//System.out.println(boats.get(0));
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers(boats);
|
notifyObservers(boats);
|
||||||
|
|
||||||
// sleep for 1 second.
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(lapse);
|
Thread.sleep(lapse);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("[SERVER] Race simulator has been terminated");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a boat with given time duration.
|
* Moves a boat with given time duration.
|
||||||
*
|
|
||||||
* @param boat the boat to be moved
|
* @param boat the boat to be moved
|
||||||
* @param duration the moving duration in milliseconds
|
* @param duration the moving duration in milliseconds
|
||||||
* @return 1 if the boat has reached the final line, otherwise return 0
|
* @return 1 if the boat has reached the final line, otherwise return 0
|
||||||
@@ -85,7 +91,10 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
boat.setHeadingCorner(boat.getLastPassedCorner().getNextCorner());
|
boat.setHeadingCorner(boat.getLastPassedCorner().getNextCorner());
|
||||||
|
|
||||||
// heading corner == null means boat has reached the final mark
|
// heading corner == null means boat has reached the final mark
|
||||||
if (boat.getHeadingCorner() == null) return 1;
|
if (boat.getHeadingCorner() == null) {
|
||||||
|
boat.setFinished(true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// move compensate distance for the mark just passed
|
// move compensate distance for the mark just passed
|
||||||
Position pos = GeoUtility.getGeoCoordinate(
|
Position pos = GeoUtility.getGeoCoordinate(
|
||||||
@@ -126,4 +135,7 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
return boats;
|
return boats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRaceStarted(boolean raceStarted) {
|
||||||
|
isRaceStarted = raceStarted;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,20 +7,21 @@
|
|||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<AnchorPane fx:id="contentPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.Controller">
|
<AnchorPane fx:id="contentPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.Controller">
|
||||||
<children>
|
<children>
|
||||||
<GridPane nodeOrientation="LEFT_TO_RIGHT" prefHeight="1080.0" prefWidth="1920.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<GridPane nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="170.0" minHeight="170.0" prefHeight="170.0" vgrow="SOMETIMES" />
|
<RowConstraints percentHeight="10.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="52.0" minHeight="52.0" prefHeight="52.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="52.0" minHeight="52.0" prefHeight="52.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="102.0" minHeight="102.0" prefHeight="102.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="0.0" percentHeight="8.0" prefHeight="0.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="28.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="365.0" minHeight="365.0" prefHeight="365.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="55.0" minHeight="55.0" percentHeight="5.0" prefHeight="55.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="93.0" minHeight="93.0" prefHeight="93.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="0.0" minHeight="0.0" percentHeight="23.0" prefHeight="0.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="262.0" minHeight="262.0" prefHeight="262.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="93.0" minHeight="72.0" prefHeight="72.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="283.0" minHeight="262.0" prefHeight="283.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="CENTER" text="Welcome to Race Vision" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
|
<Label alignment="CENTER" text="Welcome to Race Vision" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
|
||||||
@@ -38,24 +39,25 @@
|
|||||||
<Font size="28.0" />
|
<Font size="28.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="timeTillLive" text="0:00 minutes" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3">
|
<Label fx:id="timeTillLive" text="0:00 minutes" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="4">
|
||||||
<font>
|
<font>
|
||||||
<Font size="27.0" />
|
<Font size="27.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="3" />
|
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
||||||
<Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="6" GridPane.valignment="TOP" />
|
<Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="TOP" />
|
||||||
<TableView fx:id="teamList" maxWidth="500.0" prefHeight="200.0" prefWidth="200.0" GridPane.halignment="CENTER" GridPane.rowIndex="4">
|
<TableView fx:id="teamList" maxWidth="500.0" prefHeight="200.0" prefWidth="210.0" GridPane.halignment="CENTER" GridPane.rowIndex="5">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn fx:id="boatNameCol" editable="false" prefWidth="250.0" sortable="false" text="Boat Name" />
|
<TableColumn fx:id="posCol" editable="false" maxWidth="74.0" minWidth="74.0" prefWidth="74.0" resizable="false" sortable="false" text="Position" />
|
||||||
<TableColumn fx:id="shortNameCol" editable="false" prefWidth="125.0" sortable="false" text="Short Name" />
|
<TableColumn fx:id="boatNameCol" editable="false" maxWidth="171.0" minWidth="171.0" prefWidth="171.0" resizable="false" sortable="false" text="Boat Name" />
|
||||||
<TableColumn fx:id="countryCol" editable="false" prefWidth="125.0" sortable="false" text="Country" />
|
<TableColumn fx:id="shortNameCol" editable="false" maxWidth="107.0" minWidth="107.0" prefWidth="107.0" resizable="false" sortable="false" text="Short Name" />
|
||||||
|
<TableColumn fx:id="countryCol" editable="false" maxWidth="147.0" minWidth="147.0" prefWidth="147.0" resizable="false" sortable="false" text="Country" />
|
||||||
</columns>
|
</columns>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets />
|
<Insets />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</TableView>
|
</TableView>
|
||||||
<Label text="*Team position in table do not correspond to race position" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="TOP" />
|
<Label fx:id="realTime" text="Local time" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
<Label layoutX="10.0" layoutY="499.0" text="Annotations" />
|
<Label layoutX="10.0" layoutY="499.0" text="Annotations" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<AnchorPane fx:id="contentAnchorPane" prefHeight="960.0" prefWidth="1280.0" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2147483647" GridPane.valignment="TOP">
|
<AnchorPane fx:id="contentAnchorPane" prefHeight="960.0" prefWidth="1280.0" style="-fx-background-color: skyblue;" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2147483647" GridPane.valignment="TOP">
|
||||||
<children>
|
<children>
|
||||||
<fx:include fx:id="includedCanvas" source="CanvasView.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
<fx:include fx:id="includedCanvas" source="CanvasView.fxml" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
</children></AnchorPane>
|
</children></AnchorPane>
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
package seng302;
|
//package seng302;
|
||||||
|
//
|
||||||
import org.junit.Test;
|
//import org.junit.Test;
|
||||||
import seng302.models.Boat;
|
//import seng302.models.Boat;
|
||||||
|
//
|
||||||
import static org.junit.Assert.assertEquals;
|
//import static org.junit.Assert.assertEquals;
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* Unit test for the Team class.
|
// * Unit test for the Team class.
|
||||||
*/
|
// */
|
||||||
public class BoatTest {
|
//public class BoatTest {
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
public void testBoatCreation() {
|
// public void testBoatCreation() {
|
||||||
Boat boat1 = new Boat("Team 1");
|
// Boat boat1 = new Boat("Team 1");
|
||||||
assertEquals(boat1.getTeamName(), "Team 1");
|
// assertEquals(boat1.getTeamName(), "Team 1");
|
||||||
assertEquals(boat1.getVelocity(), (double) 10.0, 1e-15);
|
// assertEquals(boat1.getVelocity(), (double) 10.0, 1e-15);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
public void testChangeTeamName() {
|
// public void testChangeTeamName() {
|
||||||
Boat boat1 = new Boat("Team 1");
|
// Boat boat1 = new Boat("Team 1");
|
||||||
boat1.setTeamName("Team 2");
|
// boat1.setTeamName("Team 2");
|
||||||
assertEquals(boat1.getTeamName(), "Team 2");
|
// assertEquals(boat1.getTeamName(), "Team 2");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
public void testSetVelocity() {
|
// public void testSetVelocity() {
|
||||||
Boat boat1 = new Boat("Team 1", 29.0, "", 100);
|
// Boat boat1 = new Boat("Team 1", 29.0, "", 100);
|
||||||
assertEquals(boat1.getVelocity(), (double) 29.0, 1e-15);
|
// assertEquals(boat1.getVelocity(), (double) 29.0, 1e-15);
|
||||||
|
//
|
||||||
boat1.setVelocity(12.0);
|
// boat1.setVelocity(12.0);
|
||||||
assertEquals(boat1.getVelocity(), (double)12.0, 1e-15);
|
// assertEquals(boat1.getVelocity(), (double)12.0, 1e-15);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package seng302;
|
package seng302;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.models.Boat;
|
|
||||||
import seng302.models.Event;
|
import seng302.models.Event;
|
||||||
|
import seng302.models.Yacht;
|
||||||
import seng302.models.mark.SingleMark;
|
import seng302.models.mark.SingleMark;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -15,14 +15,14 @@ public class EventTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getTimeString() throws Exception {
|
public void getTimeString() throws Exception {
|
||||||
Boat boat = new Boat("testBoat");
|
Yacht boat = new Yacht("testBoat");
|
||||||
Event event = new Event(1231242.2, boat, new SingleMark("mark1"), new SingleMark("mark2"), 0);
|
Event event = new Event(1231242.2, boat, new SingleMark("mark1"), new SingleMark("mark2"), 0);
|
||||||
assertEquals("20:31:242", event.getTimeString());
|
assertEquals("20:31:242", event.getTimeString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBoatHeading() throws Exception {
|
public void testBoatHeading() throws Exception {
|
||||||
Boat boat = new Boat("testBoat");
|
Yacht boat = new Yacht("testBoat");
|
||||||
Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1, 1), new SingleMark("mark2", 121.9,99.2, 2), 0);
|
Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1, 1), new SingleMark("mark2", 121.9,99.2, 2), 0);
|
||||||
|
|
||||||
assertEquals(event.getBoatHeading(), 228.0266137055349, 1e-15);
|
assertEquals(event.getBoatHeading(), 228.0266137055349, 1e-15);
|
||||||
@@ -30,7 +30,7 @@ public class EventTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDistanceBetweenMarks() throws Exception {
|
public void testDistanceBetweenMarks() throws Exception {
|
||||||
Boat boat = new Boat("testBoat");
|
Yacht boat = new Yacht("testBoat");
|
||||||
Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1, 1), new SingleMark("mark2", 121.9,99.2, 2), 0);
|
Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1, 1), new SingleMark("mark2", 121.9,99.2, 2), 0);
|
||||||
|
|
||||||
assertEquals(event.getDistanceBetweenMarks(), 339059.653830461, 1e-15);
|
assertEquals(event.getDistanceBetweenMarks(), 339059.653830461, 1e-15);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package seng302;
|
package seng302;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.models.Boat;
|
|
||||||
import seng302.models.Race;
|
import seng302.models.Race;
|
||||||
|
import seng302.models.Yacht;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ public class RaceTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testAddingBoatsToRace() {
|
public void testAddingBoatsToRace() {
|
||||||
Boat boat1 = new Boat("Team 1");
|
Yacht boat1 = new Yacht("Team 1");
|
||||||
Boat boat2 = new Boat("Team 2");
|
Yacht boat2 = new Yacht("Team 2");
|
||||||
|
|
||||||
Race race = new Race();
|
Race race = new Race();
|
||||||
race.addBoat(boat1);
|
race.addBoat(boat1);
|
||||||
@@ -29,8 +29,8 @@ public class RaceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetShuffledBoats(){
|
public void testGetShuffledBoats(){
|
||||||
Boat boat1 = new Boat("Team 1");
|
Yacht boat1 = new Yacht("Team 1");
|
||||||
Boat boat2 = new Boat("Team 2");
|
Yacht boat2 = new Yacht("Team 2");
|
||||||
|
|
||||||
Race race = new Race();
|
Race race = new Race();
|
||||||
race.addBoat(boat1);
|
race.addBoat(boat1);
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// TODO: 4/05/17 cir27 - Currently the CI cannot build these tests. Unsure of exact issue but believe it may be a driver issue. Find a way to make tests work.
|
||||||
|
|
||||||
|
//package seng302.models;
|
||||||
|
//
|
||||||
|
//public class BoatGroupTest {
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
package seng302.models;
|
||||||
|
/*
|
||||||
|
* Created by cir27 on 4/05/17.
|
||||||
|
|
||||||
|
public class BoatGroupTest {
|
||||||
|
BoatGroup boatGroup;
|
||||||
|
@Before
|
||||||
|
public void setUp () {
|
||||||
|
Yacht b = new Yacht("TEST", 0.0, "T" ,0);
|
||||||
|
boatGroup = new BoatGroup(b, Color.BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDestinationFirstUseForcesLocationUpdate () {
|
||||||
|
boatGroup.setDestination(10, 10, 90, 0);
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
Assert.assertTrue(10 == bp.getLayoutX());
|
||||||
|
Assert.assertTrue(10 == bp.getLayoutY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDestinationFutureUseDoesntForce () {
|
||||||
|
for (int i = 0; i < 60; i++) {
|
||||||
|
boatGroup.setDestination(200, 200, 90, 0);
|
||||||
|
}
|
||||||
|
boatGroup.setDestination(210, 210, 90, 0);
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
Assert.assertTrue(200 == bp.getLayoutX());
|
||||||
|
Assert.assertTrue(200 == bp.getLayoutY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDestinationUnrealisticMovementForceUpdate () {
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
double xLocation = bp.getLayoutX();
|
||||||
|
double yLocation = bp.getLayoutY();
|
||||||
|
boatGroup.setDestination(xLocation + 500, yLocation + 500, 90, 0);
|
||||||
|
Assert.assertTrue(xLocation + 500 == bp.getLayoutX());
|
||||||
|
Assert.assertTrue(yLocation + 500 == bp.getLayoutY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDestinationUnrealisticNegativeForceUpdate () {
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
double xLocation = bp.getLayoutX();
|
||||||
|
double yLocation = bp.getLayoutY();
|
||||||
|
boatGroup.setDestination(xLocation - 500, yLocation - 500, 90, 0);
|
||||||
|
Assert.assertTrue(xLocation - 500 == bp.getLayoutX());
|
||||||
|
Assert.assertTrue(yLocation - 500 == bp.getLayoutY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updatePositionGeneratesExpectedMovement () {
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
double xLocation = bp.getLayoutX();
|
||||||
|
double yLocation = bp.getLayoutY();
|
||||||
|
int movement = 10;
|
||||||
|
double delay = RaceObject.getExpectedUpdateInterval();
|
||||||
|
double defaultTimePeriod = 1000 / 60;
|
||||||
|
double expectedMovement = movement / delay * defaultTimePeriod;
|
||||||
|
for (int i = 0; i < 60; i++) {
|
||||||
|
boatGroup.setDestination(xLocation, yLocation, 90, 0);
|
||||||
|
}
|
||||||
|
boatGroup.setDestination(xLocation + 10, yLocation + 10, 90, 0);
|
||||||
|
boatGroup.updatePosition(1000/60);
|
||||||
|
Assert.assertEquals(expectedMovement, bp.getLayoutX() - xLocation, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void correctRaceID () {
|
||||||
|
Assert.assertTrue(boatGroup.hasRaceId(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void incorrectRaceID () {
|
||||||
|
Assert.assertTrue(!boatGroup.hasRaceId(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void nothingOnWrongId () {
|
||||||
|
Polygon bp = (Polygon) boatGroup.getChildren().get(2);
|
||||||
|
double originalX = bp.getLayoutX();
|
||||||
|
double originalY = bp.getLayoutY();
|
||||||
|
boatGroup.setDestination(10, 10, 90, 12);
|
||||||
|
Assert.assertTrue(originalX == bp.getLayoutX());
|
||||||
|
Assert.assertTrue(originalY == bp.getLayoutY());
|
||||||
|
}
|
||||||
|
}*/
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// TODO: 4/05/17 cir27 - Currently the CI cannot build these tests. Unsure of exact issue but believe it may be a driver issue. Find a way to make tests work.
|
||||||
|
//
|
||||||
|
//package seng302.models;
|
||||||
|
//
|
||||||
|
//public class MarkGroupTest {
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
package seng302.models;
|
||||||
|
/*
|
||||||
|
import javafx.scene.shape.Circle;
|
||||||
|
import seng302.*;
|
||||||
|
import javafx.geometry.Point2D;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.models.mark.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by cir27 on 4/05/17.
|
||||||
|
*/
|
||||||
|
//public class MarkGroupTest {
|
||||||
|
// private MarkGroup gateMG;
|
||||||
|
// private MarkGroup singleMG;
|
||||||
|
//
|
||||||
|
// @Before
|
||||||
|
// public void setUp () {
|
||||||
|
// Mark single = new SingleMark("SM", 0, 0 , 0);
|
||||||
|
// Mark gate = new GateMark(
|
||||||
|
// "GM",
|
||||||
|
// MarkType.OPEN_GATE,
|
||||||
|
// new SingleMark("GM1", 0, 0, 1),
|
||||||
|
// new SingleMark("GM2", 0, 0, 2),
|
||||||
|
// 0,
|
||||||
|
// 0);
|
||||||
|
// gateMG = new MarkGroup(gate, new Point2D(10, 10), new Point2D(20, 20));
|
||||||
|
// singleMG = new MarkGroup(single, new Point2D(0, 0));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void hasIDSingle () {
|
||||||
|
// Assert.assertTrue(singleMG.hasRaceId(0));
|
||||||
|
// Assert.assertTrue(!singleMG.hasRaceId(100,12));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void hasIdGate () {
|
||||||
|
// Assert.assertTrue(gateMG.hasRaceId(1));
|
||||||
|
// Assert.assertTrue(gateMG.hasRaceId(2));
|
||||||
|
// Assert.assertTrue(!gateMG.hasRaceId(100,12));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void nothingOnWrongId () {
|
||||||
|
// double originalX = singleMG.getChildren().get(0).getLayoutX();
|
||||||
|
// double originalY = singleMG.getChildren().get(0).getLayoutY();
|
||||||
|
// singleMG.setDestination(10, 10, 0, 4);
|
||||||
|
// singleMG.updatePosition(400);
|
||||||
|
// Assert.assertTrue(originalX == singleMG.getChildren().get(0).getLayoutX());
|
||||||
|
// Assert.assertTrue(originalY == singleMG.getChildren().get(0).getLayoutY());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void correctMovementCorrectIdSingle () {
|
||||||
|
// double originalX = singleMG.getChildren().get(0).getLayoutX();
|
||||||
|
// double originalY = singleMG.getChildren().get(0).getLayoutY();
|
||||||
|
// long timeinterval = 1000/60;
|
||||||
|
// double expectedChange = 10 / 200 * timeinterval;
|
||||||
|
// singleMG.setDestination(originalX + 10, originalY + 10, 0, 0);
|
||||||
|
// singleMG.updatePosition(timeinterval);
|
||||||
|
// Assert.assertTrue(originalX + expectedChange == singleMG.getChildren().get(0).getLayoutX());
|
||||||
|
// Assert.assertTrue(originalY + expectedChange == singleMG.getChildren().get(0).getLayoutY());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// public void correctMovementCorrectIDGate () {
|
||||||
|
// double originalX1 = gateMG.getChildren().get(0).getLayoutX();
|
||||||
|
// double originalY1 = gateMG.getChildren().get(0).getLayoutY();
|
||||||
|
// double originalX2 = gateMG.getChildren().get(1).getLayoutX();
|
||||||
|
// double originalY2 = gateMG.getChildren().get(1).getLayoutY();
|
||||||
|
// long timeinterval = 1000/60;
|
||||||
|
// double expectedChange = 10 / 200 * timeinterval;
|
||||||
|
// gateMG.setDestination(originalX1 + 10, originalY1 + 10, 0, 1);
|
||||||
|
// gateMG.setDestination(originalX2 + 10, originalY2 + 10, 0, 2);
|
||||||
|
// gateMG.updatePosition(timeinterval);
|
||||||
|
// Assert.assertTrue(originalX1 + expectedChange == gateMG.getChildren().get(0).getLayoutX());
|
||||||
|
// Assert.assertTrue(originalY1 + expectedChange == gateMG.getChildren().get(0).getLayoutY());
|
||||||
|
// Assert.assertTrue(originalX2 + expectedChange == gateMG.getChildren().get(1).getLayoutX());
|
||||||
|
// Assert.assertTrue(originalY2 + expectedChange == gateMG.getChildren().get(1).getLayoutY());
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@@ -1,35 +1,36 @@
|
|||||||
package seng302.models.parsers;
|
//package seng302.models.parsers;
|
||||||
|
//
|
||||||
import org.junit.Before;
|
//import org.junit.Before;
|
||||||
import org.junit.Test;
|
//import org.junit.Test;
|
||||||
import seng302.models.Boat;
|
//import seng302.models.Boat;
|
||||||
|
//import seng302.models.Yacht;
|
||||||
import java.util.ArrayList;
|
//
|
||||||
|
//import java.util.ArrayList;
|
||||||
import static org.junit.Assert.*;
|
//
|
||||||
|
//import static org.junit.Assert.*;
|
||||||
/**
|
//
|
||||||
* Created by Haoming on 18/03/17.
|
///**
|
||||||
*/
|
// * Created by Haoming on 18/03/17.
|
||||||
public class TeamsParserTest {
|
// */
|
||||||
|
//public class TeamsParserTest {
|
||||||
private TeamsParser tp;
|
//
|
||||||
@Before
|
// private TeamsParser tp;
|
||||||
public void readFile() {
|
// @Before
|
||||||
tp = new TeamsParser("/config/teams.xml");
|
// public void readFile() {
|
||||||
}
|
// tp = new TeamsParser("/config/teams.xml");
|
||||||
|
// }
|
||||||
@Test
|
//
|
||||||
public void getBoats() throws Exception {
|
// @Test
|
||||||
ArrayList<Boat> boats = tp.getBoats();
|
// public void getBoats() throws Exception {
|
||||||
|
// ArrayList<Yacht> boats = tp.getBoats();
|
||||||
assertEquals(6, boats.size(), 1e-10);
|
//
|
||||||
|
// assertEquals(6, boats.size(), 1e-10);
|
||||||
assertEquals("Oracle Team USA", boats.get(0).getTeamName());
|
//
|
||||||
//assertEquals(30.9, boats.get(0).getVelocity(), 1e-10);
|
// assertEquals("Oracle Team USA", boats.get(0).getBoatName());
|
||||||
|
// //assertEquals(30.9, boats.get(0).getVelocity(), 1e-10);
|
||||||
assertEquals("Groupama Team France", boats.get(5).getTeamName());
|
//
|
||||||
//assertEquals(45.6, boats.get(5).getVelocity(), 1e-10);
|
// assertEquals("Groupama Team France", boats.get(5).getBoatName());
|
||||||
}
|
// //assertEquals(45.6, boats.get(5).getVelocity(), 1e-10);
|
||||||
|
// }
|
||||||
}
|
//
|
||||||
|
//}
|
||||||
Reference in New Issue
Block a user