mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'develop' of https://eng-git.canterbury.ac.nz/seng302-2017/team-13 into develop
# Conflicts: # src/main/java/seng302/App.java # src/main/java/seng302/controllers/Controller.java
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
package seng302;
|
package seng302;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import seng302.controllers.Controller;
|
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.parsers.StreamParser;
|
||||||
import seng302.models.parsers.StreamReceiver;
|
import seng302.models.parsers.StreamReceiver;
|
||||||
import seng302.server.ServerThread;
|
import seng302.server.ServerThread;
|
||||||
@@ -14,31 +14,47 @@ public class App extends Application
|
|||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception {
|
public void start(Stage primaryStage) throws Exception {
|
||||||
// Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
|
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/MainView.fxml"));
|
|
||||||
primaryStage.setTitle("RaceVision");
|
primaryStage.setTitle("RaceVision");
|
||||||
primaryStage.setScene(new Scene(loader.load()));
|
primaryStage.setScene(new Scene(root));
|
||||||
((Controller) loader.getController()).setStage(primaryStage);
|
primaryStage.setMaximized(true);
|
||||||
|
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
|
primaryStage.setOnCloseRequest(e -> {
|
||||||
|
Platform.exit();
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 == 3 && args[0].equals("-server")){
|
||||||
sr = new StreamReceiver("localhost", 8085, "RaceStream");
|
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", 8085, "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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"RaceStream");
|
sr = new StreamReceiver("localhost", 8085, "RaceStream");
|
||||||
// sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
|
||||||
// sr = new StreamReceiver("localhost", 8085, "RaceStream");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.start();
|
sr.start();
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (Mark m : raceViewController.getRace().getCourse()) {
|
for (Mark m : raceViewController.getRace().getCourse()) {
|
||||||
System.out.println(m.getName());
|
//System.out.println(m.getName());
|
||||||
}
|
}
|
||||||
//timer.start();
|
//timer.start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,9 @@ 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;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
@@ -16,21 +14,17 @@ 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 javafx.stage.Stage;
|
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.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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,26 +35,25 @@ 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
|
@FXML
|
||||||
private Label realTime;
|
private Label realTime;
|
||||||
private Stage stage;
|
|
||||||
|
private XMLParser xmlParser;
|
||||||
|
|
||||||
private void setContentPane(String jfxUrl){
|
private void setContentPane(String jfxUrl){
|
||||||
try{
|
try{
|
||||||
contentPane.getChildren().removeAll();
|
contentPane.getChildren().removeAll();
|
||||||
contentPane.getChildren().clear();
|
contentPane.getChildren().clear();
|
||||||
// contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource(jfxUrl));
|
|
||||||
contentPane.getChildren().addAll((Node) loader.load());
|
|
||||||
RaceViewController r = (RaceViewController) loader.getController();
|
|
||||||
//((RaceViewController) loader.getController()).setStage(stage);
|
|
||||||
}
|
}
|
||||||
catch(javafx.fxml.LoadException e){
|
catch(javafx.fxml.LoadException e){
|
||||||
System.err.println(e.getCause());
|
System.err.println(e.getCause());
|
||||||
@@ -82,7 +75,7 @@ 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);
|
realTime.setVisible(true);
|
||||||
timeTillLive.setVisible(true);
|
timeTillLive.setVisible(true);
|
||||||
@@ -108,7 +101,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);
|
||||||
} else {
|
} else {
|
||||||
realTime.setText(StreamParser.getCurrentTimeString());
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
@@ -120,7 +113,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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -137,22 +130,32 @@ public class Controller implements Initializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateTeamList() {
|
private void updateTeamList() {
|
||||||
ObservableList<XMLParser.BoatXMLObject.Boat> data = FXCollections.observableArrayList();
|
ObservableList<Yacht> data = FXCollections.observableArrayList();
|
||||||
teamList.setItems(data);
|
teamList.setItems(data);
|
||||||
boatNameCol.setCellValueFactory(
|
boatNameCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<XMLParser.BoatXMLObject.Boat,String>("BoatName")
|
new PropertyValueFactory<>("boatName")
|
||||||
);
|
);
|
||||||
shortNameCol.setCellValueFactory(
|
shortNameCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<XMLParser.BoatXMLObject.Boat,String>("ShortName")
|
new PropertyValueFactory<>("shortName")
|
||||||
);
|
);
|
||||||
countryCol.setCellValueFactory(
|
countryCol.setCellValueFactory(
|
||||||
new PropertyValueFactory<XMLParser.BoatXMLObject.Boat,String>("Country")
|
new PropertyValueFactory<>("country")
|
||||||
);
|
);
|
||||||
for (XMLParser.BoatXMLObject.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();
|
||||||
public void setStage (Stage stage) {
|
|
||||||
this.stage = stage;
|
// posCol.setSortType(TableColumn.SortType.ASCENDING);
|
||||||
|
// teamList.getSortOrder().add(posCol);
|
||||||
|
// posCol.setSortable(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,21 +307,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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,6 @@ public class Boat {
|
|||||||
private int markLastPast;
|
private int markLastPast;
|
||||||
private String shortName;
|
private String shortName;
|
||||||
private int id;
|
private int id;
|
||||||
// new attributes to boat
|
|
||||||
private int sourceID;
|
|
||||||
private String boatName;
|
|
||||||
private String country;
|
|
||||||
|
|
||||||
public Boat(String teamName) {
|
public Boat(String teamName) {
|
||||||
this.teamName = teamName;
|
this.teamName = teamName;
|
||||||
@@ -49,21 +45,6 @@ public class Boat {
|
|||||||
this.id = id;
|
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
|
* Returns the name of the team sailing the boat
|
||||||
*
|
*
|
||||||
@@ -159,16 +140,4 @@ public class Boat {
|
|||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSourceID() {
|
|
||||||
return sourceID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBoatName() {
|
|
||||||
return boatName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCountry() {
|
|
||||||
return country;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package seng302.models;
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ 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.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;
|
||||||
|
|
||||||
@@ -37,7 +38,8 @@ public class StreamParser extends Thread{
|
|||||||
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<XMLParser.BoatXMLObject.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 double windDirection = 0;
|
||||||
private static String currentTimeString;
|
private static String currentTimeString;
|
||||||
|
|
||||||
@@ -57,7 +59,7 @@ public class StreamParser extends Thread{
|
|||||||
*/
|
*/
|
||||||
public void run(){
|
public void run(){
|
||||||
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) {
|
||||||
@@ -94,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 ();
|
||||||
@@ -181,18 +183,18 @@ public class StreamParser extends Thread{
|
|||||||
currentTimeString = format.format((new Date (currentTime)).getTime());
|
currentTimeString = format.format((new Date (currentTime)).getTime());
|
||||||
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));
|
||||||
@@ -201,17 +203,33 @@ public class StreamParser extends Thread{
|
|||||||
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++){
|
||||||
Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
||||||
String boatStatus = "SourceID: " + boatStatusSourceID;
|
Yacht boat = boats.get((int)(long) boatStatusSourceID);
|
||||||
boatStatus += "\nBoat Status: " + (int)payload[28 + (i * 20)];
|
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
||||||
boatStatus += "\nLegNumber: " + (int)payload[29 + (i * 20)];
|
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
||||||
boatStatus += "\nPenaltiesAwarded: " + (int)payload[29 + (i * 20)];
|
boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
|
||||||
boatStatus += "\nPenaltiesServed: " + (int)payload[30 + (i * 20)];
|
boat.setPenaltiesServed((int)payload[30 + (i * 20)]);
|
||||||
boatStatus += "\nEstTimeAtNextMark: " + bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
Long estTimeAtNextMark = bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
||||||
boatStatus += "\nEstTimeAtFinish: " + bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
|
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
||||||
boatStatuses.add(boatStatus);
|
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);
|
||||||
|
}
|
||||||
|
int pos = 1;
|
||||||
|
for (Yacht yacht : boatsPos.values()) {
|
||||||
|
yacht.setPosition(String.valueOf(pos));
|
||||||
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,11 +496,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<XMLParser.BoatXMLObject.Boat> getBoats() {
|
public static Map<Integer, Yacht> getBoats() {
|
||||||
return boats;
|
return boats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,5 +531,14 @@ public class StreamParser extends Thread{
|
|||||||
public static String getCurrentTimeString() {
|
public static String getCurrentTimeString() {
|
||||||
return currentTimeString;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public class StreamReceiver extends Thread {
|
|||||||
|
|
||||||
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 +45,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 ();
|
||||||
@@ -95,7 +96,6 @@ public class StreamReceiver extends Thread {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
moreBytes = false;
|
moreBytes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +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.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.
|
||||||
@@ -392,9 +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
|
//Competing boats
|
||||||
List<Boat> competingBoats = new ArrayList<>();
|
Map<Integer, Yacht> competingBoats = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a BoatXMLObject.
|
* Constructor for a BoatXMLObject.
|
||||||
@@ -427,10 +430,16 @@ 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")) {
|
if (boat.getBoatType().equals("Yacht")) {
|
||||||
competingBoats.add(boat);
|
competingBoats.put(boat.getSourceID(), boat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//System.out.println(this.getBoats());
|
//System.out.println(this.getBoats());
|
||||||
@@ -446,37 +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 List<Boat> getCompetingBoats() {
|
public Map<Integer, Yacht> getCompetingBoats() {
|
||||||
return competingBoats;
|
return competingBoats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Boat {
|
// public class Boat {
|
||||||
|
//
|
||||||
private String boatType;
|
// private String boatType;
|
||||||
private Integer sourceID;
|
// private Integer sourceID;
|
||||||
private String hullID; //matches HullNum in the XML spec.
|
// private String hullID; //matches HullNum in the XML spec.
|
||||||
private String shortName;
|
// private String shortName;
|
||||||
private String boatName;
|
// private String boatName;
|
||||||
private String country;
|
// private String country;
|
||||||
|
//
|
||||||
Boat(Node boatNode) {
|
// Boat(Node boatNode) {
|
||||||
this.boatType = getNodeAttributeString(boatNode, "Type");
|
// this.boatType = getNodeAttributeString(boatNode, "Type");
|
||||||
this.sourceID = getNodeAttributeInt(boatNode, "SourceID");
|
// this.sourceID = getNodeAttributeInt(boatNode, "SourceID");
|
||||||
this.hullID = getNodeAttributeString(boatNode, "HullNum");
|
// this.hullID = getNodeAttributeString(boatNode, "HullNum");
|
||||||
this.shortName = getNodeAttributeString(boatNode, "ShortName");
|
// this.shortName = getNodeAttributeString(boatNode, "ShortName");
|
||||||
this.boatName = getNodeAttributeString(boatNode, "BoatName");
|
// this.boatName = getNodeAttributeString(boatNode, "BoatName");
|
||||||
this.country = getNodeAttributeString(boatNode, "Country");
|
// this.country = getNodeAttributeString(boatNode, "Country");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
public String getBoatType() { return boatType; }
|
// public String getBoatType() { return boatType; }
|
||||||
public Integer getSourceID() { return sourceID; }
|
// public Integer getSourceID() { return sourceID; }
|
||||||
public String getHullID() { return hullID; }
|
// public String getHullID() { return hullID; }
|
||||||
public String getShortName() { return shortName; }
|
// public String getShortName() { return shortName; }
|
||||||
public String getBoatName() { return boatName; }
|
// public String getBoatName() { return boatName; }
|
||||||
public String getCountry() { return country; }
|
// public String getCountry() { return country; }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,26 +3,22 @@ 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 = 8085;
|
||||||
@@ -30,7 +26,9 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
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);
|
||||||
@@ -48,7 +46,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
raceSimulatorThread.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);
|
||||||
}
|
}
|
||||||
@@ -60,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 {
|
||||||
@@ -82,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;
|
||||||
@@ -128,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,12 +254,37 @@ 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
|
||||||
// TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17
|
// TODO: I don't understand why i need to check server is null or not ... confused - haoming 2/5/17
|
||||||
@@ -269,22 +292,32 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Boat b : (List<Boat>) arg){
|
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){
|
||||||
//e.printStackTrace();
|
e.printStackTrace();
|
||||||
//TODO: add a method in boat to check if a boat has finished the race. - haoming 2/5/17
|
|
||||||
serverLog("Boat " + b.getSourceID() + " finished the race", 1);
|
|
||||||
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,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;
|
||||||
|
|
||||||
@@ -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,14 @@ 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 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,4 +108,12 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
boat.setLng(startLng);
|
boat.setLng(startLng);
|
||||||
boat.setLastPassedCorner(course.get(0));
|
boat.setLastPassedCorner(course.get(0));
|
||||||
boat.setHeadingCorner(course.get(1));
|
boat.setHeadingCorner(course.get(1));
|
||||||
boat.setSpeed(ThreadLocalRandom.current().nextInt(400000, 600000 + 1));
|
boat.setSpeed(ThreadLocalRandom.current().nextInt(40000, 60000 + 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +65,8 @@ public class Simulator extends Observable implements Runnable {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println("[SERVER] Race simulator has been terminated");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,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(
|
||||||
|
|||||||
@@ -7,21 +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="28.0" minHeight="20.0" prefHeight="28.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="28.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="55.0" minHeight="55.0" prefHeight="55.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="55.0" minHeight="55.0" percentHeight="5.0" prefHeight="55.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="318.0" minHeight="318.0" prefHeight="318.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="0.0" minHeight="0.0" percentHeight="23.0" prefHeight="0.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="93.0" minHeight="93.0" prefHeight="93.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="93.0" minHeight="72.0" prefHeight="72.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="262.0" minHeight="262.0" prefHeight="262.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">
|
||||||
@@ -46,17 +46,17 @@
|
|||||||
</Label>
|
</Label>
|
||||||
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
<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="7" 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="5">
|
<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="6" GridPane.valignment="TOP" />
|
|
||||||
<Label fx:id="realTime" text="Local time" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
|
<Label fx:id="realTime" text="Local time" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user