mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'develop' into Issue#4_boat_movement
# Conflicts: # src/main/java/seng302/controllers/Controller.java # src/main/java/seng302/controllers/RaceController.java # src/main/java/seng302/controllers/RaceViewController.java # src/main/java/seng302/models/BoatGroup.java # src/main/java/seng302/models/mark/MarkGroup.java # src/main/java/seng302/models/stream/StreamParser.java # src/test/java/seng302/models/stream/StreamReceiverTest.java
This commit is contained in:
@@ -9,8 +9,8 @@ import seng302.models.stream.StreamParser;
|
|||||||
import seng302.models.stream.StreamReceiver;
|
import seng302.models.stream.StreamReceiver;
|
||||||
import seng302.server.ServerThread;
|
import seng302.server.ServerThread;
|
||||||
|
|
||||||
public class App extends Application
|
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"));
|
||||||
@@ -39,15 +39,15 @@ public class App extends Application
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length == 1 && args[0].equals("-standalone")){
|
if (args.length == 1 && args[0].equals("-standalone")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length == 3 && args[0].equals("-server")){
|
if (args.length == 3 && args[0].equals("-server")) {
|
||||||
|
|
||||||
sr = new StreamReceiver(args[1], Integer.valueOf(args[2]), "RaceStream");
|
sr = new StreamReceiver(args[1], Integer.valueOf(args[2]), "RaceStream");
|
||||||
|
|
||||||
} else if(args.length == 2 && args[0].equals("-server")){
|
} else if (args.length == 2 && args[0].equals("-server")) {
|
||||||
switch (args[1]) {
|
switch (args[1]) {
|
||||||
case "internal":
|
case "internal":
|
||||||
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
@@ -62,7 +62,8 @@ public class App extends Application
|
|||||||
}
|
}
|
||||||
//Change the StreamReceiver in this else block to change the default data source.
|
//Change the StreamReceiver in this else block to change the default data source.
|
||||||
else{
|
else{
|
||||||
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
// sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
|
sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.start();
|
sr.start();
|
||||||
@@ -71,8 +72,6 @@ public class App extends Application
|
|||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,17 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkForCourseChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForCourseChanges() {
|
||||||
|
if (StreamParser.isNewRaceXmlReceived()){
|
||||||
|
gc.setFill(Color.SKYBLUE);
|
||||||
|
gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||||
|
gc.restore();
|
||||||
|
addRaceBorder();
|
||||||
|
canvas.toBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBoatGroup(BoatGroup boatGroup) {
|
private void updateBoatGroup(BoatGroup boatGroup) {
|
||||||
@@ -285,6 +296,8 @@ public class CanvasController {
|
|||||||
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
|
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
|
||||||
*/
|
*/
|
||||||
private void fitMarksToCanvas() {
|
private void fitMarksToCanvas() {
|
||||||
|
//Check is called once to avoid unnecessarily change the course limits once the race is running
|
||||||
|
StreamParser.isNewRaceXmlReceived();
|
||||||
findMinMaxPoint();
|
findMinMaxPoint();
|
||||||
double minLonToMaxLon = scaleRaceExtremities();
|
double minLonToMaxLon = scaleRaceExtremities();
|
||||||
calculateReferencePointLocation(minLonToMaxLon);
|
calculateReferencePointLocation(minLonToMaxLon);
|
||||||
|
|||||||
@@ -1,65 +1,31 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import static seng302.models.stream.StreamParser.boatPositions;
|
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
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.control.Button;
|
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.TableColumn;
|
|
||||||
import javafx.scene.control.TableView;
|
|
||||||
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 seng302.models.Yacht;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import seng302.models.stream.StreamParser;
|
import seng302.models.stream.StreamParser;
|
||||||
|
|
||||||
public class Controller implements Initializable {
|
public class Controller implements Initializable {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane contentPane;
|
private AnchorPane contentPane;
|
||||||
@FXML
|
|
||||||
private Label timeTillLive;
|
|
||||||
@FXML
|
|
||||||
private Button streamButton;
|
|
||||||
@FXML
|
|
||||||
private Button switchToRaceViewButton;
|
|
||||||
@FXML
|
|
||||||
private TableView<Yacht> teamList;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<Yacht, String> boatNameCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<Yacht, String> shortNameCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<Yacht, String> countryCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<Yacht, String> posCol;
|
|
||||||
@FXML
|
|
||||||
private Label realTime;
|
|
||||||
|
|
||||||
private boolean switchedToRaceView = false;
|
private void setContentPane(String jfxUrl) {
|
||||||
|
try {
|
||||||
private void setContentPane(String jfxUrl){
|
|
||||||
try{
|
|
||||||
contentPane.getChildren().removeAll();
|
contentPane.getChildren().removeAll();
|
||||||
contentPane.getChildren().clear();
|
contentPane.getChildren().clear();
|
||||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
contentPane.getChildren()
|
||||||
}
|
.addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
||||||
catch(javafx.fxml.LoadException e){
|
} catch (javafx.fxml.LoadException e) {
|
||||||
System.err.println(e.getCause());
|
System.err.println(e.getCause());
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch(IOException e){
|
|
||||||
System.err.println(e);
|
System.err.println(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,94 +33,7 @@ public class Controller implements Initializable {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
teamList.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
setContentPane("/views/StartScreenView.fxml");
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Running a timer to update the livestream status on welcome screen. Update interval is 1 second.
|
|
||||||
*/
|
|
||||||
public void startStream() {
|
|
||||||
if (StreamParser.isStreamStatus()) {
|
|
||||||
streamButton.setVisible(false);
|
|
||||||
realTime.setVisible(true);
|
|
||||||
timeTillLive.setVisible(true);
|
|
||||||
timeTillLive.setTextFill(Color.GREEN);
|
|
||||||
timeTillLive.setText("Connecting...");
|
|
||||||
Timer timer = new Timer();
|
|
||||||
timer.scheduleAtFixedRate(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
if (StreamParser.isRaceStarted()) {
|
|
||||||
if (!switchedToRaceView) {
|
|
||||||
switchToRaceView();
|
|
||||||
}
|
|
||||||
timer.cancel();
|
|
||||||
}
|
|
||||||
if (StreamParser.isRaceFinished()) {
|
|
||||||
realTime.setText(StreamParser.getCurrentTimeString());
|
|
||||||
timeTillLive.setTextFill(Color.RED);
|
|
||||||
timeTillLive.setText("Race finished! Waiting for new race...");
|
|
||||||
switchToRaceViewButton.setDisable(true);
|
|
||||||
} else if (StreamParser.getTimeSinceStart() > 0) {
|
|
||||||
realTime.setText(StreamParser.getCurrentTimeString());
|
|
||||||
updateTeamList();
|
|
||||||
timeTillLive.setTextFill(Color.RED);
|
|
||||||
switchToRaceViewButton.setDisable(false);
|
|
||||||
String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60);
|
|
||||||
String timerSecond = Long.toString(StreamParser.getTimeSinceStart() % 60);
|
|
||||||
if (timerSecond.length() == 1) {
|
|
||||||
timerSecond = "0" + timerSecond;
|
|
||||||
}
|
|
||||||
String timerString = "-" + timerMinute + ":" + timerSecond;
|
|
||||||
timeTillLive.setText(timerString);
|
|
||||||
} else {
|
|
||||||
realTime.setText(StreamParser.getCurrentTimeString());
|
|
||||||
updateTeamList();
|
|
||||||
timeTillLive.setTextFill(Color.BLACK);
|
|
||||||
switchToRaceViewButton.setDisable(false);
|
|
||||||
String timerMinute = Long.toString(-1 * StreamParser.getTimeSinceStart() / 60);
|
|
||||||
String timerSecond = Long.toString(-1 * StreamParser.getTimeSinceStart() % 60);
|
|
||||||
if (timerSecond.length() == 1) {
|
|
||||||
timerSecond = "0" + timerSecond;
|
|
||||||
}
|
|
||||||
String timerString = timerMinute + ":" + timerSecond;
|
|
||||||
timeTillLive.setText(timerString);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, 0, 1000);
|
|
||||||
} else {
|
|
||||||
timeTillLive.setText("Stream not available.");
|
|
||||||
timeTillLive.setTextFill(Color.RED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchToRaceView() {
|
|
||||||
switchedToRaceView = true;
|
|
||||||
setContentPane("/views/RaceView.fxml");
|
|
||||||
StreamParser.boatPositions.clear();
|
StreamParser.boatPositions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTeamList() {
|
|
||||||
ObservableList<Yacht> data = FXCollections.observableArrayList();
|
|
||||||
|
|
||||||
teamList.setItems(data);
|
|
||||||
|
|
||||||
boatNameCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("boatName")
|
|
||||||
);
|
|
||||||
shortNameCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("shortName")
|
|
||||||
);
|
|
||||||
countryCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("country")
|
|
||||||
);
|
|
||||||
posCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("position")
|
|
||||||
);
|
|
||||||
|
|
||||||
data.addAll(StreamParser.getBoatsPos().values());
|
|
||||||
teamList.refresh();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
import javafx.scene.control.Slider;
|
import javafx.scene.control.Slider;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
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.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
@@ -24,9 +25,11 @@ import seng302.controllers.annotations.Annotation;
|
|||||||
import seng302.controllers.annotations.ImportantAnnotationController;
|
import seng302.controllers.annotations.ImportantAnnotationController;
|
||||||
import seng302.controllers.annotations.ImportantAnnotationDelegate;
|
import seng302.controllers.annotations.ImportantAnnotationDelegate;
|
||||||
import seng302.controllers.annotations.ImportantAnnotationsState;
|
import seng302.controllers.annotations.ImportantAnnotationsState;
|
||||||
import seng302.models.BoatGroup;
|
import seng302.models.*;
|
||||||
import seng302.models.Yacht;
|
import seng302.models.parsers.StreamParser;
|
||||||
import seng302.models.stream.StreamParser;
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ptg19 on 29/03/17.
|
* Created by ptg19 on 29/03/17.
|
||||||
@@ -48,23 +51,36 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private Button selectAnnotationBtn;
|
private Button selectAnnotationBtn;
|
||||||
@FXML
|
@FXML
|
||||||
|
private ComboBox boatSelectionComboBox;
|
||||||
|
@FXML
|
||||||
private CanvasController includedCanvasController;
|
private CanvasController includedCanvasController;
|
||||||
|
|
||||||
|
private ArrayList<Yacht> startingBoats = new ArrayList<>();
|
||||||
private boolean displayFps;
|
private boolean displayFps;
|
||||||
private Timeline timerTimeline;
|
private Timeline timerTimeline;
|
||||||
|
private Race race;
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
|
||||||
private ImportantAnnotationsState importantAnnotations;
|
private ImportantAnnotationsState importantAnnotations;
|
||||||
|
private Yacht selectedBoat;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
importantAnnotations = new ImportantAnnotationsState();
|
importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
|
//Initialise race controller
|
||||||
|
RaceController raceController = new RaceController();
|
||||||
|
raceController.initializeRace();
|
||||||
|
race = raceController.getRace();
|
||||||
|
|
||||||
|
startingBoats = new ArrayList<>(Arrays.asList(race.getBoats()));
|
||||||
|
|
||||||
includedCanvasController.setup(this);
|
includedCanvasController.setup(this);
|
||||||
includedCanvasController.initializeCanvas();
|
includedCanvasController.initializeCanvas();
|
||||||
initializeTimer();
|
initializeUpdateTimer();
|
||||||
initializeSettings();
|
initialiseFPSCheckBox();
|
||||||
initialiseWindDirection();
|
initialiseAnnotationSlider();
|
||||||
initialisePositionVBox();
|
initialiseBoatSelectionComboBox();
|
||||||
includedCanvasController.timer.start();
|
includedCanvasController.timer.start();
|
||||||
|
|
||||||
selectAnnotationBtn.setOnAction(event -> {
|
selectAnnotationBtn.setOnAction(event -> {
|
||||||
@@ -74,7 +90,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The important annotations have been changed, update this view
|
* The important annotations have been changed, update this view
|
||||||
*
|
|
||||||
* @param importantAnnotationsState The current state of the selected annotations
|
* @param importantAnnotationsState The current state of the selected annotations
|
||||||
*/
|
*/
|
||||||
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) {
|
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) {
|
||||||
@@ -112,18 +127,14 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeSettings() {
|
|
||||||
|
private void initialiseFPSCheckBox() {
|
||||||
displayFps = true;
|
displayFps = true;
|
||||||
|
toggleFps.selectedProperty().addListener(
|
||||||
|
(observable, oldValue, newValue) -> displayFps = !displayFps);
|
||||||
|
}
|
||||||
|
|
||||||
toggleFps.selectedProperty().addListener(new ChangeListener<Boolean>() {
|
private void initialiseAnnotationSlider() {
|
||||||
@Override
|
|
||||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue,
|
|
||||||
Boolean newValue) {
|
|
||||||
displayFps = !displayFps;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//SLIDER STUFF BELOW
|
|
||||||
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(Double n) {
|
public String toString(Double n) {
|
||||||
@@ -131,12 +142,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
if (n == 1) {
|
if (n == 1) {
|
||||||
return "Low";
|
|
||||||
}
|
|
||||||
if (n == 2) {
|
|
||||||
return "Important";
|
return "Important";
|
||||||
}
|
}
|
||||||
if (n == 3) {
|
if (n == 2) {
|
||||||
return "All";
|
return "All";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,15 +156,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
switch (s) {
|
switch (s) {
|
||||||
case "None":
|
case "None":
|
||||||
return 0d;
|
return 0d;
|
||||||
case "Low":
|
|
||||||
return 1d;
|
|
||||||
case "Important":
|
case "Important":
|
||||||
return 2d;
|
return 1d;
|
||||||
case "All":
|
case "All":
|
||||||
return 3d;
|
return 2d;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 3d;
|
return 2d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -164,22 +170,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
annotationSlider.valueProperty().addListener((obs, oldval, newVal) ->
|
annotationSlider.valueProperty().addListener((obs, oldval, newVal) ->
|
||||||
setAnnotations((int) annotationSlider.getValue()));
|
setAnnotations((int) annotationSlider.getValue()));
|
||||||
|
|
||||||
annotationSlider.setValue(3);
|
annotationSlider.setValue(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeTimer() {
|
|
||||||
|
/**
|
||||||
|
* Initalises a timer which updates elements of the RaceView such as wind direction, boat
|
||||||
|
* orderings etc.. which are dependent on the info from the stream parser constantly.
|
||||||
|
* Updates of each of these attributes are called ONCE EACH SECOND
|
||||||
|
*/
|
||||||
|
private void initializeUpdateTimer() {
|
||||||
timerTimeline = new Timeline();
|
timerTimeline = new Timeline();
|
||||||
timerTimeline.setCycleCount(Timeline.INDEFINITE);
|
timerTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
// Run timer update every second
|
// Run timer update every second
|
||||||
timerTimeline.getKeyFrames().add(
|
timerTimeline.getKeyFrames().add(
|
||||||
new KeyFrame(Duration.seconds(1),
|
new KeyFrame(Duration.seconds(1),
|
||||||
event -> {
|
event -> {
|
||||||
if (StreamParser.isRaceFinished()) {
|
updateRaceTime();
|
||||||
timerLabel.setFill(Color.RED);
|
updateWindDirection();
|
||||||
timerLabel.setText("Race Finished!");
|
updateOrder();
|
||||||
} else {
|
updateBoatSelectionComboBox();
|
||||||
timerLabel.setText(currentTimer());
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -187,34 +198,45 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
timerTimeline.playFromStart();
|
timerTimeline.playFromStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialiseWindDirection() {
|
|
||||||
Timeline windDirTimeline = new Timeline();
|
/**
|
||||||
windDirTimeline.setCycleCount(Timeline.INDEFINITE);
|
* Updates the wind direction arrow and text as from info from the StreamParser
|
||||||
windDirTimeline.getKeyFrames().add(
|
*/
|
||||||
new KeyFrame(Duration.seconds(1),
|
private void updateWindDirection() {
|
||||||
event -> {
|
windDirectionText.setText(String.format("%.1f°", StreamParser.getWindDirection()));
|
||||||
windDirectionText
|
windArrowText.setRotate(StreamParser.getWindDirection());
|
||||||
.setText(String.format("%.1f°", StreamParser.getWindDirection()));
|
|
||||||
windArrowText.setRotate(StreamParser.getWindDirection());
|
|
||||||
})
|
|
||||||
);
|
|
||||||
windDirTimeline.playFromStart();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initialisePositionVBox() {
|
|
||||||
|
|
||||||
Timeline posVBoxTimeline = new Timeline();
|
/**
|
||||||
posVBoxTimeline.setCycleCount(Timeline.INDEFINITE);
|
* Updates the clock for the race
|
||||||
posVBoxTimeline.getKeyFrames().add(
|
*/
|
||||||
new KeyFrame(Duration.seconds(1),
|
private void updateRaceTime() {
|
||||||
event -> {
|
if (StreamParser.isRaceFinished()) {
|
||||||
showOrder();
|
timerLabel.setFill(Color.RED);
|
||||||
})
|
timerLabel.setText("Race Finished!");
|
||||||
);
|
} else {
|
||||||
posVBoxTimeline.playFromStart();
|
timerLabel.setText(getTimeSinceStartOfRace());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showOrder() {
|
|
||||||
|
/**
|
||||||
|
* Grabs the boats currently in the race as from the StreamParser and sets them to be selectable
|
||||||
|
* in the boat selection combo box
|
||||||
|
*/
|
||||||
|
private void updateBoatSelectionComboBox() {
|
||||||
|
ObservableList<Yacht> observableBoats = FXCollections
|
||||||
|
.observableArrayList(StreamParser.getBoatsPos().values());
|
||||||
|
boatSelectionComboBox.setItems(observableBoats);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the order of the boats as from the StreamParser and sets them in the boat order
|
||||||
|
* section
|
||||||
|
*/
|
||||||
|
private void updateOrder() {
|
||||||
positionVbox.getChildren().clear();
|
positionVbox.getChildren().clear();
|
||||||
positionVbox.getChildren().removeAll();
|
positionVbox.getChildren().removeAll();
|
||||||
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
@@ -237,6 +259,44 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialised the combo box with any boats currently in the race and adds the required listener
|
||||||
|
* for the combobox to take action upon selection
|
||||||
|
*/
|
||||||
|
private void initialiseBoatSelectionComboBox() {
|
||||||
|
updateBoatSelectionComboBox();
|
||||||
|
boatSelectionComboBox.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
//This listener is fired whenever the combo box changes. This means when the values are updated
|
||||||
|
//We dont want to set the selected value if the values are updated but nothing clicked (null)
|
||||||
|
if (newValue != null && newValue != selectedBoat) {
|
||||||
|
Yacht thisYacht = (Yacht) newValue;
|
||||||
|
setSelectedBoat(thisYacht);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the list of boats in the order they finished the race
|
||||||
|
*/
|
||||||
|
private void loadRaceResultView() {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml"));
|
||||||
|
loader.setController(new RaceResultController(race));
|
||||||
|
|
||||||
|
try {
|
||||||
|
contentAnchorPane.getChildren().removeAll();
|
||||||
|
contentAnchorPane.getChildren().clear();
|
||||||
|
contentAnchorPane.getChildren().addAll((Pane) loader.load());
|
||||||
|
|
||||||
|
} catch (javafx.fxml.LoadException e) {
|
||||||
|
System.err.println(e.getCause());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert seconds to a string of the format mm:ss
|
* Convert seconds to a string of the format mm:ss
|
||||||
*
|
*
|
||||||
@@ -250,7 +310,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
return String.format("%02d:%02d", time / 60, time % 60);
|
return String.format("%02d:%02d", time / 60, time % 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String currentTimer() {
|
private String getTimeSinceStartOfRace() {
|
||||||
String timerString = "0:00";
|
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);
|
||||||
@@ -270,13 +330,18 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
return timerString;
|
return timerString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isDisplayFps() {
|
public boolean isDisplayFps() {
|
||||||
return displayFps;
|
return displayFps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Race getRace() {
|
||||||
|
return race;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the important annotations for a specific BoatGroup
|
* Display the important annotations for a specific BoatGroup
|
||||||
*
|
|
||||||
* @param bg The boat group to set the annotations for
|
* @param bg The boat group to set the annotations for
|
||||||
*/
|
*/
|
||||||
private void setBoatGroupImportantAnnotations(BoatGroup bg) {
|
private void setBoatGroupImportantAnnotations(BoatGroup bg) {
|
||||||
@@ -303,42 +368,81 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
} else {
|
} else {
|
||||||
bg.setWakeVisible(false);
|
bg.setWakeVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK)) {
|
||||||
|
bg.setEstTimeToNextMarkObjectVisible(true);
|
||||||
|
} else {
|
||||||
|
bg.setEstTimeToNextMarkObjectVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importantAnnotations.getAnnotationState(Annotation.LEGTIME)) {
|
||||||
|
bg.setLegTimeObjectVisible(true);
|
||||||
|
} else {
|
||||||
|
bg.setLegTimeObjectVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAnnotations(Integer annotationLevel) {
|
private void setAnnotations(Integer annotationLevel) {
|
||||||
switch (annotationLevel) {
|
switch (annotationLevel) {
|
||||||
|
// No Annotations
|
||||||
case 0:
|
case 0:
|
||||||
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
||||||
bg.setTeamNameObjectVisible(false);
|
if (ro instanceof BoatGroup) {
|
||||||
bg.setVelocityObjectVisible(false);
|
BoatGroup bg = (BoatGroup) ro;
|
||||||
bg.setLineGroupVisible(false);
|
bg.setTeamNameObjectVisible(false);
|
||||||
bg.setWakeVisible(false);
|
bg.setVelocityObjectVisible(false);
|
||||||
|
bg.setEstTimeToNextMarkObjectVisible(false);
|
||||||
|
bg.setLegTimeObjectVisible(false);
|
||||||
|
bg.setLineGroupVisible(false);
|
||||||
|
bg.setWakeVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// Important Annotations
|
||||||
case 1:
|
case 1:
|
||||||
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
||||||
bg.setTeamNameObjectVisible(true);
|
if (ro instanceof BoatGroup) {
|
||||||
bg.setVelocityObjectVisible(false);
|
BoatGroup bg = (BoatGroup) ro;
|
||||||
bg.setLineGroupVisible(false);
|
setBoatGroupImportantAnnotations(bg);
|
||||||
bg.setWakeVisible(false);
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
// All Annotations
|
||||||
case 2:
|
case 2:
|
||||||
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
||||||
bg.setTeamNameObjectVisible(true);
|
if (ro instanceof BoatGroup) {
|
||||||
bg.setVelocityObjectVisible(false);
|
BoatGroup bg = (BoatGroup) ro;
|
||||||
bg.setLineGroupVisible(true);
|
bg.setTeamNameObjectVisible(true);
|
||||||
bg.setWakeVisible(false);
|
bg.setVelocityObjectVisible(true);
|
||||||
|
bg.setEstTimeToNextMarkObjectVisible(true);
|
||||||
|
bg.setLegTimeObjectVisible(true);
|
||||||
|
bg.setLineGroupVisible(true);
|
||||||
|
bg.setWakeVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
}
|
||||||
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
}
|
||||||
bg.setTeamNameObjectVisible(true);
|
|
||||||
bg.setVelocityObjectVisible(true);
|
|
||||||
bg.setLineGroupVisible(true);
|
/**
|
||||||
bg.setWakeVisible(true);
|
* Sets all the annotations of the selected boat to be visible and all others to be hidden
|
||||||
|
*
|
||||||
|
* @param yacht The yacht for which we want to view all annotations
|
||||||
|
*/
|
||||||
|
private void setSelectedBoat(Yacht yacht) {
|
||||||
|
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
||||||
|
if (ro instanceof BoatGroup) {
|
||||||
|
BoatGroup bg = (BoatGroup) ro;
|
||||||
|
//We need to iterate over all race groups to get the matching boat group belonging to this boat if we
|
||||||
|
//are to toggle its annotations, there is no other backwards knowledge of a yacht to its boatgroup.
|
||||||
|
if (bg.getBoat().getHullID().equals(yacht.getHullID())) {
|
||||||
|
bg.setIsSelected(true);
|
||||||
|
selectedBoat = yacht;
|
||||||
|
} else {
|
||||||
|
bg.setIsSelected(false);
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package seng302.controllers;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.Parent;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TableColumn;
|
||||||
|
import javafx.scene.control.TableView;
|
||||||
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import seng302.models.Yacht;
|
||||||
|
import seng302.models.parsers.StreamParser;
|
||||||
|
|
||||||
|
public class StartScreenController implements Initializable {
|
||||||
|
@FXML
|
||||||
|
private GridPane gridPane;
|
||||||
|
@FXML
|
||||||
|
private Label timeTillLive;
|
||||||
|
@FXML
|
||||||
|
private Button streamButton;
|
||||||
|
@FXML
|
||||||
|
private Button switchToRaceViewButton;
|
||||||
|
@FXML
|
||||||
|
private TableView<Yacht> teamList;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Yacht, String> boatNameCol;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Yacht, String> shortNameCol;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Yacht, String> countryCol;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<Yacht, String> posCol;
|
||||||
|
@FXML
|
||||||
|
private Label realTime;
|
||||||
|
|
||||||
|
private boolean switchedToRaceView = false;
|
||||||
|
|
||||||
|
private void setContentPane(String jfxUrl){
|
||||||
|
try{
|
||||||
|
// get the main controller anchor pane (MainView.fxml)
|
||||||
|
AnchorPane contentPane = (AnchorPane) gridPane.getParent();
|
||||||
|
contentPane.getChildren().removeAll();
|
||||||
|
contentPane.getChildren().clear();
|
||||||
|
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
|
contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
||||||
|
}
|
||||||
|
catch(javafx.fxml.LoadException e){
|
||||||
|
System.err.println(e.getCause());
|
||||||
|
}
|
||||||
|
catch(IOException e){
|
||||||
|
System.err.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
gridPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
|
teamList.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Running a timer to update the livestream status on welcome screen. Update interval is 1 second.
|
||||||
|
*/
|
||||||
|
public void startStream() {
|
||||||
|
if (StreamParser.isStreamStatus()) {
|
||||||
|
streamButton.setVisible(false);
|
||||||
|
realTime.setVisible(true);
|
||||||
|
timeTillLive.setVisible(true);
|
||||||
|
timeTillLive.setTextFill(Color.GREEN);
|
||||||
|
timeTillLive.setText("Connecting...");
|
||||||
|
Timer timer = new Timer();
|
||||||
|
timer.scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
if (StreamParser.isRaceStarted()) {
|
||||||
|
if (!switchedToRaceView) {
|
||||||
|
switchToRaceView();
|
||||||
|
}
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
if (StreamParser.isRaceFinished()) {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
|
timeTillLive.setTextFill(Color.RED);
|
||||||
|
timeTillLive.setText("Race finished! Waiting for new race...");
|
||||||
|
switchToRaceViewButton.setDisable(true);
|
||||||
|
} else if (StreamParser.getTimeSinceStart() > 0) {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
|
updateTeamList();
|
||||||
|
timeTillLive.setTextFill(Color.RED);
|
||||||
|
switchToRaceViewButton.setDisable(false);
|
||||||
|
String timerMinute = Long.toString(StreamParser.getTimeSinceStart() / 60);
|
||||||
|
String timerSecond = Long.toString(StreamParser.getTimeSinceStart() % 60);
|
||||||
|
if (timerSecond.length() == 1) {
|
||||||
|
timerSecond = "0" + timerSecond;
|
||||||
|
}
|
||||||
|
String timerString = "-" + timerMinute + ":" + timerSecond;
|
||||||
|
timeTillLive.setText(timerString);
|
||||||
|
} else {
|
||||||
|
realTime.setText(StreamParser.getCurrentTimeString());
|
||||||
|
updateTeamList();
|
||||||
|
timeTillLive.setTextFill(Color.BLACK);
|
||||||
|
switchToRaceViewButton.setDisable(false);
|
||||||
|
String timerMinute = Long.toString(-1 * StreamParser.getTimeSinceStart() / 60);
|
||||||
|
String timerSecond = Long.toString(-1 * StreamParser.getTimeSinceStart() % 60);
|
||||||
|
if (timerSecond.length() == 1) {
|
||||||
|
timerSecond = "0" + timerSecond;
|
||||||
|
}
|
||||||
|
String timerString = timerMinute + ":" + timerSecond;
|
||||||
|
timeTillLive.setText(timerString);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 0, 1000);
|
||||||
|
} else {
|
||||||
|
timeTillLive.setText("Stream not available.");
|
||||||
|
timeTillLive.setTextFill(Color.RED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void switchToRaceView() {
|
||||||
|
switchedToRaceView = true;
|
||||||
|
setContentPane("/views/RaceView.fxml");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTeamList() {
|
||||||
|
ObservableList<Yacht> data = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
teamList.setItems(data);
|
||||||
|
|
||||||
|
boatNameCol.setCellValueFactory(
|
||||||
|
new PropertyValueFactory<>("boatName")
|
||||||
|
);
|
||||||
|
shortNameCol.setCellValueFactory(
|
||||||
|
new PropertyValueFactory<>("shortName")
|
||||||
|
);
|
||||||
|
countryCol.setCellValueFactory(
|
||||||
|
new PropertyValueFactory<>("country")
|
||||||
|
);
|
||||||
|
posCol.setCellValueFactory(
|
||||||
|
new PropertyValueFactory<>("position")
|
||||||
|
);
|
||||||
|
|
||||||
|
data.addAll(StreamParser.getBoatsPos().values());
|
||||||
|
teamList.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,5 +7,7 @@ public enum Annotation {
|
|||||||
SPEED,
|
SPEED,
|
||||||
WAKE,
|
WAKE,
|
||||||
TRACK,
|
TRACK,
|
||||||
NAME
|
NAME,
|
||||||
|
ESTTIMETONEXTMARK,
|
||||||
|
LEGTIME
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.Map;
|
|||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class ImportantAnnotationController implements Initializable {
|
public class ImportantAnnotationController implements Initializable {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* JavaFX Outlets
|
* JavaFX Outlets
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +31,12 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
@FXML
|
@FXML
|
||||||
private CheckBox boatNameSelect;
|
private CheckBox boatNameSelect;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private CheckBox boatEstTimeToNextMarkSelect;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private CheckBox boatElapsedTimeSelect;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane annotationSelectWindow;
|
private AnchorPane annotationSelectWindow;
|
||||||
|
|
||||||
@@ -40,7 +47,7 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
private ImportantAnnotationsState importantAnnotationsState;
|
private ImportantAnnotationsState importantAnnotationsState;
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
|
|
||||||
public ImportantAnnotationController(ImportantAnnotationDelegate delegate, Stage stage){
|
public ImportantAnnotationController(ImportantAnnotationDelegate delegate, Stage stage) {
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
importantAnnotationsState = new ImportantAnnotationsState();
|
importantAnnotationsState = new ImportantAnnotationsState();
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
@@ -49,10 +56,11 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
/**
|
/**
|
||||||
* Sets whether or not an annotation is considered important, then
|
* Sets whether or not an annotation is considered important, then
|
||||||
* sends an update to the delegate
|
* sends an update to the delegate
|
||||||
|
*
|
||||||
* @param annotation The annotation
|
* @param annotation The annotation
|
||||||
* @param isSet True if annotation is important
|
* @param isSet True if annotation is important
|
||||||
*/
|
*/
|
||||||
private void setAnnotation(Annotation annotation, Boolean isSet){
|
private void setAnnotation(Annotation annotation, Boolean isSet) {
|
||||||
importantAnnotationsState.setAnnotationState(annotation, isSet);
|
importantAnnotationsState.setAnnotationState(annotation, isSet);
|
||||||
sendUpdate();
|
sendUpdate();
|
||||||
}
|
}
|
||||||
@@ -61,36 +69,50 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
* Sends an update to the delegate when the important
|
* Sends an update to the delegate when the important
|
||||||
* annotations have changed
|
* annotations have changed
|
||||||
*/
|
*/
|
||||||
private void sendUpdate(){
|
private void sendUpdate() {
|
||||||
this.delegate.importantAnnotationsChanged(importantAnnotationsState);
|
this.delegate.importantAnnotationsChanged(importantAnnotationsState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the current state of the 'important annotations'
|
* Load the current state of the 'important annotations'
|
||||||
|
*
|
||||||
* @param currentState hashmap containing the states of each annotation
|
* @param currentState hashmap containing the states of each annotation
|
||||||
*/
|
*/
|
||||||
public void loadState(ImportantAnnotationsState currentState){
|
public void loadState(ImportantAnnotationsState currentState) {
|
||||||
this.importantAnnotationsState = currentState;
|
this.importantAnnotationsState = currentState;
|
||||||
|
|
||||||
// Initialise checkboxes
|
// Initialise checkboxes
|
||||||
for (Annotation annotation : importantAnnotationsState.getAnnotations()){
|
for (Annotation annotation : importantAnnotationsState.getAnnotations()) {
|
||||||
switch (annotation){
|
switch (annotation) {
|
||||||
case WAKE:
|
case WAKE:
|
||||||
boatWakeSelect.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
boatWakeSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPEED:
|
case SPEED:
|
||||||
boatSpeedSelect.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
boatSpeedSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRACK:
|
case TRACK:
|
||||||
boatTrackSelect.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
boatTrackSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME:
|
case NAME:
|
||||||
boatNameSelect.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
boatNameSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ESTTIMETONEXTMARK:
|
||||||
|
boatEstTimeToNextMarkSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LEGTIME:
|
||||||
|
boatElapsedTimeSelect
|
||||||
|
.setSelected(importantAnnotationsState.getAnnotationState(annotation));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -99,15 +121,24 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* View did load
|
* View did load
|
||||||
|
*
|
||||||
* @param location .
|
* @param location .
|
||||||
* @param resources .
|
* @param resources .
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
boatWakeSelect.setOnAction(event -> setAnnotation(Annotation.WAKE, boatWakeSelect.isSelected()));
|
boatWakeSelect
|
||||||
boatSpeedSelect.setOnAction(event -> setAnnotation(Annotation.SPEED, boatSpeedSelect.isSelected()));
|
.setOnAction(event -> setAnnotation(Annotation.WAKE, boatWakeSelect.isSelected()));
|
||||||
boatTrackSelect.setOnAction(event -> setAnnotation(Annotation.TRACK, boatTrackSelect.isSelected()));
|
boatSpeedSelect
|
||||||
boatNameSelect.setOnAction(event -> setAnnotation(Annotation.NAME, boatNameSelect.isSelected()));
|
.setOnAction(event -> setAnnotation(Annotation.SPEED, boatSpeedSelect.isSelected()));
|
||||||
|
boatTrackSelect
|
||||||
|
.setOnAction(event -> setAnnotation(Annotation.TRACK, boatTrackSelect.isSelected()));
|
||||||
|
boatNameSelect
|
||||||
|
.setOnAction(event -> setAnnotation(Annotation.NAME, boatNameSelect.isSelected()));
|
||||||
|
boatEstTimeToNextMarkSelect.setOnAction(event -> setAnnotation(Annotation.ESTTIMETONEXTMARK,
|
||||||
|
boatEstTimeToNextMarkSelect.isSelected()));
|
||||||
|
boatElapsedTimeSelect.setOnAction(
|
||||||
|
event -> setAnnotation(Annotation.LEGTIME, boatElapsedTimeSelect.isSelected()));
|
||||||
|
|
||||||
closeButton.setOnAction(event -> stage.close());
|
closeButton.setOnAction(event -> stage.close());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import java.text.SimpleDateFormat;
|
|||||||
* also done outside Boat class because some old variables are not used anymore.
|
* also done outside Boat class because some old variables are not used anymore.
|
||||||
*/
|
*/
|
||||||
public class Yacht {
|
public class Yacht {
|
||||||
|
// Used in boat group
|
||||||
private Color colour;
|
private Color colour;
|
||||||
private double velocity;
|
private double velocity;
|
||||||
private Integer markLastPast;
|
|
||||||
|
|
||||||
private String boatType;
|
private String boatType;
|
||||||
private Integer sourceID;
|
private Integer sourceID;
|
||||||
@@ -30,6 +30,8 @@ public class Yacht {
|
|||||||
private Long estimateTimeAtNextMark;
|
private Long estimateTimeAtNextMark;
|
||||||
private Long estimateTimeAtFinish;
|
private Long estimateTimeAtFinish;
|
||||||
private String position;
|
private String position;
|
||||||
|
// Mark rounding
|
||||||
|
private Long markRoundingTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in EventTest and RaceTest.
|
* Used in EventTest and RaceTest.
|
||||||
@@ -157,11 +159,16 @@ public class Yacht {
|
|||||||
this.velocity = velocity;
|
this.velocity = velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getMarkLastPast() {
|
public Long getMarkRoundingTime() {
|
||||||
return markLastPast;
|
return markRoundingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMarkLastPast(Integer markLastPast) {
|
public void setMarkRoundingTime(Long markRoundingTime) {
|
||||||
this.markLastPast = markLastPast;
|
this.markRoundingTime = markRoundingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return boatName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package seng302.models.stream;
|
package seng302.models.parsers;
|
||||||
|
|
||||||
|
|
||||||
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.Yacht;
|
||||||
import seng302.models.stream.packets.BoatPositionPacket;
|
import seng302.models.parsers.packets.BoatPositionPacket;
|
||||||
import seng302.models.stream.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;
|
||||||
@@ -17,6 +17,7 @@ import java.text.DateFormat;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,21 +25,22 @@ import java.util.concurrent.PriorityBlockingQueue;
|
|||||||
* and parsed in by turning the byte arrays into useful data. There are two public static hashmaps
|
* and parsed in by turning the byte arrays into useful data. There are two public static hashmaps
|
||||||
* that are threadsafe so the visualiser can always access the latest speed and position available
|
* that are threadsafe so the visualiser can always access the latest speed and position available
|
||||||
* Created by kre39 on 23/04/17.
|
* Created by kre39 on 23/04/17.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class StreamParser extends Thread{
|
public class StreamParser extends Thread{
|
||||||
|
|
||||||
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatPositions = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatPositions = new ConcurrentHashMap<>();
|
||||||
private String threadName;
|
private String threadName;
|
||||||
private Thread t;
|
private Thread t;
|
||||||
|
private static boolean newRaceXmlReceived = false;
|
||||||
private static boolean raceStarted = false;
|
private static boolean raceStarted = false;
|
||||||
private 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 Map<Integer, Yacht> boats = new HashMap<>();
|
private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
|
||||||
private static Map<Long, Yacht> boatsPos = new TreeMap<>();
|
private static Map<Long, Yacht> boatsPos = new ConcurrentSkipListMap<>();
|
||||||
private static double windDirection = 0;
|
private static double windDirection = 0;
|
||||||
|
private static Long currentTimeLong;
|
||||||
private static String currentTimeString;
|
private static String currentTimeString;
|
||||||
private static boolean appRunning;
|
private static boolean appRunning;
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ public class StreamParser extends Thread{
|
|||||||
while (appRunning){
|
while (appRunning){
|
||||||
StreamPacket packet = StreamReceiver.packetBuffer.take();
|
StreamPacket packet = StreamReceiver.packetBuffer.take();
|
||||||
parsePacket(packet);
|
parsePacket(packet);
|
||||||
|
Thread.sleep(1);
|
||||||
while (StreamReceiver.packetBuffer.peek() == null) {
|
while (StreamReceiver.packetBuffer.peek() == null) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,6 +110,7 @@ public class StreamParser extends Thread{
|
|||||||
extractDisplayMessage(packet);
|
extractDisplayMessage(packet);
|
||||||
break;
|
break;
|
||||||
case XML_MESSAGE:
|
case XML_MESSAGE:
|
||||||
|
newRaceXmlReceived = true;
|
||||||
extractXmlMessage(packet);
|
extractXmlMessage(packet);
|
||||||
break;
|
break;
|
||||||
case RACE_START_STATUS:
|
case RACE_START_STATUS:
|
||||||
@@ -181,9 +185,11 @@ public class StreamParser extends Thread{
|
|||||||
long currentTime = bytesToLong(Arrays.copyOfRange(payload,1,7));
|
long currentTime = bytesToLong(Arrays.copyOfRange(payload,1,7));
|
||||||
long raceId = bytesToLong(Arrays.copyOfRange(payload,7,11));
|
long raceId = bytesToLong(Arrays.copyOfRange(payload,7,11));
|
||||||
int raceStatus = payload[11];
|
int raceStatus = payload[11];
|
||||||
// System.out.println("raceStatus = " + raceStatus);
|
|
||||||
long expectedStartTime = bytesToLong(Arrays.copyOfRange(payload,12,18));
|
long expectedStartTime = bytesToLong(Arrays.copyOfRange(payload,12,18));
|
||||||
|
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
||||||
|
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
||||||
|
|
||||||
|
currentTimeLong = currentTime;
|
||||||
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
|
||||||
if (xmlObject.getRegattaXML() != null) {
|
if (xmlObject.getRegattaXML() != null) {
|
||||||
format.setTimeZone(TimeZone.getTimeZone(getTimeZoneString()));
|
format.setTimeZone(TimeZone.getTimeZone(getTimeZoneString()));
|
||||||
@@ -191,7 +197,6 @@ public class StreamParser extends Thread{
|
|||||||
}
|
}
|
||||||
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");
|
||||||
@@ -207,10 +212,10 @@ public class StreamParser extends Thread{
|
|||||||
}
|
}
|
||||||
timeSinceStart = timeTillStart;
|
timeSinceStart = timeTillStart;
|
||||||
}
|
}
|
||||||
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
|
||||||
double windDirFactor = 0x4000 / 90; //0x4000 is 90 degrees, 0x8000 is 180 degrees, etc...
|
double windDirFactor = 0x4000 / 90; //0x4000 is 90 degrees, 0x8000 is 180 degrees, etc...
|
||||||
windDirection = windDir / windDirFactor;
|
windDirection = windDir / windDirFactor;
|
||||||
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
|
||||||
int noBoats = payload[22];
|
int noBoats = payload[22];
|
||||||
int raceType = payload[23];
|
int raceType = payload[23];
|
||||||
boatsPos = new TreeMap<>();
|
boatsPos = new TreeMap<>();
|
||||||
@@ -219,11 +224,11 @@ public class StreamParser extends Thread{
|
|||||||
Yacht boat = boats.get((int) boatStatusSourceID);
|
Yacht boat = boats.get((int) boatStatusSourceID);
|
||||||
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
||||||
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
||||||
boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
|
boat.setPenaltiesAwarded((int)payload[30 + (i * 20)]);
|
||||||
boat.setPenaltiesServed((int)payload[30 + (i * 20)]);
|
boat.setPenaltiesServed((int)payload[31 + (i * 20)]);
|
||||||
Long estTimeAtNextMark = bytesToLong(Arrays.copyOfRange(payload,31 + (i * 20),37+ (i * 20)));
|
Long estTimeAtNextMark = bytesToLong(Arrays.copyOfRange(payload,32 + (i * 20),38+ (i * 20)));
|
||||||
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
||||||
Long estTimeAtFinish = bytesToLong(Arrays.copyOfRange(payload,37 + (i * 20),43+ (i * 20)));
|
Long estTimeAtFinish = bytesToLong(Arrays.copyOfRange(payload,38 + (i * 20),44+ (i * 20)));
|
||||||
boat.setEstimateTimeAtFinish(estTimeAtFinish);
|
boat.setEstimateTimeAtFinish(estTimeAtFinish);
|
||||||
boatsPos.put(estTimeAtFinish, boat);
|
boatsPos.put(estTimeAtFinish, boat);
|
||||||
// String boatStatus = "SourceID: " + boatStatusSourceID;
|
// String boatStatus = "SourceID: " + boatStatusSourceID;
|
||||||
@@ -277,8 +282,8 @@ public class StreamParser extends Thread{
|
|||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
|
|
||||||
int messageType = payload[9];
|
int messageType = payload[9];
|
||||||
long messagelength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
long messageLength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
||||||
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messagelength)))).trim();
|
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messageLength)))).trim();
|
||||||
|
|
||||||
//Create XML document Object
|
//Create XML document Object
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
@@ -295,6 +300,9 @@ public class StreamParser extends Thread{
|
|||||||
if (messageType == 7) { //7 is the boat XML
|
if (messageType == 7) { //7 is the boat XML
|
||||||
boats = xmlObject.getBoatXML().getCompetingBoats();
|
boats = xmlObject.getBoatXML().getCompetingBoats();
|
||||||
}
|
}
|
||||||
|
if (messageType == 6) { //6 is race info xml
|
||||||
|
newRaceXmlReceived = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -409,6 +417,9 @@ public class StreamParser extends Thread{
|
|||||||
int roundingSide = payload[18];
|
int roundingSide = payload[18];
|
||||||
int markType = payload[19];
|
int markType = payload[19];
|
||||||
int markId = payload[20];
|
int markId = payload[20];
|
||||||
|
|
||||||
|
// assign mark rounding time to boat
|
||||||
|
boats.get((int)subjectId).setMarkRoundingTime(timeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -555,9 +566,33 @@ public class StreamParser extends Thread{
|
|||||||
return boatsPos;
|
return boatsPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns current time in stream in long
|
||||||
|
*
|
||||||
|
* @return a long value of current time
|
||||||
|
*/
|
||||||
|
public static Long getCurrentTimeLong() {
|
||||||
|
return currentTimeLong;
|
||||||
|
}
|
||||||
|
|
||||||
public static void appClose(){
|
public static void appClose(){
|
||||||
appRunning = false;
|
appRunning = false;
|
||||||
System.out.println("[CLIENT] Shutting down stream parser");
|
System.out.println("[CLIENT] Shutting down stream parser");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check if a new un-processed xml has been found, if so will return true before
|
||||||
|
* toggling off so that the next check will return false.
|
||||||
|
*
|
||||||
|
* @return the status of if new xml has been received
|
||||||
|
*/
|
||||||
|
public static boolean isNewRaceXmlReceived(){
|
||||||
|
if (newRaceXmlReceived){
|
||||||
|
newRaceXmlReceived = false;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,28 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the post-start race course information
|
||||||
|
*/
|
||||||
|
private void sendPostStartCourseXml(){
|
||||||
|
Timer t = new Timer();
|
||||||
|
t.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Message raceData = getXmlMessage("/server_config/courseLimits.xml", XMLMessageSubType.RACE);
|
||||||
|
if (raceData != null) {
|
||||||
|
server.send(raceData);
|
||||||
|
serverLog("Sending race data", 0);
|
||||||
|
}
|
||||||
|
}catch (IOException e) {
|
||||||
|
serverLog("Couldn't send an XML Message: " + e.getMessage(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},25000);
|
||||||
|
//Delays the new course xml data for 25 seconds so the boats are able to pass the starting line
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try{
|
try{
|
||||||
server = new StreamingServerSocket(PORT_NUMBER);
|
server = new StreamingServerSocket(PORT_NUMBER);
|
||||||
@@ -252,12 +274,13 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
sendXml();
|
sendXml();
|
||||||
startSendingRaceStartStatusMessages();
|
startSendingRaceStartStatusMessages();
|
||||||
startSendingRaceStatusMessages();
|
startSendingRaceStatusMessages();
|
||||||
|
sendPostStartCourseXml();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start sending static boat position updates when race has finished
|
* Start sending static boat position updates when race has finished
|
||||||
*/
|
*/
|
||||||
private void startSendingRaceFinishedBoatPostions(){
|
private void startSendingRaceFinishedBoatPositions(){
|
||||||
Timer t = new Timer();
|
Timer t = new Timer();
|
||||||
t.schedule(new TimerTask() {
|
t.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
@@ -316,7 +339,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
||||||
startSendingRaceFinishedBoatPostions();
|
startSendingRaceFinishedBoatPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package seng302.server.messages;
|
package seng302.server.messages;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.nio.channels.SocketChannel;
|
import java.nio.channels.SocketChannel;
|
||||||
import java.nio.channels.WritableByteChannel;
|
|
||||||
|
|
||||||
public class BoatLocationMessage extends Message {
|
public class BoatLocationMessage extends Message {
|
||||||
private final int MESSAGE_SIZE = 56;
|
private final int MESSAGE_SIZE = 56;
|
||||||
|
|||||||
@@ -128,6 +128,24 @@ Table
|
|||||||
-fx-border-style: none;
|
-fx-border-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Combo Box
|
||||||
|
*/
|
||||||
|
|
||||||
|
.combo-box-base {
|
||||||
|
-fx-background-color: #119796;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combo-box-popup .list-view .list-cell:hover {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combo-box .cell:selected {
|
||||||
|
-fx-text-fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove scroll bars
|
Remove scroll bars
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Race>
|
||||||
|
<CreationTimeDate>2015-08-29T13:12:40+02:00</CreationTimeDate>
|
||||||
|
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False"/>
|
||||||
|
<RaceID>15082901</RaceID>
|
||||||
|
<RaceType>Fleet</RaceType>
|
||||||
|
<Participants>
|
||||||
|
<Yacht SourceID="101"/>
|
||||||
|
<Yacht SourceID="102"/>
|
||||||
|
<Yacht SourceID="103"/>
|
||||||
|
<Yacht SourceID="104"/>
|
||||||
|
<Yacht SourceID="105"/>
|
||||||
|
<Yacht SourceID="106"/>
|
||||||
|
</Participants>
|
||||||
|
<Course>
|
||||||
|
<CompoundMark CompoundMarkID="1" Name="Mark0">
|
||||||
|
<Mark SeqID="1" Name="Start Line 1" TargetLat="57.6703330" TargetLng="11.8278330"
|
||||||
|
SourceID="122"/>
|
||||||
|
<Mark SeqID="2" Name="Start Line 2" TargetLat="57.6703330" TargetLng="11.8278330"
|
||||||
|
SourceID="123"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2" Name="Mark1">
|
||||||
|
<Mark SeqID="1" Name="Mark1" TargetLat="57.6675700" TargetLng="11.8359880" SourceID="131"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="6" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="7" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="8" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="9" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="10" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="11" Name="Mark4">
|
||||||
|
<Mark SeqID="1" Name="Finish Line 1" TargetLat="57.6715240" TargetLng="11.8444950"
|
||||||
|
SourceID="128"/>
|
||||||
|
<Mark SeqID="2" Name="Finish Line 2" TargetLat="57.6715240" TargetLng="11.8444950"
|
||||||
|
SourceID="129"/>
|
||||||
|
</CompoundMark>
|
||||||
|
</Course>
|
||||||
|
<CompoundMarkSequence>
|
||||||
|
<Corner SeqID="1" CompoundMarkID="1" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="2" CompoundMarkID="2" Rounding="Port" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="3" CompoundMarkID="3" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="4" CompoundMarkID="4" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="5" CompoundMarkID="5" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="6" CompoundMarkID="6" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="7" CompoundMarkID="7" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="8" CompoundMarkID="8" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="9" CompoundMarkID="9" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="10" CompoundMarkID="10" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="11" CompoundMarkID="11" Rounding="PS" ZoneSize="3"/>
|
||||||
|
</CompoundMarkSequence>
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit SeqID="1" Lat="57.6739450" Lon="11.8417100"/>
|
||||||
|
<Limit SeqID="2" Lat="57.6709520" Lon="11.8485010"/>
|
||||||
|
<Limit SeqID="3" Lat="57.6690260" Lon="11.8472790"/>
|
||||||
|
<Limit SeqID="4" Lat="57.6693140" Lon="11.8457610"/>
|
||||||
|
<Limit SeqID="5" Lat="57.6665370" Lon="11.8432910"/>
|
||||||
|
<Limit SeqID="6" Lat="57.6641400" Lon="11.8385840"/>
|
||||||
|
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030"/>
|
||||||
|
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660"/>
|
||||||
|
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920"/>
|
||||||
|
<Limit SeqID="10" Lat="57.6708220" Lon="11.8321340"/>
|
||||||
|
</CourseLimit>
|
||||||
|
</Race>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Race>
|
<Race>
|
||||||
<CreationTimeDate>2015-08-29T13:12:40+02:00</CreationTimeDate>
|
<CreationTimeDate>2015-08-29T11:27:15+02:00</CreationTimeDate>
|
||||||
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False" />
|
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False" />
|
||||||
<RaceID>15082901</RaceID>
|
<RaceID>15082901</RaceID>
|
||||||
<RaceType>Fleet</RaceType>
|
<RaceType>Fleet</RaceType>
|
||||||
@@ -80,6 +80,8 @@
|
|||||||
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030" />
|
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030" />
|
||||||
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660" />
|
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660" />
|
||||||
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920" />
|
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920" />
|
||||||
<Limit SeqID="10" Lat="57.6708220" Lon="11.8321340" />
|
<Limit SeqID="10" Lat="57.6692230" Lon="11.8231430" />
|
||||||
|
<Limit SeqID="11" Lat="57.6725370" Lon="11.8272480" />
|
||||||
|
<Limit SeqID="12" Lat="57.6708220" Lon="11.8321340" />
|
||||||
</CourseLimit>
|
</CourseLimit>
|
||||||
</Race>
|
</Race>
|
||||||
@@ -7,58 +7,4 @@
|
|||||||
<?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" 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>
|
|
||||||
<GridPane nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
|
||||||
<columnConstraints>
|
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
|
||||||
</columnConstraints>
|
|
||||||
<rowConstraints>
|
|
||||||
<RowConstraints percentHeight="10.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="52.0" minHeight="52.0" prefHeight="52.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="0.0" percentHeight="8.0" prefHeight="0.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="28.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="55.0" minHeight="55.0" percentHeight="9.0" prefHeight="55.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="0.0" minHeight="0.0" percentHeight="29.0" prefHeight="0.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>
|
|
||||||
<children>
|
|
||||||
<Label alignment="CENTER" text="Welcome to Race Vision" textFill="WHITE" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
|
|
||||||
<font>
|
|
||||||
<Font size="40.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Label text="Your live AC35 livestream" textFill="WHITE" GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
|
||||||
<font>
|
|
||||||
<Font size="20.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Label text="Livestream Status:" textFill="WHITE" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
|
|
||||||
<font>
|
|
||||||
<Font size="28.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Label fx:id="timeTillLive" text="0:00 minutes" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="4">
|
|
||||||
<font>
|
|
||||||
<Font size="27.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" styleClass="blue-ui-btn" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
|
||||||
<Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" styleClass="blue-ui-btn" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="TOP" />
|
|
||||||
<TableView fx:id="teamList" maxWidth="661.0" prefHeight="324.0" prefWidth="629.0" styleClass="ui-table" GridPane.halignment="CENTER" GridPane.hgrow="NEVER" GridPane.rowIndex="5" GridPane.vgrow="NEVER">
|
|
||||||
<columns>
|
|
||||||
<TableColumn fx:id="posCol" editable="false" maxWidth="74.0" minWidth="74.0" prefWidth="74.0" resizable="false" sortable="false" text="Position" />
|
|
||||||
<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="shortNameCol" editable="false" maxWidth="155.18472290039062" minWidth="107.0" prefWidth="155.18472290039062" resizable="false" sortable="false" text="Short Name" />
|
|
||||||
<TableColumn fx:id="countryCol" editable="false" maxWidth="258.9999694824219" minWidth="147.0" prefWidth="258.9999694824219" resizable="false" sortable="false" text="Country" />
|
|
||||||
</columns>
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets top="10.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</TableView>
|
|
||||||
<Label fx:id="realTime" text="Local time" textFill="WHITE" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
|
|
||||||
</children>
|
|
||||||
</GridPane>
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
||||||
|
|||||||
@@ -44,9 +44,11 @@
|
|||||||
</Text>
|
</Text>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Slider fx:id="annotationSlider" blockIncrement="1.0" layoutX="38.0" layoutY="527.0" majorTickUnit="1.0" max="3.0" minorTickCount="0" prefHeight="51.0" prefWidth="170.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" styleClass="ui-slider" />
|
<Slider fx:id="annotationSlider" blockIncrement="1.0" layoutX="38.0" layoutY="527.0" majorTickUnit="1.0" max="2.0" minorTickCount="0" prefHeight="51.0" prefWidth="170.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" styleClass="ui-slider" />
|
||||||
<Label layoutX="10.0" layoutY="499.0" text="Annotations" textFill="WHITE" />
|
<Label layoutX="10.0" layoutY="499.0" text="Annotations" textFill="WHITE" />
|
||||||
<Button fx:id="selectAnnotationBtn" layoutX="35.0" layoutY="578.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="170.0" styleClass="blue-ui-btn" text="Select Annotations" textFill="WHITE" />
|
<Button fx:id="selectAnnotationBtn" layoutX="35.0" layoutY="578.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="170.0" styleClass="blue-ui-btn" text="Select Annotations" textFill="WHITE" />
|
||||||
|
<Text fill="WHITE" layoutX="11.0" layoutY="649.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Boat Selection" />
|
||||||
|
<ComboBox fx:id="boatSelectionComboBox" layoutX="37.0" layoutY="664.0" prefHeight="25.0" prefWidth="170.0" promptText="Select Boat" styleClass="combo-box-base" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<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">
|
<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">
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.geometry.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import javafx.scene.canvas.*?>
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<GridPane fx:id="gridPane" nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.StartScreenController">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints percentHeight="10.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="52.0" minHeight="52.0" prefHeight="52.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="0.0" percentHeight="8.0" prefHeight="0.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="28.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="55.0" minHeight="55.0" percentHeight="9.0" prefHeight="55.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="0.0" minHeight="0.0" percentHeight="29.0" prefHeight="0.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>
|
||||||
|
<children>
|
||||||
|
<Label alignment="CENTER" text="Welcome to Race Vision" textFill="WHITE" GridPane.halignment="CENTER" GridPane.valignment="BOTTOM">
|
||||||
|
<font>
|
||||||
|
<Font size="40.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label text="Your live AC35 livestream" textFill="WHITE" GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
||||||
|
<font>
|
||||||
|
<Font size="20.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label text="Livestream Status:" textFill="WHITE" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
|
||||||
|
<font>
|
||||||
|
<Font size="28.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="timeTillLive" text="0:00 minutes" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="4">
|
||||||
|
<font>
|
||||||
|
<Font size="27.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Button fx:id="streamButton" mnemonicParsing="false" onAction="#startStream" styleClass="blue-ui-btn" text="Click to stream" GridPane.halignment="CENTER" GridPane.rowIndex="4" />
|
||||||
|
<Button fx:id="switchToRaceViewButton" disable="true" mnemonicParsing="false" onAction="#switchToRaceView" styleClass="blue-ui-btn" text="Watch Race" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="TOP" />
|
||||||
|
<TableView fx:id="teamList" maxWidth="661.0" prefHeight="324.0" prefWidth="629.0" styleClass="ui-table" GridPane.halignment="CENTER" GridPane.hgrow="NEVER" GridPane.rowIndex="5" GridPane.vgrow="NEVER">
|
||||||
|
<columns>
|
||||||
|
<TableColumn fx:id="posCol" editable="false" maxWidth="74.0" minWidth="74.0" prefWidth="74.0" resizable="false" sortable="false" text="Position" />
|
||||||
|
<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="shortNameCol" editable="false" maxWidth="155.18472290039062" minWidth="107.0" prefWidth="155.18472290039062" resizable="false" sortable="false" text="Short Name" />
|
||||||
|
<TableColumn fx:id="countryCol" editable="false" maxWidth="258.9999694824219" minWidth="147.0" prefWidth="258.9999694824219" resizable="false" sortable="false" text="Country" />
|
||||||
|
</columns>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets top="10.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</TableView>
|
||||||
|
<Label fx:id="realTime" text="Local time" textFill="WHITE" visible="false" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM" />
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<AnchorPane fx:id="annotationSelectWindow" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="248.0" prefWidth="469.0" styleClass="background-blue" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
<AnchorPane fx:id="annotationSelectWindow" maxHeight="270.0" maxWidth="469.0" minHeight="270.0" minWidth="469.0" prefHeight="270.0" prefWidth="469.0" styleClass="background-blue" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Text fill="WHITE" layoutX="26.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Select important annotations">
|
<Text fill="WHITE" layoutX="26.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Select important annotations">
|
||||||
<font>
|
<font>
|
||||||
@@ -15,7 +15,8 @@
|
|||||||
<CheckBox fx:id="boatWakeSelect" layoutX="26.0" layoutY="80.0" mnemonicParsing="false" style="-fx-border-width: 0; -fx-background-insets: 0;" text="Boat Wakes" textFill="#e7e7e7" />
|
<CheckBox fx:id="boatWakeSelect" layoutX="26.0" layoutY="80.0" mnemonicParsing="false" style="-fx-border-width: 0; -fx-background-insets: 0;" text="Boat Wakes" textFill="#e7e7e7" />
|
||||||
<CheckBox fx:id="boatSpeedSelect" layoutX="26.0" layoutY="111.0" mnemonicParsing="false" text="Boat Speed" textFill="#e7e7e7" />
|
<CheckBox fx:id="boatSpeedSelect" layoutX="26.0" layoutY="111.0" mnemonicParsing="false" text="Boat Speed" textFill="#e7e7e7" />
|
||||||
<CheckBox fx:id="boatTrackSelect" layoutX="26.0" layoutY="142.0" mnemonicParsing="false" text="Boat Tracks" textFill="#e7e7e7" />
|
<CheckBox fx:id="boatTrackSelect" layoutX="26.0" layoutY="142.0" mnemonicParsing="false" text="Boat Tracks" textFill="#e7e7e7" />
|
||||||
<CheckBox fx:id="boatNameSelect" layoutX="26.0" layoutY="175.0" mnemonicParsing="false" text="Boat Name" textFill="#e7e7e7" />
|
<CheckBox fx:id="boatNameSelect" layoutX="26.0" layoutY="173.0" mnemonicParsing="false" text="Boat Name" textFill="#e7e7e7" />
|
||||||
|
<CheckBox fx:id="boatEstTimeToNextMarkSelect" layoutX="26.0" layoutY="204.0" mnemonicParsing="false" text="Boat Estimated Time To Next Mark" textFill="#e7e7e7" />
|
||||||
<Button fx:id="closeButton" layoutX="424.0" layoutY="-1.0" mnemonicParsing="false" prefHeight="11.0" prefWidth="49.0" style=": 0;" text="X" textFill="#ffffff4e">
|
<Button fx:id="closeButton" layoutX="424.0" layoutY="-1.0" mnemonicParsing="false" prefHeight="11.0" prefWidth="49.0" style=": 0;" text="X" textFill="#ffffff4e">
|
||||||
<font>
|
<font>
|
||||||
<Font size="24.0" />
|
<Font size="24.0" />
|
||||||
@@ -25,5 +26,6 @@
|
|||||||
<String fx:value="clearExitButton" />
|
<String fx:value="clearExitButton" />
|
||||||
</styleClass>
|
</styleClass>
|
||||||
</Button>
|
</Button>
|
||||||
|
<CheckBox fx:id="boatElapsedTimeSelect" layoutX="26.0" layoutY="235.0" mnemonicParsing="false" text="Boat Elapsed Time Since Last Mark" textFill="#e7e7e7" />
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
|||||||
Reference in New Issue
Block a user