mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
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:
@@ -0,0 +1,11 @@
|
||||
package seng302.visualiser;
|
||||
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
|
||||
/**
|
||||
* Created by cir27 on 21/07/17.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClientSocketListener {
|
||||
void newPacket(StreamPacket packet);
|
||||
}
|
||||
@@ -8,18 +8,10 @@ import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser;
|
||||
import seng302.model.stream.packets.BoatPositionPacket;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.Message;
|
||||
@@ -29,7 +21,7 @@ import seng302.server.messages.Message;
|
||||
*/
|
||||
public class ClientToServerThread extends Thread {
|
||||
private Queue<StreamPacket> streamPackets = new ConcurrentLinkedQueue<>();
|
||||
private List<ListChangeListener<Queue<StreamPacket>>> boatPacketListeners = new ArrayList<>();
|
||||
private List<ClientSocketListener> listeners = new ArrayList<>();
|
||||
|
||||
private Socket socket;
|
||||
private InputStream is;
|
||||
@@ -78,10 +70,9 @@ public class ClientToServerThread extends Thread {
|
||||
long computedCrc = checksum.getValue();
|
||||
long packetCrc = Message.bytesToLong(getBytes(4));
|
||||
if (computedCrc == packetCrc) {
|
||||
streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
for (ListChangeListener cl : boatPacketListeners) {
|
||||
cl.onChanged();
|
||||
}
|
||||
// streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
for (ClientSocketListener csl : listeners)
|
||||
csl.newPacket(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
} else {
|
||||
System.err.println("Packet has been dropped");
|
||||
}
|
||||
@@ -114,12 +105,12 @@ public class ClientToServerThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
public void addStreamObserver (ListChangeListener<Queue<StreamPacket>> listChangeListener) {
|
||||
boatPacketListeners.add(listChangeListener);
|
||||
public void addStreamObserver (ClientSocketListener streamListener) {
|
||||
listeners.add(streamListener);
|
||||
}
|
||||
|
||||
public void removeStreamObserver (ListChangeListener<Queue<StreamPacket>> listChangeListener) {
|
||||
boatPacketListeners.remove(listChangeListener);
|
||||
public void removeStreamObserver (ClientSocketListener streamListener) {
|
||||
listeners.remove(streamListener);
|
||||
}
|
||||
|
||||
private int readByte() throws Exception {
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Point2D;
|
||||
@@ -19,22 +20,22 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.text.Text;
|
||||
import seng302.visualiser.controllers.RaceViewController;
|
||||
import seng302.model.Limit;
|
||||
import seng302.visualiser.fxObjects.BoatGroup;
|
||||
import seng302.visualiser.fxObjects.MarkGroup;
|
||||
import seng302.model.Colors;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.Boat;
|
||||
import seng302.model.map.Boundary;
|
||||
import seng302.model.map.CanvasMap;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.MarkType;
|
||||
import seng302.model.mark.SingleMark;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.model.stream.packets.BoatPositionPacket;
|
||||
import seng302.model.stream.parsers.StreamParser;
|
||||
import seng302.model.stream.parsers.xml.XMLParser;
|
||||
import seng302.model.stream.parsers.xml.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.model.stream.parsers.xml.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.model.stream.parsers.PositionUpdateData;
|
||||
import seng302.utilities.GeoPoint;
|
||||
import seng302.utilities.GeoUtility;
|
||||
|
||||
@@ -42,7 +43,7 @@ import seng302.utilities.GeoUtility;
|
||||
* Created by cir27 on 20/07/17.
|
||||
*/
|
||||
public class GameView extends Pane {
|
||||
private RaceViewController raceViewController;
|
||||
|
||||
private ObservableList<Node> gameObjects;
|
||||
private ImageView mapImage;
|
||||
|
||||
@@ -66,7 +67,9 @@ public class GameView extends Pane {
|
||||
|
||||
private List<MarkGroup> markGroups = new ArrayList<>();
|
||||
private List<BoatGroup> boatGroups = new ArrayList<>();
|
||||
private Text FPSdisplay = new Text();
|
||||
|
||||
private Text fpsDisplay = new Text();
|
||||
|
||||
private Polygon raceBorder = new Polygon();
|
||||
|
||||
//FRAME RATE
|
||||
@@ -75,44 +78,24 @@ public class GameView extends Pane {
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
|
||||
AnimationTimer timer;
|
||||
private AnimationTimer timer;
|
||||
|
||||
private enum ScaleDirection {
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
}
|
||||
|
||||
void setup(RaceViewController raceViewController) {
|
||||
this.raceViewController = raceViewController;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
raceViewController = new RaceViewController();
|
||||
public GameView () {
|
||||
gameObjects = this.getChildren();
|
||||
// create image view for map, bind panel size to image
|
||||
mapImage = new ImageView();
|
||||
gameObjects.add(mapImage);
|
||||
mapImage.fitWidthProperty().bind(this.widthProperty());
|
||||
mapImage.fitHeightProperty().bind(this.heightProperty());
|
||||
initializeTimer();
|
||||
}
|
||||
|
||||
void initializeCanvas() {
|
||||
|
||||
fitMarksToCanvas();
|
||||
drawGoogleMap();
|
||||
FPSdisplay.setLayoutX(5);
|
||||
FPSdisplay.setLayoutY(20);
|
||||
FPSdisplay.setStrokeWidth(2);
|
||||
gameObjects.add(FPSdisplay);
|
||||
gameObjects.add(raceBorder);
|
||||
initializeMarks();
|
||||
initializeBoats();
|
||||
this.widthProperty().addListener(resize -> {
|
||||
canvasWidth = this.getWidth();
|
||||
canvasHeight = this.getHeight();
|
||||
fitMarksToCanvas();
|
||||
});
|
||||
|
||||
private void initializeTimer () {
|
||||
timer = new AnimationTimer() {
|
||||
private long lastTime = 0;
|
||||
private int FPSCount = 30;
|
||||
@@ -136,24 +119,35 @@ public class GameView extends Pane {
|
||||
frameRate = 1_000_000_000.0 / elapsedNanosPerFrame;
|
||||
if (FPSCount-- == 0) {
|
||||
FPSCount = 30;
|
||||
// drawFps(frameRate.intValue());
|
||||
drawFps(frameRate.intValue());
|
||||
}
|
||||
}
|
||||
updateGroups();
|
||||
if (StreamParser.isRaceFinished()) {
|
||||
this.stop();
|
||||
}
|
||||
lastTime = now;
|
||||
}
|
||||
}
|
||||
if (StreamParser.isRaceFinished()) {
|
||||
this.stop();
|
||||
switchToFinishScreen();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void initializeCanvas() {
|
||||
|
||||
fitMarksToCanvas();
|
||||
drawGoogleMap();
|
||||
fpsDisplay.setLayoutX(5);
|
||||
fpsDisplay.setLayoutY(20);
|
||||
fpsDisplay.setStrokeWidth(2);
|
||||
gameObjects.add(fpsDisplay);
|
||||
gameObjects.add(raceBorder);
|
||||
initializeMarks();
|
||||
initializeBoats();
|
||||
this.widthProperty().addListener(resize -> {
|
||||
canvasWidth = this.getWidth();
|
||||
canvasHeight = this.getHeight();
|
||||
fitMarksToCanvas();
|
||||
});
|
||||
}
|
||||
|
||||
private void switchToFinishScreen() {
|
||||
try {
|
||||
// canvas view -> anchor pane -> grid pane -> main view
|
||||
@@ -255,28 +249,28 @@ public class GameView extends Pane {
|
||||
}
|
||||
|
||||
private void updateBoatGroup(BoatGroup boatGroup) {
|
||||
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatLocations.get(boatGroup.getRaceId());
|
||||
// giving the movementQueue a 5 packet buffer to account for slightly out of order packets
|
||||
if (movementQueue.size() > 0) {
|
||||
try {
|
||||
BoatPositionPacket positionPacket = movementQueue.take();
|
||||
// PriorityBlockingQueue<PositionUpdateData> movementQueue = StreamParser.boatLocations.get(boatGroup.getRaceId());
|
||||
// // giving the movementQueue a 5 packet buffer to account for slightly out of order packets
|
||||
// if (movementQueue.size() > 0) {
|
||||
// try {
|
||||
// PositionUpdateData positionPacket = movementQueue.take();
|
||||
Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon());
|
||||
double heading = 360.0 / 0xffff * positionPacket.getHeading();
|
||||
// double heading = 360.0 / 0xffff * positionPacket.getHeading();
|
||||
boatGroup.setDestination(
|
||||
p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(),
|
||||
positionPacket.getTimeValid(), frameRate);
|
||||
} catch (InterruptedException e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
// } catch (InterruptedException e){
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
}
|
||||
//// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void updateMarkGroup (long raceId, MarkGroup markGroup) {
|
||||
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.markLocations.get(raceId);
|
||||
PriorityBlockingQueue<PositionUpdateData> movementQueue = StreamParser.markLocations.get(raceId);
|
||||
if (movementQueue.size() > 0){
|
||||
try {
|
||||
BoatPositionPacket positionPacket = movementQueue.take();
|
||||
PositionUpdateData positionPacket = movementQueue.take();
|
||||
Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon());
|
||||
markGroup.moveMarkTo(p2d.getX(), p2d.getY(), raceId);
|
||||
} catch (InterruptedException e) {
|
||||
@@ -289,7 +283,7 @@ public class GameView extends Pane {
|
||||
* Draws all the boats.
|
||||
*/
|
||||
private void initializeBoats() {
|
||||
Map<Integer, Yacht> boats = StreamParser.getBoats();
|
||||
Map<Integer, Boat> boats = StreamParser.getBoats();
|
||||
Group wakes = new Group();
|
||||
Group trails = new Group();
|
||||
Group annotations = new Group();
|
||||
@@ -301,7 +295,7 @@ public class GameView extends Pane {
|
||||
participantIDs.add(p.getsourceID());
|
||||
}
|
||||
|
||||
for (Yacht boat : boats.values()) {
|
||||
for (Boat boat : boats.values()) {
|
||||
if (participantIDs.contains(boat.getSourceID())) {
|
||||
boat.setColour(Colors.getColor());
|
||||
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
||||
@@ -336,14 +330,9 @@ public class GameView extends Pane {
|
||||
gameObjects.addAll(markGroups);
|
||||
}
|
||||
|
||||
// private void drawFps(int fps){
|
||||
// if (raceViewController.isDisplayFps()){
|
||||
// FPSdisplay.setVisible(true);
|
||||
// FPSdisplay.setText(String.format("%d FPS", fps));
|
||||
// } else {
|
||||
// FPSdisplay.setVisible(false);
|
||||
// }
|
||||
// }
|
||||
private void drawFps(int fps){
|
||||
fpsDisplay.setText(String.format("%d FPS", fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates x and y location for every marker that fits it to the canvas the race will be
|
||||
@@ -367,7 +356,7 @@ public class GameView extends Pane {
|
||||
*/
|
||||
private void findMinMaxPoint() {
|
||||
List<Limit> sortedPoints = new ArrayList<>();
|
||||
for (Limit limit : StreamParser.getXmlObject().getRaceXML().getCourseLimit()) {
|
||||
for (Limit limit : raceData) {
|
||||
sortedPoints.add(limit);
|
||||
}
|
||||
sortedPoints.sort(Comparator.comparingDouble(Limit::getLat));
|
||||
@@ -512,4 +501,34 @@ public class GameView extends Pane {
|
||||
metersPerPixelY = dVertical / dy;
|
||||
}
|
||||
|
||||
public void setAnnotationVisibilities (boolean teamName, boolean velocity, boolean estTime,
|
||||
boolean legTime, boolean trail, boolean wake) {
|
||||
for (BoatGroup boatGroup : boatGroups) {
|
||||
boatGroup.setVisibility(teamName, velocity, estTime, legTime, trail, wake);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFPSVisibility (boolean visibility) {
|
||||
fpsDisplay.setVisible(visibility);
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty getFPSVisibilityProperty () {
|
||||
return fpsDisplay.visibleProperty();
|
||||
}
|
||||
|
||||
public void selectBoat (int boatId) {
|
||||
|
||||
}
|
||||
|
||||
public void pauseRace () {
|
||||
timer.stop();
|
||||
}
|
||||
|
||||
public void startRace () {
|
||||
timer.start();
|
||||
}
|
||||
|
||||
public void updateBorder (List<Limit> courseLimit) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.scene.text.Text;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.Boat;
|
||||
import seng302.model.stream.parsers.StreamParser;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -34,9 +34,9 @@ public class BoatAnnotations extends Group{
|
||||
private Text estTimeToNextMarkObject;
|
||||
private Text legTimeObject;
|
||||
|
||||
private Yacht boat;
|
||||
private Boat boat;
|
||||
|
||||
BoatAnnotations (Yacht boat, Color theme) {
|
||||
BoatAnnotations (Boat boat, Color theme) {
|
||||
super.setCache(true);
|
||||
this.boat = boat;
|
||||
background.setX(BACKGROUND_X);
|
||||
@@ -83,10 +83,10 @@ public class BoatAnnotations extends Group{
|
||||
}
|
||||
|
||||
void update () {
|
||||
velocityObject.setText(String.format(String.format("%.2f m/s", boat.getVelocity())));
|
||||
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
|
||||
|
||||
DateFormat format = new SimpleDateFormat("mm:ss");
|
||||
if (boat.getTimeTillNext() != null) {
|
||||
DateFormat format = new SimpleDateFormat("mm:ss");
|
||||
String timeToNextMark = format
|
||||
.format(boat.getTimeTillNext() - StreamParser.getCurrentTimeLong());
|
||||
estTimeToNextMarkObject.setText("Next mark: " + timeToNextMark);
|
||||
@@ -95,7 +95,6 @@ public class BoatAnnotations extends Group{
|
||||
}
|
||||
|
||||
if (boat.getMarkRoundTime() != null) {
|
||||
DateFormat format = new SimpleDateFormat("mm:ss");
|
||||
String elapsedTime = format
|
||||
.format(StreamParser.getCurrentTimeLong() - boat.getMarkRoundTime());
|
||||
legTimeObject.setText("Last mark: " + elapsedTime);
|
||||
|
||||
@@ -10,12 +10,12 @@ import javafx.scene.shape.Line;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import seng302.visualiser.controllers.GameViewController;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.Boat;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.SingleMark;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.parsers.StreamParser;
|
||||
|
||||
/**
|
||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||
@@ -38,7 +38,7 @@ public class BoatGroup extends Group {
|
||||
private Double lastRotation = 0.0;
|
||||
private long framesToMove;
|
||||
//Graphical objects
|
||||
private Yacht boat;
|
||||
private Boat boat;
|
||||
private Group lineGroup = new Group();
|
||||
private Polygon boatPoly;
|
||||
private Wake wake;
|
||||
@@ -58,7 +58,7 @@ public class BoatGroup extends Group {
|
||||
* to tell which BoatGroup to update.
|
||||
* @param color The colour of the boat polygon and the trailing line.
|
||||
*/
|
||||
public BoatGroup(Yacht boat, Color color) {
|
||||
public BoatGroup(Boat boat, Color color) {
|
||||
destinationSet = false;
|
||||
this.boat = boat;
|
||||
initChildren(color);
|
||||
@@ -74,7 +74,7 @@ public class BoatGroup extends Group {
|
||||
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat
|
||||
* polygon.
|
||||
*/
|
||||
public BoatGroup(Yacht boat, Color color, double... points) {
|
||||
public BoatGroup(Boat boat, Color color, double... points) {
|
||||
destinationSet = false;
|
||||
this.boat = boat;
|
||||
initChildren(color, points);
|
||||
@@ -258,15 +258,9 @@ public class BoatGroup extends Group {
|
||||
boat is travelling into the wind. thus upwind. Otherwise if they are on different sides, then the boat is going
|
||||
with the wind.
|
||||
*/
|
||||
if (boatLineFuncResult == windLineFuncResult) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return boatLineFuncResult.equals(windLineFuncResult);
|
||||
}
|
||||
|
||||
|
||||
public void setIsSelected(Boolean isSelected) {
|
||||
this.isSelected = isSelected;
|
||||
setLineGroupVisible(isSelected);
|
||||
@@ -275,7 +269,9 @@ public class BoatGroup extends Group {
|
||||
setLayLinesVisible(isSelected);
|
||||
}
|
||||
|
||||
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime, boolean trail, boolean wake) {
|
||||
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime,
|
||||
boolean trail, boolean wake) {
|
||||
|
||||
boatAnnotations.setVisibile(teamName, velocity, estTime, legTime);
|
||||
this.wake.setVisible(wake);
|
||||
this.lineGroup.setVisible(trail);
|
||||
@@ -306,7 +302,7 @@ public class BoatGroup extends Group {
|
||||
return laylines;
|
||||
}
|
||||
|
||||
public Yacht getBoat() {
|
||||
public Boat getBoat() {
|
||||
return boat;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user