mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
The axis is labeled correctly and is scaled accordingly.
The sparkline should work from the start of a race now also. We now have the boat in first place listed at the top along with the axis labeling and marking matching the position (eg, 1st at top. 6th at bottom). Boats picked up on the visualiser park way through the race are able to added and drawn onto the sparkline. #story[952]
This commit is contained in:
@@ -62,8 +62,9 @@ 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 = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941, "RaceStream");
|
||||||
|
// sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.start();
|
sr.start();
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.geometry.Side;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.chart.LineChart;
|
import javafx.scene.chart.LineChart;
|
||||||
|
import javafx.scene.chart.NumberAxis;
|
||||||
import javafx.scene.chart.XYChart;
|
import javafx.scene.chart.XYChart;
|
||||||
import javafx.scene.chart.XYChart.Series;
|
import javafx.scene.chart.XYChart.Series;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
@@ -33,14 +35,18 @@ import seng302.models.stream.StreamParser;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Created by ptg19 on 29/03/17.
|
* Created by ptg19 on 29/03/17.
|
||||||
*/
|
*/
|
||||||
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
|
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
|
||||||
|
|
||||||
|
@FXML
|
||||||
public LineChart raceSparkLine;
|
private LineChart raceSparkLine;
|
||||||
|
@FXML
|
||||||
|
private NumberAxis sparklineYAxis;
|
||||||
@FXML
|
@FXML
|
||||||
private VBox positionVbox;
|
private VBox positionVbox;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -65,11 +71,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
private Timeline timerTimeline;
|
private Timeline timerTimeline;
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
private static HashMap<Integer, Series<String, Double>> sparkLineData = new HashMap<>();
|
private static HashMap<Integer, Series<String, Double>> sparkLineData = new HashMap<>();
|
||||||
private ArrayList<String> positions;
|
private static ArrayList<Yacht> racingBoats = new ArrayList<>();
|
||||||
private int time;
|
|
||||||
|
|
||||||
private int index = 0;
|
|
||||||
|
|
||||||
private ImportantAnnotationsState importantAnnotations;
|
private ImportantAnnotationsState importantAnnotations;
|
||||||
private Yacht selectedBoat;
|
private Yacht selectedBoat;
|
||||||
|
|
||||||
@@ -77,12 +79,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
importantAnnotations = new ImportantAnnotationsState();
|
importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
//Initialise race controller
|
//Format the yaxis of the sparkline
|
||||||
RaceController raceController = new RaceController();
|
raceSparkLine.getYAxis().setRotate(180);
|
||||||
raceController.initializeRace();
|
raceSparkLine.getYAxis().setTickLabelRotation(180);
|
||||||
race = raceController.getRace();
|
raceSparkLine.getYAxis().setTranslateX(15);
|
||||||
positions = new ArrayList<>();
|
raceSparkLine.getYAxis().setAutoRanging(false);
|
||||||
startingBoats = new ArrayList<>(Arrays.asList(race.getBoats()));
|
|
||||||
|
startingBoats = new ArrayList<>(StreamParser.getBoats().values());
|
||||||
|
|
||||||
includedCanvasController.setup(this);
|
includedCanvasController.setup(this);
|
||||||
includedCanvasController.initializeCanvas();
|
includedCanvasController.initializeCanvas();
|
||||||
@@ -91,12 +94,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
initialiseAnnotationSlider();
|
initialiseAnnotationSlider();
|
||||||
initialiseBoatSelectionComboBox();
|
initialiseBoatSelectionComboBox();
|
||||||
includedCanvasController.timer.start();
|
includedCanvasController.timer.start();
|
||||||
time = 0;
|
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
|
||||||
selectAnnotationBtn.setOnAction(event -> {
|
|
||||||
loadSelectAnnotationView();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -106,6 +107,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations
|
setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the "select annotations" view in a new window
|
* Loads the "select annotations" view in a new window
|
||||||
*/
|
*/
|
||||||
@@ -143,6 +145,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
(observable, oldValue, newValue) -> displayFps = !displayFps);
|
(observable, oldValue, newValue) -> displayFps = !displayFps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initialiseAnnotationSlider() {
|
private void initialiseAnnotationSlider() {
|
||||||
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
||||||
@Override
|
@Override
|
||||||
@@ -182,50 +185,65 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
annotationSlider.setValue(2);
|
annotationSlider.setValue(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateSparkLine(){
|
void updateSparkLine(){
|
||||||
ArrayList<Yacht> sparkLineCandidates = new ArrayList<>();
|
// Goes through and collects the racing boats that aren't already in the chart
|
||||||
for (Yacht yacht: startingBoats){
|
ArrayList<Yacht> sparkLineCandidates = startingBoats.stream().filter(yacht -> !sparkLineData.containsKey(yacht.getSourceID())
|
||||||
if (!sparkLineData.containsKey(yacht.getSourceID()) && yacht.getPosition() != "-") {
|
&& yacht.getPosition() != null & yacht.getPosition() != "-").collect(Collectors.toCollection(ArrayList::new));
|
||||||
sparkLineCandidates.add(yacht);
|
|
||||||
}
|
racingBoats = startingBoats.stream().filter(yacht ->
|
||||||
}
|
yacht.getPosition() != null & yacht.getPosition() != "-").collect(Collectors.toCollection(ArrayList::new));
|
||||||
for (Yacht yacht: sparkLineCandidates){
|
|
||||||
XYChart.Series<String, Double> yachtData = new XYChart.Series<>();
|
// Creates new data series for boats to the data series on the line chart
|
||||||
|
sparkLineCandidates.stream().filter(yacht -> yacht.getPosition() != null).forEach(yacht -> {
|
||||||
|
Series<String, Double> yachtData = new Series<>();
|
||||||
yachtData.setName(yacht.getBoatName());
|
yachtData.setName(yacht.getBoatName());
|
||||||
yachtData.getData().add(new XYChart.Data<>(Integer.toString(yacht.getLegNumber()),1 + sparkLineCandidates.size() - Double.parseDouble(yacht.getPosition())));
|
yachtData.getData().add(new XYChart.Data<>(Integer.toString(yacht.getLegNumber()), 1 + racingBoats.size() - Double.parseDouble(yacht.getPosition())));
|
||||||
sparkLineData.put(yacht.getSourceID(), yachtData);
|
sparkLineData.put(yacht.getSourceID(), yachtData);
|
||||||
}
|
});
|
||||||
|
|
||||||
// Lambda function to sort the series in order of leg (later legs shown more to the right)
|
// Lambda function to sort the series in order of leg (later legs shown more to the right)
|
||||||
List<XYChart.Series<String, Double>> positions = new ArrayList<>(sparkLineData.values());
|
List<XYChart.Series<String, Double>> positions = new ArrayList<>(sparkLineData.values());
|
||||||
Collections.sort(positions, (o1, o2) -> {
|
Collections.sort(positions, (o1, o2) -> {
|
||||||
Integer leg1 = Integer.parseInt( ((XYChart.Data<String, Double>) o1.getData().get(o1.getData().size()-1)).getXValue());
|
Integer leg1 = Integer.parseInt(o1.getData().get(o1.getData().size()-1).getXValue());
|
||||||
Integer leg2 = Integer.parseInt( ((XYChart.Data<String, Double>) o2.getData().get(o2.getData().size()-1)).getXValue());
|
Integer leg2 = Integer.parseInt(o2.getData().get(o2.getData().size()-1).getXValue());
|
||||||
if (leg2 < leg1){
|
if (leg2 < leg1){
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
sparklineYAxis.setUpperBound(racingBoats.size() + 1);
|
||||||
|
// Adds the new data series to the sparkline
|
||||||
raceSparkLine.setCreateSymbols(false);
|
raceSparkLine.setCreateSymbols(false);
|
||||||
for (Series<String, Double> spark: positions){
|
positions.stream().filter(spark -> !raceSparkLine.getData().contains(spark)).forEach(spark -> {
|
||||||
if (!raceSparkLine.getData().contains(spark)) {
|
raceSparkLine.getData().add(spark);
|
||||||
raceSparkLine.getData().add(spark);
|
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
|
||||||
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()).toString());
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UUpdates the yachts sparkline of the desired boat and using the new leg number
|
||||||
|
* @param yacht
|
||||||
|
* @param legNumber
|
||||||
|
*/
|
||||||
public static void updateYachtPositionSparkline(Yacht yacht, Integer legNumber){
|
public static void updateYachtPositionSparkline(Yacht yacht, Integer legNumber){
|
||||||
XYChart.Series<String, Double> positionData = sparkLineData.get(yacht.getSourceID());
|
XYChart.Series<String, Double> positionData = sparkLineData.get(yacht.getSourceID());
|
||||||
positionData.getData().add(new XYChart.Data<>(Integer.toString(legNumber), 1 + sparkLineData.size() - Double.parseDouble(yacht.getPosition())));
|
positionData.getData().add(new XYChart.Data<>(Integer.toString(legNumber), 1 + racingBoats.size() - Double.parseDouble(yacht.getPosition())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets the rgb string of the boats colour to use for the chart via css
|
||||||
|
* @param boatName boat passed in to get the boats colour
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
private String getBoatColorAsRGB(String boatName){
|
private String getBoatColorAsRGB(String boatName){
|
||||||
Color color = Color.WHITE;
|
Color color = Color.WHITE;
|
||||||
for (Yacht yacht: startingBoats){
|
for (Yacht yacht: startingBoats){
|
||||||
if (yacht.getBoatName() == boatName){
|
if (Objects.equals(yacht.getBoatName(), boatName)){
|
||||||
color = yacht.getColour();
|
color = yacht.getColour();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,7 +412,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isDisplayFps() {
|
boolean isDisplayFps() {
|
||||||
return displayFps;
|
return displayFps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +473,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
break;
|
break;
|
||||||
// Important Annotations
|
// Important Annotations
|
||||||
case 1:
|
case 1:
|
||||||
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
includedCanvasController.getBoatGroups().forEach(this::setBoatGroupImportantAnnotations);
|
||||||
setBoatGroupImportantAnnotations(bg);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
// All Annotations
|
// All Annotations
|
||||||
case 2:
|
case 2:
|
||||||
@@ -501,9 +517,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean sparkLineStatus(Integer yachtId) {
|
public static boolean sparkLineStatus(Integer yachtId) {
|
||||||
if (sparkLineData.containsKey(yachtId)){
|
return sparkLineData.containsKey(yachtId);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<CategoryAxis label="Leg Number" side="BOTTOM" styleClass="spark-line-xaxis" />
|
<CategoryAxis label="Leg Number" side="BOTTOM" styleClass="spark-line-xaxis" />
|
||||||
</xAxis>
|
</xAxis>
|
||||||
<yAxis>
|
<yAxis>
|
||||||
<NumberAxis label="Position" minorTickCount="1" minorTickLength="1.0" side="LEFT" styleClass="spark-line-yaxis" tickLabelGap="1.0" tickUnit="1.0" upperBound="7.0" />
|
<NumberAxis fx:id="sparklineYAxis" minorTickCount="1" minorTickLength="1.0" side="LEFT" styleClass="spark-line-yaxis" tickLabelGap="1.0" tickUnit="1.0" upperBound="7.0" />
|
||||||
</yAxis>
|
</yAxis>
|
||||||
</LineChart>
|
</LineChart>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
Reference in New Issue
Block a user