mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'master'
Conflicts: src/main/java/seng302/controllers/CanvasController.java src/main/resources/RaceView.fxml
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"team-name": "Artemis Racing",
|
"team-name": "Artemis Racing",
|
||||||
"velocity": 10.3
|
"velocity": 59.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"team-name": "Emirates Team New Zealand",
|
"team-name": "Emirates Team New Zealand",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"team-name": "Groupama Team France",
|
"team-name": "Groupama Team France",
|
||||||
"velocity": 9.9
|
"velocity": 29.9
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"team-name": "Land Rover BAR",
|
"team-name": "Land Rover BAR",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<configurations>
|
<configurations>
|
||||||
<race-name>AC35</race-name>
|
<race-name>AC35</race-name>
|
||||||
<race-size>6</race-size>
|
<race-size>6</race-size>
|
||||||
<time-scale>2.0</time-scale>
|
<time-scale>1.0</time-scale>
|
||||||
|
<wind-direction>135</wind-direction>
|
||||||
</configurations>
|
</configurations>
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -6,57 +6,57 @@
|
|||||||
<name type="start-line">Start</name>
|
<name type="start-line">Start</name>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Start1</name>
|
<name>Start1</name>
|
||||||
<latitude>32.296038</latitude>
|
<latitude>32.296577</latitude>
|
||||||
<longitude>-64.854401</longitude>
|
<longitude>-64.854304</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Start2</name>
|
<name>Start2</name>
|
||||||
<latitude>32.293834</latitude>
|
<latitude>32.293771</latitude>
|
||||||
<longitude>-64.855195</longitude>
|
<longitude>-64.855242</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
</gate>
|
</gate>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Mid Mark</name>
|
<name>Mid Mark</name>
|
||||||
<latitude>32.292881</latitude>
|
<latitude>32.293039</latitude>
|
||||||
<longitude>-64.843231</longitude>
|
<longitude>-64.843983</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
<gate>
|
<gate>
|
||||||
<name>Leeward Gate</name>
|
<name>Leeward Gate</name>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Leeward Gate1</name>
|
<name>Leeward Gate1</name>
|
||||||
<latitude>32.283808</latitude>
|
<latitude>32.284680</latitude>
|
||||||
<longitude>-64.850012</longitude>
|
<longitude>-64.850045</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Leeward Gate2</name>
|
<name>Leeward Gate2</name>
|
||||||
<latitude>32.283216</latitude>
|
<latitude>32.280164</latitude>
|
||||||
<longitude>-64.847686</longitude>
|
<longitude>-64.847591</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
</gate>
|
</gate>
|
||||||
<gate>
|
<gate>
|
||||||
<name>Windward Gate</name>
|
<name>Windward Gate</name>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Windward Gate1</name>
|
<name>Windward Gate1</name>
|
||||||
<latitude>32.309908</latitude>
|
<latitude>32.309693</latitude>
|
||||||
<longitude>-64.833665</longitude>
|
<longitude>-64.835249</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Windward Gate2</name>
|
<name>Windward Gate2</name>
|
||||||
<latitude>32.309158</latitude>
|
<latitude>32.308046</latitude>
|
||||||
<longitude>-64.830834</longitude>
|
<longitude>-64.831785</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
</gate>
|
</gate>
|
||||||
<gate type="finish-line">
|
<gate type="finish-line">
|
||||||
<name>Finish</name>
|
<name>Finish</name>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Finish1</name>
|
<name>Finish1</name>
|
||||||
<latitude>32.318439</latitude>
|
<latitude>32.317379</latitude>
|
||||||
<longitude>-64.837367</longitude>
|
<longitude>-64.839291</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
<mark>
|
<mark>
|
||||||
<name>Finish2</name>
|
<name>Finish2</name>
|
||||||
<latitude>32.318303</latitude>
|
<latitude>32.317257</latitude>
|
||||||
<longitude>-64.834974</longitude>
|
<longitude>-64.836260</longitude>
|
||||||
</mark>
|
</mark>
|
||||||
</gate>
|
</gate>
|
||||||
</marks>
|
</marks>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ 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("/RaceView.fxml"));
|
Parent root = FXMLLoader.load(getClass().getResource("/MainView.fxml"));
|
||||||
primaryStage.setTitle("RaceVision");
|
primaryStage.setTitle("RaceVision");
|
||||||
primaryStage.setScene(new Scene(root));
|
primaryStage.setScene(new Scene(root));
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.*;
|
||||||
import javafx.animation.KeyFrame;
|
|
||||||
import javafx.animation.KeyValue;
|
|
||||||
import javafx.animation.Timeline;
|
|
||||||
import javafx.beans.property.DoubleProperty;
|
import javafx.beans.property.DoubleProperty;
|
||||||
import javafx.beans.property.SimpleDoubleProperty;
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
import javafx.scene.canvas.GraphicsContext;
|
import javafx.scene.canvas.GraphicsContext;
|
||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
import seng302.models.Boat;
|
import seng302.models.Boat;
|
||||||
import seng302.models.Event;
|
import seng302.models.Event;
|
||||||
@@ -22,13 +22,13 @@ import seng302.models.mark.GateMark;
|
|||||||
import seng302.models.mark.Mark;
|
import seng302.models.mark.Mark;
|
||||||
import seng302.models.mark.MarkType;
|
import seng302.models.mark.MarkType;
|
||||||
import seng302.models.mark.SingleMark;
|
import seng302.models.mark.SingleMark;
|
||||||
|
import seng302.models.parsers.ConfigParser;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.Math.abs;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ptg19 on 15/03/17.
|
* Created by ptg19 on 15/03/17.
|
||||||
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
||||||
@@ -42,13 +42,94 @@ public class CanvasController {
|
|||||||
private Race race;
|
private Race race;
|
||||||
private GraphicsContext gc;
|
private GraphicsContext gc;
|
||||||
private HashMap<Boat, TimelineInfo> timelineInfos;
|
private HashMap<Boat, TimelineInfo> timelineInfos;
|
||||||
private final double VIEW_CORNER_LAT = 32.280808;
|
|
||||||
private final double VIEW_CORNER_LON = -64.858401;
|
|
||||||
|
|
||||||
|
private AnchorPane raceResults;
|
||||||
|
|
||||||
|
private final double ORIGIN_LAT = 32.320504;
|
||||||
|
private final double ORIGIN_LON = -64.857063;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private AnchorPane contentAnchorPane;
|
||||||
|
@FXML
|
||||||
|
private Text windArrowText, windDirectionText;
|
||||||
|
|
||||||
|
@FXML Pane raceTimer;
|
||||||
|
|
||||||
|
private Animation.Status raceStatus = Animation.Status.PAUSED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the list of boats in the order they finished the race
|
||||||
|
*/
|
||||||
|
private void loadRaceResultView() {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the race timer
|
||||||
|
*/
|
||||||
|
private void loadTimerView(){
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/raceTimer.fxml"));
|
||||||
|
loader.setController(new RaceTimerController(race));
|
||||||
|
|
||||||
|
try{
|
||||||
|
raceTimer.getChildren().clear();
|
||||||
|
raceTimer.getChildren().removeAll();
|
||||||
|
raceTimer.getChildren().addAll((Pane) loader.load());
|
||||||
|
}
|
||||||
|
catch(javafx.fxml.LoadException e){
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
catch(IOException e){
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play each boats timeline
|
||||||
|
*/
|
||||||
|
private void playTimelines(){
|
||||||
|
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
||||||
|
Timeline timeline = timelineInfo.getTimeline();
|
||||||
|
|
||||||
|
if (timeline.getStatus() == Animation.Status.PAUSED){
|
||||||
|
timeline.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raceStatus = Animation.Status.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause each boats timeline
|
||||||
|
*/
|
||||||
|
private void pauseTimelines(){
|
||||||
|
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
||||||
|
Timeline timeline = timelineInfo.getTimeline();
|
||||||
|
|
||||||
|
if (timeline.getStatus() == Animation.Status.RUNNING){
|
||||||
|
timeline.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raceStatus = Animation.Status.PAUSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the controller
|
||||||
|
*/
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
gc = canvas.getGraphicsContext2D();
|
gc = canvas.getGraphicsContext2D();
|
||||||
gc.scale(22, 22);
|
gc.scale(15, 15);
|
||||||
RaceController raceController = new RaceController();
|
RaceController raceController = new RaceController();
|
||||||
raceController.initializeRace();
|
raceController.initializeRace();
|
||||||
race = raceController.getRace();
|
race = raceController.getRace();
|
||||||
@@ -62,17 +143,53 @@ public class CanvasController {
|
|||||||
drawCourse();
|
drawCourse();
|
||||||
drawBoats();
|
drawBoats();
|
||||||
|
|
||||||
|
// If race has started, draw the boats and play the timeline
|
||||||
|
if (race.getRaceTime() > 1){
|
||||||
|
playTimelines();
|
||||||
|
|
||||||
|
}
|
||||||
|
// Race has not started, pause the timelines
|
||||||
|
else if (race.getRaceTime() < 1 || raceStatus == Animation.Status.RUNNING){
|
||||||
|
pauseTimelines();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
generateTimeline();
|
generateTimeline();
|
||||||
|
|
||||||
// starts the timer and reads events from each boat's time line
|
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
|
loadTimerView();
|
||||||
|
|
||||||
|
Double maxDuration = 0.0;
|
||||||
|
Timeline maxTimeline = null;
|
||||||
|
|
||||||
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
||||||
|
|
||||||
Timeline timeline = timelineInfo.getTimeline();
|
Timeline timeline = timelineInfo.getTimeline();
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
if (timeline.getTotalDuration().toMillis() >= maxDuration) {
|
||||||
|
maxDuration = timeline.getTotalDuration().toMillis();
|
||||||
|
maxTimeline = timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timelines are paused by default
|
||||||
timeline.play();
|
timeline.play();
|
||||||
|
timeline.pause();
|
||||||
|
raceStatus = Animation.Status.RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxTimeline.setOnFinished(event -> {
|
||||||
|
race.setRaceFinished();
|
||||||
|
loadRaceResultView();
|
||||||
|
});
|
||||||
|
|
||||||
|
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
||||||
|
double windDirection = new ConfigParser("doc/examples/config.xml").getWindDirection();
|
||||||
|
windDirectionText.setText(String.format("%.1f°", windDirection));
|
||||||
|
windArrowText.setRotate(windDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,13 +214,22 @@ public class CanvasController {
|
|||||||
|
|
||||||
// iterates all events and convert each event to keyFrame, then add them into a list
|
// iterates all events and convert each event to keyFrame, then add them into a list
|
||||||
for (Event event : events) {
|
for (Event event : events) {
|
||||||
keyFrames.add(
|
if (event.getIsFinishingEvent()) {
|
||||||
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
keyFrames.add(
|
||||||
onFinished,
|
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||||
new KeyValue(x, event.getThisMark().getLatitude()),
|
event1 -> race.setBoatFinished(boat),
|
||||||
new KeyValue(y, event.getThisMark().getLongitude())
|
new KeyValue(x, event.getThisMark().getLatitude()),
|
||||||
)
|
new KeyValue(y, event.getThisMark().getLongitude())
|
||||||
);
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
keyFrames.add(
|
||||||
|
new KeyFrame(Duration.seconds(event.getTime() / 60 / 60 / 5),
|
||||||
|
new KeyValue(x, event.getThisMark().getLatitude()),
|
||||||
|
new KeyValue(y, event.getThisMark().getLongitude())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// uses the lists generated above to create a Timeline for the boat.
|
// uses the lists generated above to create a Timeline for the boat.
|
||||||
@@ -121,22 +247,6 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the distance between the two marks
|
|
||||||
*/
|
|
||||||
public double getDistanceBetweenMarks(Mark mark1, Mark mark2) {
|
|
||||||
double earth_radius = 6378.137;
|
|
||||||
double dLat = mark2.getLatitude() * Math.PI / 180 - mark1.getLatitude() * Math.PI / 180;
|
|
||||||
double dLon = mark2.getLongitude() * Math.PI / 180 - mark1.getLongitude() * Math.PI / 180;
|
|
||||||
|
|
||||||
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(mark1.getLatitude() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
||||||
|
|
||||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
||||||
double d = earth_radius * c;
|
|
||||||
|
|
||||||
return d * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a boat with given (x, y) position in the given color
|
* Draws a boat with given (x, y) position in the given color
|
||||||
*
|
*
|
||||||
@@ -146,13 +256,11 @@ public class CanvasController {
|
|||||||
*/
|
*/
|
||||||
private void drawBoat(double lat, double lon, Color color) {
|
private void drawBoat(double lat, double lon, Color color) {
|
||||||
// Latitude
|
// Latitude
|
||||||
//Double x = (MAP_WIDTH / 360.0) * (180 + lon);
|
double x = (lon - ORIGIN_LON) * 1000;
|
||||||
//Double y = (MAP_HEIGHT / 180.0) * (80 - lat);
|
double y = (ORIGIN_LAT - lat) * 1000;
|
||||||
|
|
||||||
double x = (lat - VIEW_CORNER_LAT) * 1000; // to prevent negative longitude
|
|
||||||
double y = (lon - VIEW_CORNER_LON) * 1000; // to prevent negative latitude
|
|
||||||
|
|
||||||
double diameter = 0.5;
|
double diameter = 0.5;
|
||||||
|
|
||||||
gc.setFill(color);
|
gc.setFill(color);
|
||||||
gc.fillOval(x, y, diameter, diameter);
|
gc.fillOval(x, y, diameter, diameter);
|
||||||
}
|
}
|
||||||
@@ -163,7 +271,7 @@ public class CanvasController {
|
|||||||
private void drawCourse() {
|
private void drawCourse() {
|
||||||
for (Mark mark : race.getCourse()) {
|
for (Mark mark : race.getCourse()) {
|
||||||
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||||
drawSingleMark((SingleMark) mark);
|
drawSingleMark((SingleMark) mark, Color.BLACK);
|
||||||
} else if (mark.getMarkType() == MarkType.GATE_MARK) {
|
} else if (mark.getMarkType() == MarkType.GATE_MARK) {
|
||||||
drawGateMark((GateMark) mark);
|
drawGateMark((GateMark) mark);
|
||||||
}
|
}
|
||||||
@@ -175,12 +283,12 @@ public class CanvasController {
|
|||||||
*
|
*
|
||||||
* @param singleMark
|
* @param singleMark
|
||||||
*/
|
*/
|
||||||
private void drawSingleMark(SingleMark singleMark) {
|
private void drawSingleMark(SingleMark singleMark, Color color) {
|
||||||
double x = (singleMark.getLatitude() - VIEW_CORNER_LAT) * 1000; // to prevent negative longitude
|
double x = (singleMark.getLongitude() - ORIGIN_LON) * 1000;
|
||||||
double y = (singleMark.getLongitude() - VIEW_CORNER_LON) * 1000; // to prevent negative latitude
|
double y = (ORIGIN_LAT - singleMark.getLatitude()) * 1000;
|
||||||
|
|
||||||
gc.setFill(Color.BLACK);
|
gc.setFill(color);
|
||||||
gc.fillOval(x, y, 0.5, 0.5);
|
gc.fillRect(x,y,0.5,0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,7 +297,35 @@ public class CanvasController {
|
|||||||
* @param gateMark
|
* @param gateMark
|
||||||
*/
|
*/
|
||||||
private void drawGateMark(GateMark gateMark) {
|
private void drawGateMark(GateMark gateMark) {
|
||||||
drawSingleMark(gateMark.getSingleMark1());
|
Color color = Color.BLUE;
|
||||||
drawSingleMark(gateMark.getSingleMark2());
|
|
||||||
|
if (gateMark.getName().equals("Start")){
|
||||||
|
color = Color.RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gateMark.getName().equals("Finish")){
|
||||||
|
color = Color.GREEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawSingleMark(gateMark.getSingleMark1(), color);
|
||||||
|
drawSingleMark(gateMark.getSingleMark2(), color);
|
||||||
|
|
||||||
|
GraphicsContext gc = canvas.getGraphicsContext2D();
|
||||||
|
|
||||||
|
gc.setStroke(color);
|
||||||
|
|
||||||
|
// Convert lat/lon to x,y
|
||||||
|
double x1 = (gateMark.getSingleMark1().getLongitude()- ORIGIN_LON) * 1000;
|
||||||
|
double y1 = (ORIGIN_LAT - gateMark.getSingleMark1().getLatitude()) * 1000;
|
||||||
|
|
||||||
|
double x2 = (gateMark.getSingleMark2().getLongitude() - ORIGIN_LON) * 1000;
|
||||||
|
double y2 = (ORIGIN_LAT - gateMark.getSingleMark2().getLatitude()) * 1000;
|
||||||
|
|
||||||
|
gc.setLineWidth(0.07);
|
||||||
|
gc.strokeLine(x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public Race getRace(){
|
||||||
|
return this.race;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package seng302.controllers;
|
|
||||||
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.scene.Parent;
|
|
||||||
import javafx.scene.layout.AnchorPane;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by ptg19 on 20/03/17.
|
|
||||||
*/
|
|
||||||
public class Controller {
|
|
||||||
@FXML private AnchorPane window;
|
|
||||||
@FXML private Parent raceView;
|
|
||||||
@FXML private RaceController raceViewController;
|
|
||||||
|
|
||||||
//^ this is automatic fxml linking based off http://blog.buildpath.de/fxml-composition-how-to-get-the-controller-of-an-included-fxml-view-nested-controllers/
|
|
||||||
// From googling it's probably better to just add a child however you did that in your 301 michael, it kinda depends on how we are going to
|
|
||||||
// make an event for changing the screen.
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package seng302.controllers;
|
||||||
|
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by michaelrausch on 21/03/17.
|
||||||
|
*/
|
||||||
|
public class MasterViewController implements Initializable {
|
||||||
|
@FXML
|
||||||
|
private AnchorPane contentPane;
|
||||||
|
|
||||||
|
private void setContentPane(String jfxUrl){
|
||||||
|
try{
|
||||||
|
contentPane.getChildren().removeAll();
|
||||||
|
contentPane.getChildren().clear();
|
||||||
|
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) {
|
||||||
|
setContentPane("/RaceView.fxml");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,8 @@ package seng302.controllers;
|
|||||||
|
|
||||||
import seng302.models.Boat;
|
import seng302.models.Boat;
|
||||||
import seng302.models.OldFileParser;
|
import seng302.models.OldFileParser;
|
||||||
import seng302.models.parsers.*;
|
|
||||||
import seng302.models.mark.*;
|
|
||||||
import seng302.models.Race;
|
import seng302.models.Race;
|
||||||
|
import seng302.models.parsers.CourseParser;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
@@ -20,6 +19,7 @@ import java.util.Random;
|
|||||||
*/
|
*/
|
||||||
public class RaceController {
|
public class RaceController {
|
||||||
Race race = null;
|
Race race = null;
|
||||||
|
|
||||||
public void initializeRace() {
|
public void initializeRace() {
|
||||||
String raceConfigFile;
|
String raceConfigFile;
|
||||||
raceConfigFile = "doc/examples/config.json";
|
raceConfigFile = "doc/examples/config.json";
|
||||||
@@ -55,13 +55,18 @@ public class RaceController {
|
|||||||
|
|
||||||
//get race size
|
//get race size
|
||||||
int numberOfBoats = (int) fp.getRaceSize();
|
int numberOfBoats = (int) fp.getRaceSize();
|
||||||
|
int boatsAdded = 0;
|
||||||
|
|
||||||
//get time scale
|
//get time scale
|
||||||
double timeScale = fp.getTimeScale();
|
double timeScale = fp.getTimeScale();
|
||||||
race.setTimeScale(timeScale);
|
race.setTimeScale(timeScale);
|
||||||
|
|
||||||
for (Map<String, Object> team : teams) {
|
for (Map<String, Object> team : teams) {
|
||||||
boatNames.add((String) team.get("team-name"));
|
if (boatsAdded < numberOfBoats){
|
||||||
|
boatNames.add((String) team.get("team-name"));
|
||||||
|
race.addBoat(new Boat(team.get("team-name").toString(), (Double) (team.get("velocity"))));
|
||||||
|
}
|
||||||
|
boatsAdded++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shuffle team names
|
// Shuffle team names
|
||||||
@@ -72,11 +77,6 @@ public class RaceController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add boats to the race
|
|
||||||
for (int i = 0; i < numberOfBoats; i++) {
|
|
||||||
race.addBoat(new Boat(boatNames.get(i), (Double) (teams.get(i).get("velocity"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
CourseParser cp = new CourseParser("doc/examples/course.xml");
|
CourseParser cp = new CourseParser("doc/examples/course.xml");
|
||||||
race.addCourse(cp.getCourse());
|
race.addCourse(cp.getCourse());
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package seng302.controllers;
|
||||||
|
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.layout.AnchorPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import seng302.models.Race;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ptg19 on 20/03/17.
|
||||||
|
*/
|
||||||
|
public class RaceResultController implements Initializable{
|
||||||
|
@FXML private AnchorPane window;
|
||||||
|
@FXML private VBox resultsVBox;
|
||||||
|
private Race race;
|
||||||
|
|
||||||
|
RaceResultController(Race race){
|
||||||
|
this.race = race;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
int boatPosition = this.race.getFinishedBoats().length;
|
||||||
|
|
||||||
|
for (int i = this.race.getFinishedBoats().length - 1; i >= 0; i--){
|
||||||
|
resultsVBox.getChildren().add(0, new Text(boatPosition + ": " + this.race.getFinishedBoats()[i].getTeamName()));
|
||||||
|
boatPosition--;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package seng302.controllers;
|
||||||
|
|
||||||
|
import javafx.animation.KeyFrame;
|
||||||
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.fxml.Initializable;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
import seng302.models.Race;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
public class RaceTimerController implements Initializable{
|
||||||
|
private Timeline timeline;
|
||||||
|
private Race race;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Text timerLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert seconds to a string of the format mm:ss
|
||||||
|
* @param time the time in seconds
|
||||||
|
* @return a formatted string
|
||||||
|
*/
|
||||||
|
public String convertTimeToMinutesSeconds(int time){
|
||||||
|
if (time < 0){
|
||||||
|
return String.format("-%02d:%02d", (time * -1) / 60, (time * -1)% 60);
|
||||||
|
}
|
||||||
|
return String.format("%02d:%02d", time / 60, time % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to control the race timer
|
||||||
|
* @param race the race the timer is timing
|
||||||
|
*/
|
||||||
|
public RaceTimerController(Race race){
|
||||||
|
this.race = race;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
timeline = new Timeline();
|
||||||
|
timeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
|
|
||||||
|
// Run timer update every second
|
||||||
|
timeline.getKeyFrames().add(
|
||||||
|
new KeyFrame(Duration.seconds(1),
|
||||||
|
event -> {
|
||||||
|
// Stop timer if race is finished
|
||||||
|
if (this.race.isRaceFinished()){
|
||||||
|
this.timeline.stop();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
timerLabel.setText(convertTimeToMinutesSeconds(race.getRaceTime()));
|
||||||
|
this.race.incrementRaceTime();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start the timer
|
||||||
|
timeline.playFromStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the race timer
|
||||||
|
*/
|
||||||
|
public void stop(){
|
||||||
|
timeline.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the race timer
|
||||||
|
*/
|
||||||
|
public void start(){
|
||||||
|
timeline.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package seng302.models;
|
package seng302.models;
|
||||||
|
|
||||||
import seng302.models.mark.Mark;
|
import seng302.models.mark.Mark;
|
||||||
import seng302.models.mark.SingleMark;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -40,7 +39,7 @@ public class Event {
|
|||||||
* @param eventTime, what time the event happens
|
* @param eventTime, what time the event happens
|
||||||
* @param eventBoat, the boat that the event belongs to
|
* @param eventBoat, the boat that the event belongs to
|
||||||
*/
|
*/
|
||||||
public Event(Double eventTime, Boat eventBoat, SingleMark mark1) {
|
public Event(Double eventTime, Boat eventBoat, Mark mark1) {
|
||||||
this.time = eventTime;
|
this.time = eventTime;
|
||||||
this.boat = eventBoat;
|
this.boat = eventBoat;
|
||||||
this.mark1 = mark1;
|
this.mark1 = mark1;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ public class Race {
|
|||||||
private List<Mark> course; // Marks in the race
|
private List<Mark> course; // Marks in the race
|
||||||
private long startTime = 0;
|
private long startTime = 0;
|
||||||
private double timeScale = 1;
|
private double timeScale = 1;
|
||||||
|
private boolean raceFinished = false; // Race is finished
|
||||||
|
private int raceTime = -10; // Current time in the race
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Race class containing the boats and legs in the race
|
* Race class containing the boats and legs in the race
|
||||||
@@ -104,7 +106,7 @@ public class Race {
|
|||||||
// There are no more marks after this event
|
// There are no more marks after this event
|
||||||
|
|
||||||
else{
|
else{
|
||||||
Event event = new Event(time, boat, course.get(i), course.get(i));
|
Event event = new Event(time, boat, course.get(i));
|
||||||
events.get(boat).add(event);
|
events.get(boat).add(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,15 +123,74 @@ public class Race {
|
|||||||
generateEvents();
|
generateEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the race course
|
||||||
|
* @param course a list of marks in the course
|
||||||
|
*/
|
||||||
public void addCourse(List<Mark> course) {
|
public void addCourse(List<Mark> course) {
|
||||||
this.course = course;
|
this.course = course;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of marks in the course
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public List<Mark> getCourse() {
|
public List<Mark> getCourse() {
|
||||||
return course;
|
return course;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a map of the events in the race
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public HashMap<Boat, List> getEvents() {
|
public HashMap<Boat, List> getEvents() {
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a boat as finished
|
||||||
|
* @param boat The boat that has finished the race
|
||||||
|
*/
|
||||||
|
public void setBoatFinished(Boat boat){
|
||||||
|
System.out.println(boat.getTeamName() + " finished");
|
||||||
|
this.finishingOrder.add(boat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the race as finished
|
||||||
|
*/
|
||||||
|
public void setRaceFinished(){
|
||||||
|
this.raceFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether or not the race is finished
|
||||||
|
* @return true if the race is finished
|
||||||
|
*/
|
||||||
|
public boolean isRaceFinished(){
|
||||||
|
return this.raceFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the race time
|
||||||
|
* @param raceTime the race time in seconds
|
||||||
|
*/
|
||||||
|
public void setRaceTime(int raceTime){
|
||||||
|
this.raceTime = raceTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the race time
|
||||||
|
* @return the race time in seconds
|
||||||
|
*/
|
||||||
|
public int getRaceTime(){
|
||||||
|
return this.raceTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the race time by one second
|
||||||
|
*/
|
||||||
|
public void incrementRaceTime(){
|
||||||
|
this.raceTime ++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,4 +37,12 @@ public class GateMark extends Mark {
|
|||||||
public void setSingleMark2(SingleMark singleMark2) {
|
public void setSingleMark2(SingleMark singleMark2) {
|
||||||
this.singleMark2 = singleMark2;
|
this.singleMark2 = singleMark2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double getLatitude(){
|
||||||
|
return (this.getSingleMark1().getLatitude() + this.getSingleMark2().getLatitude()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getLongitude(){
|
||||||
|
return (this.getSingleMark1().getLongitude() + this.getSingleMark2().getLongitude()) / 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package seng302.models.parsers;
|
||||||
|
|
||||||
|
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
import java.util.DoubleSummaryStatistics;
|
||||||
|
|
||||||
|
public class ConfigParser extends FileParser {
|
||||||
|
|
||||||
|
private Document doc;
|
||||||
|
|
||||||
|
public ConfigParser(String path) {
|
||||||
|
super(path);
|
||||||
|
this.doc = this.parseFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets wind direction from config file.
|
||||||
|
*
|
||||||
|
* @return a double type degree, or 0 if no value or invalid value is found
|
||||||
|
*/
|
||||||
|
public double getWindDirection() {
|
||||||
|
return getDoubleByTagName("wind-direction", 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a non negative time scale for the race
|
||||||
|
*
|
||||||
|
* @return a double type scale, or 0 if no scale or invalid scale is found
|
||||||
|
*/
|
||||||
|
public double getTimeScale() {
|
||||||
|
return getDoubleByTagName("time-scale", 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a double type number by given tag name found in xml file
|
||||||
|
*
|
||||||
|
* @param tagName a string of tag name
|
||||||
|
* @param defaultVal value returned if no value or invalid value is found
|
||||||
|
* @return value found
|
||||||
|
*/
|
||||||
|
public double getDoubleByTagName(String tagName, double defaultVal) {
|
||||||
|
double val = defaultVal;
|
||||||
|
try {
|
||||||
|
Node node = this.doc.getElementsByTagName(tagName).item(0);
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
Element element = (Element) node;
|
||||||
|
val = Double.valueOf(element.getTextContent());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a string by given tag name found in xml file
|
||||||
|
*
|
||||||
|
* @param tagName a string of tag name
|
||||||
|
* @param defaultVal a string returned if no value or invalid value is found
|
||||||
|
* @return string found
|
||||||
|
*/
|
||||||
|
public String getStringByTagName(String tagName, String defaultVal) {
|
||||||
|
String string = defaultVal;
|
||||||
|
try {
|
||||||
|
Node node = this.doc.getElementsByTagName(tagName).item(0);
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
Element element = (Element) node;
|
||||||
|
string = element.getTextContent();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +1,53 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.geometry.*?>
|
||||||
<?import javafx.scene.text.*?>
|
<?import javafx.scene.text.*?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<AnchorPane fx:id="raceResults" maxHeight="1080.0" maxWidth="1920.0" minHeight="1080.0" minWidth="1920.0" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="960.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<children>
|
<children>
|
||||||
<GridPane layoutX="444.0" layoutY="256.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<GridPane layoutX="444.0" layoutY="256.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" maxWidth="620.1734008789062" minWidth="10.0" prefWidth="493.2829895019531" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="862.0581665039062" minWidth="10.0" prefWidth="786.7170104980469" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="348.0" minHeight="10.0" prefHeight="112.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="348.0" minHeight="10.0" prefHeight="112.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="348.0" minHeight="10.0" prefHeight="99.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="348.0" minHeight="10.0" prefHeight="99.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="348.0" minHeight="7.0" prefHeight="53.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="348.0" minHeight="7.0" prefHeight="88.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="653.0" minHeight="10.0" prefHeight="62.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="348.0" minHeight="0.0" prefHeight="278.3376770019531" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="812.0" minHeight="10.0" prefHeight="753.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="653.0" minHeight="0.0" prefHeight="98.66232299804688" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="812.0" minHeight="10.0" prefHeight="418.4577941894531" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Race Results:" textAlignment="CENTER" wrappingWidth="640.244140625" GridPane.columnIndex="1" GridPane.rowIndex="3">
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Race Results:" wrappingWidth="616.5260620117188" GridPane.rowIndex="2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="45.0" />
|
<Font size="45.0" />
|
||||||
</font>
|
</font>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0" />
|
||||||
|
</GridPane.margin>
|
||||||
</Text>
|
</Text>
|
||||||
<VBox fx:id="resultsVBox" prefHeight="200.0" prefWidth="100.0" GridPane.columnIndex="1" GridPane.rowIndex="4" />
|
<VBox fx:id="resultsVBox" prefHeight="44.0" prefWidth="571.0" GridPane.rowIndex="3">
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Finish!" textAlignment="CENTER" wrappingWidth="640.0234375" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
<opaqueInsets>
|
||||||
|
<Insets />
|
||||||
|
</opaqueInsets>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets top="60.0" />
|
||||||
|
</padding></VBox>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Finish!" wrappingWidth="623.9530334472656" GridPane.rowIndex="1">
|
||||||
<font>
|
<font>
|
||||||
<Font size="75.0" />
|
<Font size="75.0" />
|
||||||
</font>
|
</font>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0" />
|
||||||
|
</GridPane.margin>
|
||||||
</Text>
|
</Text>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
|||||||
@@ -4,9 +4,8 @@
|
|||||||
<?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.MasterViewController">
|
||||||
<AnchorPane fx:id="window" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="960.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.Controller">
|
|
||||||
<children>
|
<children>
|
||||||
<fx:include source="RaceView.fxml" fx:id="raceView"/>
|
<!--<fx:include source="RaceView.fxml" fx:id="raceView"/>-->
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import javafx.scene.shape.*?>
|
||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
<?import javafx.scene.canvas.*?>
|
<?import javafx.scene.canvas.*?>
|
||||||
@@ -9,26 +11,34 @@
|
|||||||
|
|
||||||
<AnchorPane prefHeight="960.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.CanvasController">
|
<AnchorPane prefHeight="960.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.controllers.CanvasController">
|
||||||
<children>
|
<children>
|
||||||
<SplitPane dividerPositions="0.17683881064162754" prefHeight="160.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<AnchorPane fx:id="contentAnchorPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="960.0" prefWidth="1280.0" style="-fx-background-color: lightblue;" GridPane.columnIndex="1" GridPane.rowSpan="3">
|
||||||
<items>
|
<children>
|
||||||
<AnchorPane prefHeight="200.0" prefWidth="200.0">
|
<Canvas fx:id="canvas" height="960.0" style="-fx-background-color: Aqua;" width="1007.0" />
|
||||||
<children>
|
</children>
|
||||||
<Label layoutX="11.0" layoutY="259.0" text="Team Position" />
|
</AnchorPane>
|
||||||
<Label layoutX="11.0" layoutY="617.0" text="Race Log" />
|
<AnchorPane prefHeight="200.0" prefWidth="200.0" GridPane.rowSpan="3">
|
||||||
<Label layoutX="13.0" layoutY="432.0" text="Annotation toggle" />
|
<children>
|
||||||
<Label layoutX="11.0" layoutY="14.0" text="Timer" />
|
<Label layoutX="11.0" layoutY="259.0" text="Team Position" />
|
||||||
<Label layoutX="11.0" layoutY="88.0" text="Wind direction" />
|
<Label layoutX="11.0" layoutY="617.0" text="Race Log" />
|
||||||
<Button layoutX="18.0" layoutY="468.0" mnemonicParsing="false" text="Button" />
|
<Label layoutX="13.0" layoutY="432.0" text="Annotation toggle" />
|
||||||
<TextArea editable="false" layoutX="11.0" layoutY="640.0" prefHeight="306.0" prefWidth="200.0" />
|
<Label layoutX="11.0" layoutY="14.0" text="Timer" />
|
||||||
<TextArea fx:id="boatOrder" editable="false" layoutX="11.0" layoutY="280.0" prefHeight="141.0" prefWidth="200.0" />
|
<Label layoutX="11.0" layoutY="88.0" text="Wind direction" />
|
||||||
</children>
|
<Button layoutX="18.0" layoutY="468.0" mnemonicParsing="false" text="Button" />
|
||||||
</AnchorPane>
|
<TextArea editable="false" layoutX="11.0" layoutY="640.0" prefHeight="306.0" prefWidth="200.0" />
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
|
<TextArea editable="false" layoutX="11.0" layoutY="280.0" prefHeight="141.0" prefWidth="200.0" />
|
||||||
<children>
|
<Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#76baf8" layoutX="110.0" layoutY="166.0" radius="35.0" stroke="#686868" strokeType="INSIDE" strokeWidth="3.0" />
|
||||||
<Canvas fx:id="canvas" height="960.0" style="-fx-background-color: Aqua;" width="1007.0" />
|
<Text fx:id="windArrowText" fill="#686868" layoutX="86.0" layoutY="186.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↑">
|
||||||
</children>
|
<font>
|
||||||
</AnchorPane>
|
<Font name="AdobeArabic-Regular" size="55.0" />
|
||||||
</items>
|
</font>
|
||||||
</SplitPane>
|
</Text>
|
||||||
|
<Text fx:id="windDirectionText" fill="#a8a7a7" layoutX="171.0" layoutY="214.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0°" textAlignment="RIGHT">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="13.0" />
|
||||||
|
</font>
|
||||||
|
</Text>
|
||||||
|
<Pane fx:id="raceTimer" layoutX="11.0" layoutY="30.0" prefHeight="51.0" prefWidth="193.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="66.0" prefWidth="181.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
|
<children>
|
||||||
|
<Text fx:id="timerLabel" layoutY="41.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="181.0">
|
||||||
|
<font>
|
||||||
|
<Font size="34.0" />
|
||||||
|
</font>
|
||||||
|
</Text>
|
||||||
|
</children>
|
||||||
|
</Pane>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package seng302;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.controllers.RaceTimerController;
|
||||||
|
import seng302.models.Race;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
public class TestRaceTimer {
|
||||||
|
@Test
|
||||||
|
public void testPositiveTimeString(){
|
||||||
|
RaceTimerController controller = new RaceTimerController(new Race());
|
||||||
|
String result = controller.convertTimeToMinutesSeconds(61);
|
||||||
|
|
||||||
|
assertTrue(result.equals("01:01"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNegativeTimeString(){
|
||||||
|
RaceTimerController controller = new RaceTimerController(new Race());
|
||||||
|
String result = controller.convertTimeToMinutesSeconds(-61);
|
||||||
|
|
||||||
|
assertTrue(result.equals("-01:01"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package seng302.models.parsers;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Haoming on 23/03/17.
|
||||||
|
*/
|
||||||
|
public class ConfigParserTest {
|
||||||
|
|
||||||
|
private ConfigParser cp;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initializeParser() throws Exception {
|
||||||
|
cp = new ConfigParser("doc/examples/config.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getWindDirection() throws Exception {
|
||||||
|
assertEquals(135, cp.getWindDirection(), 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getTimeScale() throws Exception {
|
||||||
|
assertEquals(1.0, cp.getTimeScale(), 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDoubleByTagName() throws Exception {
|
||||||
|
assertEquals(6, cp.getDoubleByTagName("race-size", 0), 1e-10);
|
||||||
|
assertEquals(100, cp.getDoubleByTagName("noTag", 100), 1e-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStringByTagName() throws Exception {
|
||||||
|
assertEquals("AC35", cp.getStringByTagName("race-name", "11"));
|
||||||
|
assertEquals("oops", cp.getStringByTagName("noTag", "oops"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user