Parsing classes now static utilities. Data now moved to model via controller class. Race logic shifted out of grpahics classes. Several improvements to code readability.

#story[986] #refactor
This commit is contained in:
Calum
2017-07-24 12:14:08 +12:00
parent 3ec1242a9a
commit aad93d8913
33 changed files with 1515 additions and 1682 deletions
@@ -15,24 +15,24 @@ import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import seng302.model.Yacht;
import seng302.model.stream.StreamParser;
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
import seng302.model.Boat;
import seng302.model.stream.parsers.StreamParser;
import seng302.model.stream.parsers.xml.XMLParser.RaceXMLObject.Participant;
public class FinishScreenViewController implements Initializable {
@FXML
private GridPane finishScreenGridPane;
@FXML
private TableView<Yacht> finishOrderTable;
private TableView<Boat> finishOrderTable;
@FXML
private TableColumn<Yacht, String> posCol;
private TableColumn<Boat, String> posCol;
@FXML
private TableColumn<Yacht, String> boatNameCol;
private TableColumn<Boat, String> boatNameCol;
@FXML
private TableColumn<Yacht, String> shortNameCol;
private TableColumn<Boat, String> shortNameCol;
@FXML
private TableColumn<Yacht, String> countryCol;
private TableColumn<Boat, String> countryCol;
@Override
public void initialize(URL location, ResourceBundle resources) {
@@ -41,7 +41,7 @@ public class FinishScreenViewController implements Initializable {
finishOrderTable.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// set up data for table
ObservableList<Yacht> data = FXCollections.observableArrayList();
ObservableList<Boat> data = FXCollections.observableArrayList();
finishOrderTable.setItems(data);
// setting table col data
@@ -67,7 +67,7 @@ public class FinishScreenViewController implements Initializable {
}
// add data to table
for (Yacht boat : StreamParser.getBoatsPos().values()) {
for (Boat boat : StreamParser.getBoatsPos().values()) {
if (participantIDs.contains(boat.getSourceID())) {
data.add(boat);
}
@@ -27,7 +27,10 @@ import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import javafx.util.StringConverter;
import seng302.model.Corner;
import seng302.model.stream.parsers.xml.RaceXMLData;
import seng302.utilities.GeoUtility;
import seng302.visualiser.GameView;
import seng302.visualiser.controllers.annotations.Annotation;
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
@@ -38,13 +41,11 @@ import seng302.model.*;
import seng302.model.mark.GateMark;
import seng302.model.mark.Mark;
import seng302.model.mark.SingleMark;
import seng302.model.stream.StreamParser;
import seng302.model.stream.XMLParser;
import seng302.model.stream.parsers.StreamParser;
import java.io.IOException;
import java.util.*;
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
import java.util.stream.Collectors;
import seng302.model.stream.parsers.xml.XMLParser.RaceXMLObject.Participant;
/**
* Created by ptg19 on 29/03/17.
@@ -70,21 +71,21 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
@FXML
private Button selectAnnotationBtn;
@FXML
private ComboBox boatSelectionComboBox;
@FXML
private GameViewController gameViewController;
private ComboBox<Boat> boatSelectionComboBox;
//Race Data
private Map<Integer, Boat> participants;
private Map<Integer, Mark> course;
private RaceXMLData raceData;
private GameView gameView;
private static ArrayList<Yacht> startingBoats = new ArrayList<>();
private boolean displayFps;
private Timeline timerTimeline;
private Stage stage;
private static HashMap<Integer, Series<String, Double>> sparkLineData = new HashMap<>();
private static ArrayList<Yacht> racingBoats = new ArrayList<>();
private HashMap<Integer, Series<String, Double>> sparkLineData = new HashMap<>();
private ImportantAnnotationsState importantAnnotations;
private Yacht selectedBoat;
private Boat selectedBoat;
public void initialize() {
// Load a default important annotation state
importantAnnotations = new ImportantAnnotationsState();
@@ -94,19 +95,22 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
raceSparkLine.getYAxis().setTranslateX(-5);
raceSparkLine.getYAxis().setAutoRanging(false);
sparklineYAxis.setTickMarkVisible(false);
startingBoats = new ArrayList<>(StreamParser.getBoats().values());
gameViewController.setup(this);
gameViewController.initializeCanvas();
initializeUpdateTimer();
initialiseFPSCheckBox();
initialiseAnnotationSlider();
initialiseBoatSelectionComboBox();
gameViewController.timer.start();
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
}
public void loadRace (Map<Integer, Boat> participants, RaceXMLData raceData) {
this.participants = participants;
this.raceData = raceData;
this.course = raceData.getCompoundMarks();
gameView = new GameView();
gameView.startRace();
}
/**
* The important annotations have been changed, update this view
@@ -126,33 +130,30 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
try {
FXMLLoader fxmlLoader = new FXMLLoader();
Stage stage = new Stage();
// Set controller
ImportantAnnotationController controller = new ImportantAnnotationController(this,
stage);
ImportantAnnotationController controller = new ImportantAnnotationController(
this, stage
);
fxmlLoader.setController(controller);
// Load FXML and set CSS
fxmlLoader
.setLocation(getClass().getResource("/views/importantAnnotationSelectView.fxml"));
fxmlLoader.setLocation(
getClass().getResource("/views/importantAnnotationSelectView.fxml")
);
Scene scene = new Scene(fxmlLoader.load(), 469, 298);
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
stage.initStyle(StageStyle.UNDECORATED);
stage.setScene(scene);
stage.show();
controller.loadState(importantAnnotations);
} catch (IOException e) {
e.printStackTrace();
}
}
private void initialiseFPSCheckBox() {
displayFps = true;
toggleFps.selectedProperty().addListener(
(observable, oldValue, newValue) -> displayFps = !displayFps);
toggleFps.selectedProperty().addListener((obs, oldVal, newVal) ->
gameView.setFPSVisibility(toggleFps.isSelected())
);
}
private void initialiseAnnotationSlider() {
@@ -189,8 +190,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
});
annotationSlider.valueProperty().addListener((obs, oldval, newVal) ->
setAnnotations((int) annotationSlider.getValue()));
setAnnotations((int) annotationSlider.getValue())
);
annotationSlider.setValue(2);
}
@@ -198,21 +199,21 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
/**
* Used to add any new boats into the race that may have started late or not have had data received yet
*/
void updateSparkLine(){
private void updateSparkLine(){
// Collect the racing boats that aren't already in the chart
ArrayList<Yacht> sparkLineCandidates = startingBoats.stream().filter(yacht -> !sparkLineData.containsKey(yacht.getSourceID())
&& yacht.getPosition() != null & yacht.getPosition() != "-").collect(Collectors.toCollection(ArrayList::new));
List<Boat> sparkLineCandidates = new ArrayList<>();
participants.forEach((id, boat) ->{
if (!sparkLineData.containsKey(id) && boat.getPosition() != null && !boat.getPosition().equals("-"))
sparkLineCandidates.add(boat);
});
// Obtain the qualifying boats to set the max on the Y axis
racingBoats = startingBoats.stream().filter(yacht ->
yacht.getPosition() != null & yacht.getPosition() != "-").collect(Collectors.toCollection(ArrayList::new));
sparklineYAxis.setUpperBound(racingBoats.size() + 1);
sparklineYAxis.setUpperBound(participants.size() + 1);
// Create a new data series for new boats
sparkLineCandidates.stream().filter(yacht -> yacht.getPosition() != null).forEach(yacht -> {
Series<String, Double> yachtData = new Series<>();
yachtData.setName(yacht.getBoatName());
yachtData.getData().add(new XYChart.Data<>(Integer.toString(yacht.getLegNumber()), 1 + racingBoats.size() - Double.parseDouble(yacht.getPosition())));
yachtData.setName(yacht.getSourceID().toString());
yachtData.getData().add(new XYChart.Data<>(Integer.toString(yacht.getLegNumber()), 1 + participants.size() - Double.parseDouble(yacht.getPosition())));
sparkLineData.put(yacht.getSourceID(), yachtData);
});
@@ -230,48 +231,52 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// Adds the new data series to the sparkline (and set the colour of the series)
raceSparkLine.setCreateSymbols(false);
positions.stream().filter(spark -> !raceSparkLine.getData().contains(spark)).forEach(spark -> {
raceSparkLine.getData().add(spark);
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
});
positions
.stream()
.filter(spark -> !raceSparkLine.getData().contains(spark))
.forEach(spark -> {
raceSparkLine.getData().add(spark);
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
});
}
/**
* Updates the yachts sparkline of the desired boat and using the new leg number
* @param yacht The yacht to be updated on the sparkline
* @param boat The yacht to be updated on the sparkline
* @param legNumber the leg number that the position will be assigned to
*/
public static void updateYachtPositionSparkline(Yacht yacht, Integer legNumber){
XYChart.Series<String, Double> positionData = sparkLineData.get(yacht.getSourceID());
positionData.getData().add(new XYChart.Data<>(Integer.toString(legNumber), 1 + racingBoats.size() - Double.parseDouble(yacht.getPosition())));
public void updateYachtPositionSparkline(Boat boat, Integer legNumber){
XYChart.Series<String, Double> positionData = sparkLineData.get(boat.getSourceID());
positionData.getData().add(
new XYChart.Data<>(
Integer.toString(legNumber),
1 + participants.size() - Double.parseDouble(boat.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
* @param boatId id of boat passed in to get the boats colour
* @return the colour as an rgb string
*/
private String getBoatColorAsRGB(String boatName){
Color color = Color.WHITE;
for (Yacht yacht: startingBoats){
if (Objects.equals(yacht.getBoatName(), boatName)){
color = yacht.getColour();
}
}
private String getBoatColorAsRGB(String boatId){
Color color = participants.get(Integer.valueOf(boatId)).getColour();
if (color == null){
return String.format( "#%02X%02X%02X",255,255,255);
return String.format("#%02X%02X%02X",255,255,255);
}
return String.format( "#%02X%02X%02X",
(int)( color.getRed() * 255 ),
(int)( color.getGreen() * 255 ),
(int)( color.getBlue() * 255 ) );
(int)( color.getBlue() * 255 )
);
}
/**
* Initalises a timer which updates elements of the RaceView such as wind direction, boat
* Initialises 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
*/
@@ -286,9 +291,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
updateWindDirection();
updateOrder();
updateBoatSelectionComboBox();
updateSparkLine();
})
);
// Start the timer
timerTimeline.playFromStart();
}
@@ -302,9 +307,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* @return The next Mark or null if none found
*/
private Mark getNextMark(BoatGroup bg) {
Integer legNumber = bg.getBoat().getLegNumber();
List<XMLParser.RaceXMLObject.Corner> markSequence = StreamParser.getXmlObject().getRaceXML().getCompoundMarkSequence();
Integer legNumber = bg.getBoat().getLegNumber();
List<Corner> markSequence = raceData.getMarkSequence();
if (legNumber == 0) {
return null;
@@ -312,18 +317,11 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
return null;
}
for (XMLParser.RaceXMLObject.Corner corner : markSequence) {
for (Corner corner : markSequence) {
if (legNumber + 2 == corner.getSeqID()) {
Integer thisCompoundMarkID = corner.getCompoundMarkID();
for (Mark mark : StreamParser.getXmlObject().getRaceXML().getAllCompoundMarks()) {
if (mark.getCompoundMarkID() == thisCompoundMarkID) {
return mark;
}
}
return raceData.getCompoundMarks().get(corner.getCompoundMarkID());
}
}
return null;
}
@@ -355,8 +353,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* in the boat selection combo box
*/
private void updateBoatSelectionComboBox() {
ObservableList<Yacht> observableBoats = FXCollections
.observableArrayList(StreamParser.getBoatsPos().values());
ObservableList<Boat> observableBoats = FXCollections.observableArrayList();
observableBoats.addAll(participants.values());
boatSelectionComboBox.setItems(observableBoats);
}
@@ -371,15 +369,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// list of racing boat id
ArrayList<Participant> participants = StreamParser.getXmlObject().getRaceXML()
.getParticipants();
ArrayList<Integer> participantIDs = new ArrayList<>();
for (Participant p : participants) {
participantIDs.add(p.getsourceID());
}
if (StreamParser.isRaceStarted()) {
for (Yacht boat : StreamParser.getBoatsPos().values()) {
for (Boat boat : StreamParser.getBoatsPos().values()) {
if (participantIDs.contains(boat.getSourceID())) { // check if the boat is racing
if (boat.getBoatStatus() == 3) { // 3 is finish status
Text textToAdd = new Text(boat.getPosition() + ". " +
@@ -397,15 +389,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
}
} else {
for (Yacht boat : StreamParser.getBoats().values()) {
if (participantIDs.contains(boat.getSourceID())) { // check if the boat is racing
Text textToAdd = new Text(boat.getPosition() + ". " +
boat.getShortName() + " ");
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle("");
positionVbox.getChildren().add(textToAdd);
}
}
participants.forEach((id, boat) ->{
Text textToAdd = new Text(boat.getPosition() + ". " +
boat.getShortName() + " ");
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle("");
positionVbox.getChildren().add(textToAdd);
});
}
}
@@ -510,8 +500,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
//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);
Boat thisBoat = (Boat) newValue;
setSelectedBoat(thisBoat);
}
});
}
@@ -529,9 +519,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
contentAnchorPane.getChildren().addAll((Pane) loader.load());
} catch (javafx.fxml.LoadException e) {
System.err.println(e.getCause());
System.err.println(e.getCause().toString());
} catch (IOException e) {
System.err.println(e);
System.err.println(e.toString());
}
}
@@ -569,37 +559,30 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
return timerString;
}
boolean isDisplayFps() {
return displayFps;
}
private void setAnnotations(Integer annotationLevel) {
switch (annotationLevel) {
// No Annotations
case 0:
for (BoatGroup bg : gameViewController.getBoatGroups()) {
bg.setVisibility(false, false, false, false, false, false);
}
gameView.setAnnotationVisibilities(
false, false, false, false, false, false
);
break;
// Important Annotations
case 1:
for (BoatGroup bg : gameViewController.getBoatGroups()) {
bg.setVisibility(
importantAnnotations.getAnnotationState(Annotation.NAME),
importantAnnotations.getAnnotationState(Annotation.SPEED),
importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
importantAnnotations.getAnnotationState(Annotation.LEGTIME),
importantAnnotations.getAnnotationState(Annotation.TRACK),
importantAnnotations.getAnnotationState(Annotation.WAKE)
);
}
gameView.setAnnotationVisibilities(
importantAnnotations.getAnnotationState(Annotation.NAME),
importantAnnotations.getAnnotationState(Annotation.SPEED),
importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
importantAnnotations.getAnnotationState(Annotation.LEGTIME),
importantAnnotations.getAnnotationState(Annotation.TRACK),
importantAnnotations.getAnnotationState(Annotation.WAKE)
);
break;
// All Annotations
case 2:
for (BoatGroup bg : gameViewController.getBoatGroups()) {
bg.setVisibility(true, true, true, true, true, true);
}
gameView.setAnnotationVisibilities(
true, true, true, true, true, true
);
break;
}
}
@@ -608,16 +591,16 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
/**
* 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
* @param boat The yacht for which we want to view all annotations
*/
private void setSelectedBoat(Yacht yacht) {
private void setSelectedBoat(Boat boat) {
for (BoatGroup bg : gameViewController.getBoatGroups()) {
//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())) {
if (bg.getBoat().getHullID().equals(boat.getHullID())) {
updateLaylines(bg);
bg.setIsSelected(true);
selectedBoat = yacht;
selectedBoat = boat;
} else {
bg.setIsSelected(false);
}
@@ -641,4 +624,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
return sparkLineData.containsKey(yachtId);
}
public void updateRaceData (RaceXMLData raceData) {
this.raceData = raceData;
gameView.updateBorder(raceData.getCourseLimit());
}
}
@@ -59,7 +59,7 @@ public class StartScreenController {
new GameState(ipAddress);
new MainServerThread().start();
ClientToServerThread clientToServerThread = new ClientToServerThread("localhost", 4950);
controller.setClientToServerThread(clientToServerThread);
// controller.setClientToServerThread(clientToServerThread);
clientToServerThread.start();
// new GameServerThread("Fuck you");
// get the lobby controller so that we can pass the game server thread to it
@@ -1,78 +1,174 @@
package seng302.visualiser.controllers.client;
import javafx.beans.value.ChangeListener;
import javafx.scene.Node;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.Pane;
import seng302.model.stream.XMLParser;
import seng302.model.Boat;
import seng302.model.mark.Mark;
import seng302.model.stream.parsers.PositionUpdateData.DeviceType;
import seng302.model.stream.parsers.MarkRoundingData;
import seng302.model.stream.parsers.RaceStartData;
import seng302.model.stream.parsers.RaceStatusData;
import seng302.model.stream.parsers.xml.RaceXMLData;
import seng302.model.stream.parsers.StreamParser;
import seng302.model.stream.parsers.xml.RegattaXMLData;
import seng302.model.stream.parsers.xml.XMLParser;
import seng302.model.stream.parsers.PositionUpdateData;
import seng302.model.stream.packets.StreamPacket;
import seng302.server.messages.BoatActionMessage;
import seng302.server.messages.BoatActionType;
import seng302.visualiser.ClientSocketListener;
import seng302.visualiser.ClientToServerThread;
import seng302.visualiser.controllers.RaceViewController;
/**
* Created by cir27 on 20/07/17.
*/
public class ClientController {
Pane holderPane;
ClientToServerThread socketThread;
private final DateFormat DATE_TIME_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
private Pane holderPane;
private ClientToServerThread socketThread;
private ClientSocketListener socketListener;
private RaceViewController raceView;
private Map<Integer, Boat> allBoatsMap;
private Map<Integer, Boat> racingBoats = new HashMap<>();
private RegattaXMLData regattaData;
private RaceXMLData raceData;
public ClientController (String ipAddress, Pane holder) {
this.holderPane = holder;
socketThread = new ClientToServerThread(ipAddress, 4950);
socketThread.start();
socketThread.waitForXML(event -> storeXMLData());
socketListener = this::parsePacket;
socketThread.addStreamObserver(socketListener);
}
private void loadRaceView () {
allBoatsMap.forEach((id, boat) -> {
if (raceData.getParticipants().contains(id))
racingBoats.put(id, boat);
});
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("RaceView.fxml"));
raceView = fxmlLoader.getController();
raceView.loadRace(racingBoats, raceData);
}
private void parsePacket(StreamPacket packet) {
try {
switch (packet.getType()) {
case HEARTBEAT:
extractHeartBeat(packet);
break;
case RACE_STATUS:
extractRaceStatus(packet);
break;
case DISPLAY_TEXT_MESSAGE:
extractDisplayMessage(packet);
break;
case XML_MESSAGE:
newRaceXmlReceived = true;
extractXmlMessage(packet);
break;
case RACE_START_STATUS:
extractRaceStartStatus(packet);
break;
case YACHT_EVENT_CODE:
extractYachtEventCode(packet);
break;
case YACHT_ACTION_CODE:
extractYachtActionCode(packet);
break;
case CHATTER_TEXT:
extractChatterText(packet);
break;
case BOAT_LOCATION:
extractBoatLocation(packet);
break;
case MARK_ROUNDING:
extractMarkRounding(packet);
break;
case COURSE_WIND:
extractCourseWind(packet);
break;
case AVG_WIND:
extractAvgWind(packet);
break;
case BOAT_ACTION:
extractBoatAction(packet);
break;
switch (packet.getType()) {
case RACE_STATUS:
processRaceStatusUpdate(StreamParser.extractRaceStatus(packet));
break;
case REGATTA_XML:
regattaData = XMLParser.parseRegatta(
StreamParser.extractXmlMessage(packet)
);
DATE_TIME_FORMAT.setTimeZone(
TimeZone.getTimeZone(
ZoneId.ofOffset("UTC", ZoneOffset.ofHours(regattaData.getUtcOffset()))
)
);
startRaceIfAllDataRecieved();
break;
case RACE_XML:
raceData = XMLParser.parseRace(
StreamParser.extractXmlMessage(packet)
);
if (raceView != null) {
raceView.updateRaceData(raceData);
}
startRaceIfAllDataRecieved();
break;
case BOAT_XML:
allBoatsMap = XMLParser.parseBoats(
StreamParser.extractXmlMessage(packet)
);
startRaceIfAllDataRecieved();
break;
case RACE_START_STATUS:
RaceStartData raceStartData = StreamParser.extractRaceStartStatus(packet);
break;
case BOAT_LOCATION:
PositionUpdateData positionData = StreamParser.extractBoatLocation(packet);
updatePosition(positionData);
break;
case MARK_ROUNDING:
MarkRoundingData roundingData = StreamParser.extractMarkRounding(packet);
updateMarkRounding(roundingData);
break;
}
}
private void startRaceIfAllDataRecieved () {
if (raceData != null && allBoatsMap != null && regattaData != null)
loadRaceView();
}
/**
* Updates the position of a boat. Boat and position are given in the provided data.
* @param positionData
*/
private void updatePosition(PositionUpdateData positionData) {
if (positionData.getType() == DeviceType.YACHT_TYPE) {
Boat boat = racingBoats.get(positionData.getDeviceId());
boat.setVelocity(positionData.getGroundSpeed());
boat.setLat(positionData.getLat());
boat.setLon(positionData.getLon());
boat.setHeading(positionData.getHeading());
} else {
Mark mark = raceData.getCompoundMarks().get(positionData.getDeviceId());
}
}
/**
* Updates the boat as having passed the mark. Boat and mark are given by the ids in the
* provided data.
* @param roundingData Contains data for the rounding of a mark.
*/
private void updateMarkRounding(MarkRoundingData roundingData) {
Boat boat = racingBoats.get(roundingData.getBoatId());
boat.setMarkRoundingTime(roundingData.getTimeStamp());
boat.setLastMarkRounded(
raceData.getCompoundMarks().get(
roundingData.getMarkId()
)
);
}
private void processRaceStatusUpdate (RaceStatusData data) {
String raceTimeStr = DATE_TIME_FORMAT.format(data.getCurrentTime());
Date date = new Date();
date.getTime();
long timeTillStart = (data.getExpectedStartTime() - data.getCurrentTime()) / 1000;
for (long[] boatData : data.getBoatData()) {
Boat boat = allBoatsMap.get((int) boatData[0]);
boat.setEstimateTimeAtNextMark(boatData[1]);
boat.setEstimateTimeAtFinish(boatData[2]);
int legNumber = (int) boatData[3];
boat.setLegNumber(legNumber);
if (legNumber != boat.getLegNumber()) {
int placing = 1;
for (Boat otherBoat : allBoatsMap.values()) {
if (otherBoat.getSourceID() != boatData[0] &&
boat.getLegNumber() <= otherBoat.getLegNumber())
placing++;
}
boat.setPosition(placing);
}
} catch (NullPointerException e) {
System.out.println("Error parsing packet");
e.printStackTrace();
}
}