Merge branch 'develop' into story1118_map_arrows

# Conflicts:
#	src/main/java/seng302/gameServer/MainServerThread.java
#	src/main/java/seng302/model/RaceState.java
#	src/main/java/seng302/visualiser/GameClient.java
#	src/main/java/seng302/visualiser/controllers/RaceViewController.java
This commit is contained in:
Calum
2017-08-17 00:52:41 +12:00
10 changed files with 189 additions and 96 deletions
@@ -36,7 +36,6 @@ import seng302.utilities.XMLParser;
* Created by wmu16 on 10/07/17. * Created by wmu16 on 10/07/17.
*/ */
public class GameState implements Runnable { public class GameState implements Runnable {
@FunctionalInterface @FunctionalInterface
interface NewMessageListener { interface NewMessageListener {
@@ -180,6 +179,14 @@ public class GameState implements Runnable {
return windDirection; return windDirection;
} }
public static void setWindDirection(Double newWindDirection) {
windDirection = newWindDirection;
}
public static void setWindSpeed(Double newWindSpeed) {
windSpeed = newWindSpeed;
}
public static Double getWindSpeedMMS() { public static Double getWindSpeedMMS() {
return windSpeed; return windSpeed;
} }
@@ -250,7 +257,6 @@ public class GameState implements Runnable {
} }
} }
/** /**
* Called periodically in this GameState thread to update the GameState values * Called periodically in this GameState thread to update the GameState values
*/ */
@@ -271,6 +277,8 @@ public class GameState implements Runnable {
checkForLegProgression(yacht); checkForLegProgression(yacht);
raceFinished = false; raceFinished = false;
} }
} }
if (raceFinished) { if (raceFinished) {
@@ -329,7 +337,9 @@ public class GameState implements Runnable {
notifyMessageListeners( notifyMessageListeners(
new YachtEventCodeMessage(serverYacht.getSourceId()) new YachtEventCodeMessage(serverYacht.getSourceId())
); );
} else if (checkBoundaryCollision(serverYacht)) { }
else{
if (checkBoundaryCollision(serverYacht)) {
serverYacht.setLocation( serverYacht.setLocation(
calculateBounceBack(serverYacht, serverYacht.getLocation(), calculateBounceBack(serverYacht, serverYacht.getLocation(),
BOUNCE_DISTANCE_YACHT) BOUNCE_DISTANCE_YACHT)
@@ -343,6 +353,7 @@ public class GameState implements Runnable {
} }
} }
} }
}
private void updateVelocity(ServerYacht yacht) { private void updateVelocity(ServerYacht yacht) {
@@ -426,6 +437,7 @@ public class GameState implements Runnable {
} }
if (hasProgressed) { if (hasProgressed) {
yacht.incrementLegNumber();
sendMarkRoundingMessage(yacht); sendMarkRoundingMessage(yacht);
logMarkRounding(yacht); logMarkRounding(yacht);
yacht.setHasPassedLine(false); yacht.setHasPassedLine(false);
@@ -3,17 +3,8 @@ package seng302.gameServer;
import java.io.IOException; import java.io.IOException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.*;
import java.util.List; import seng302.gameServer.server.messages.*;
import java.util.Timer;
import java.util.TimerTask;
import seng302.gameServer.messages.BoatSubMessage;
import seng302.gameServer.messages.Message;
import seng302.gameServer.messages.RaceStartNotificationType;
import seng302.gameServer.messages.RaceStartStatusMessage;
import seng302.gameServer.messages.RaceStatus;
import seng302.gameServer.messages.RaceStatusMessage;
import seng302.gameServer.messages.RaceType;
import seng302.model.GeoPoint; import seng302.model.GeoPoint;
import seng302.model.Player; import seng302.model.Player;
import seng302.model.PolarTable; import seng302.model.PolarTable;
@@ -29,12 +20,17 @@ import seng302.visualiser.GameClient;
public class MainServerThread implements Runnable, ClientConnectionDelegate { public class MainServerThread implements Runnable, ClientConnectionDelegate {
private static final int PORT = 4942; private static final int PORT = 4942;
private static final Integer CLIENT_UPDATES_PER_SECOND = 10; private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
private static final int LOG_LEVEL = 1; private static final int LOG_LEVEL = 1;
private static final int WARNING_TIME = 10 * -1000; private static final int WARNING_TIME = 10 * -1000;
private static final int PREPATORY_TIME = 5 * -1000; private static final int PREPATORY_TIME = 5 * -1000;
public static final int TIME_TILL_START = 10 * 1000; public static final int TIME_TILL_START = 10 * 1000;
private static final int MAX_WIND_SPEED = 12000;
private static final int MIN_WIND_SPEED = 8000;
public static int windSpeed = 1000;
private boolean terminated; private boolean terminated;
private Thread thread; private Thread thread;
@@ -55,6 +51,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
GameState.addMarkPassListener(this::broadcastMessage); GameState.addMarkPassListener(this::broadcastMessage);
terminated = false; terminated = false;
thread = new Thread(this, "MainServer"); thread = new Thread(this, "MainServer");
startUpdatingWind();
thread.start(); thread.start();
} }
@@ -108,6 +105,45 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
} }
} }
private static void updateWind(){
Integer direction = GameState.getWindDirection().intValue();
Integer windSpeed = GameState.getWindSpeedMMS().intValue();
Random random = new Random();
if (Math.floorMod(random.nextInt(), 2) == 0){
direction += random.nextInt(4);
windSpeed += random.nextInt(100) + 500;
}
else{
direction -= random.nextInt(4);
windSpeed -= random.nextInt(100) + 500;
}
direction = Math.floorMod(direction, 360);
if (windSpeed > MAX_WIND_SPEED){
windSpeed -= random.nextInt(1000);
}
if (windSpeed <= MIN_WIND_SPEED){
windSpeed += random.nextInt(1000);
}
GameState.setWindSpeed(Double.valueOf(windSpeed));
GameState.setWindDirection(direction.doubleValue());
}
private static void startUpdatingWind(){
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
updateWind();
}
}, 0, 500);
}
static void serverLog(String message, int logLevel) { static void serverLog(String message, int logLevel) {
if (logLevel <= LOG_LEVEL) { if (logLevel <= LOG_LEVEL) {
@@ -189,7 +225,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
for (Player player : GameState.getPlayers()) { for (Player player : GameState.getPlayers()) {
ServerYacht y = player.getYacht(); ServerYacht y = player.getYacht();
BoatSubMessage m = new BoatSubMessage(y.getSourceId(), y.getBoatStatus(), 0, BoatSubMessage m = new BoatSubMessage(y.getSourceId(), y.getBoatStatus(),
y.getLegNumber(),
0, 0, 1234L, 0, 0, 1234L,
1234L); 1234L);
boatSubMessages.add(m); boatSubMessages.add(m);
@@ -39,7 +39,7 @@ public class RaceStatusMessage extends Message{
this.raceId = raceId; this.raceId = raceId;
this.raceStatus = raceStatus; this.raceStatus = raceStatus;
this.expectedStartTime = expectedStartTime; this.expectedStartTime = expectedStartTime;
this.raceWindDirection = raceWindDirection * windDirFactor; this.raceWindDirection = raceWindDirection * windDirFactor+100.0;
this.windSpeed = windSpeed; this.windSpeed = windSpeed;
this.numBoatsInRace = numBoatsInRace; this.numBoatsInRace = numBoatsInRace;
this.raceType = raceType; this.raceType = raceType;
+9 -2
View File
@@ -38,13 +38,13 @@ public class ClientYacht extends Observable {
private Logger logger = LoggerFactory.getLogger(ClientYacht.class); private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
//BOTH AFAIK
private String boatType; private String boatType;
private Integer sourceId; private Integer sourceId;
private String hullID; //matches HullNum in the XML spec. private String hullID; //matches HullNum in the XML spec.
private String shortName; private String shortName;
private String boatName; private String boatName;
private String country; private String country;
private Integer position;
private Long estimateTimeAtFinish; private Long estimateTimeAtFinish;
private Boolean sailIn = true; private Boolean sailIn = true;
@@ -57,7 +57,6 @@ public class ClientYacht extends Observable {
private Integer boatStatus; private Integer boatStatus;
private Double currentVelocity; private Double currentVelocity;
//CLIENT SIDE
private List<YachtLocationListener> locationListeners = new ArrayList<>(); private List<YachtLocationListener> locationListeners = new ArrayList<>();
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>(); private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper(); private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
@@ -201,6 +200,14 @@ public class ClientYacht extends Observable {
return location; return location;
} }
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
public void toggleSail() { public void toggleSail() {
sailIn = !sailIn; sailIn = !sailIn;
} }
@@ -4,9 +4,15 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Observable;
import java.util.TimeZone; import java.util.TimeZone;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper; import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seng302.model.stream.parser.RaceStartData; import seng302.model.stream.parser.RaceStartData;
import seng302.model.stream.parser.RaceStatusData; import seng302.model.stream.parser.RaceStatusData;
@@ -29,10 +35,12 @@ public class RaceState {
private long expectedStartTime; private long expectedStartTime;
private boolean isRaceStarted = false; private boolean isRaceStarted = false;
long timeTillStart; long timeTillStart;
private ObservableList<ClientYacht> playerPositions;
private List<ClientYacht> collisions = new ArrayList<>(); private List<ClientYacht> collisions = new ArrayList<>();
private List<CollisionListener> collisionListeners = new ArrayList<>(); private List<CollisionListener> collisionListeners = new ArrayList<>();
public RaceState() { public RaceState() {
playerPositions = FXCollections.observableArrayList();
} }
public void updateState (RaceStatusData data) { public void updateState (RaceStatusData data) {
@@ -84,6 +92,19 @@ public class RaceState {
return isRaceStarted; return isRaceStarted;
} }
public void setBoats(Collection<ClientYacht> clientYachts) {
playerPositions.setAll(clientYachts);
}
public void sortPlayers() {
playerPositions.sort((yacht1, yacht2) -> Integer.compare(yacht2.getLegNumber(),
yacht1.getLegNumber()));
}
public ObservableList<ClientYacht> getPlayerPositions() {
return playerPositions;
}
public void storeCollision(ClientYacht yacht) { public void storeCollision(ClientYacht yacht) {
collisions.add(yacht); collisions.add(yacht);
for (CollisionListener collisionListener : collisionListeners) { for (CollisionListener collisionListener : collisionListeners) {
@@ -40,6 +40,7 @@ public class ServerYacht extends Observable {
private Double currentVelocity; private Double currentVelocity;
private Boolean isAuto; private Boolean isAuto;
private Double autoHeading; private Double autoHeading;
private Integer legNumber;
//Mark Rounding //Mark Rounding
private Integer currentMarkSeqID; private Integer currentMarkSeqID;
@@ -65,6 +66,7 @@ public class ServerYacht extends Observable {
this.heading = 120.0; //In degrees this.heading = 120.0; //In degrees
this.currentVelocity = 0d; //in mms-1 this.currentVelocity = 0d; //in mms-1
this.currentMarkSeqID = 0; this.currentMarkSeqID = 0;
this.legNumber = 0;
this.hasEnteredRoundingZone = false; this.hasEnteredRoundingZone = false;
this.hasPassedLine = false; this.hasPassedLine = false;
@@ -381,5 +383,12 @@ public class ServerYacht extends Observable {
return hasPassedLine; return hasPassedLine;
} }
public void incrementLegNumber() {
legNumber++;
}
public Integer getLegNumber() {
return legNumber;
}
} }
@@ -95,13 +95,8 @@ public class StreamParser {
boatID = bytesToLong( boatID = bytesToLong(
Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20))); Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20)));
boatStatus = (int) payload[28 + (i * 20)]; boatStatus = (int) payload[28 + (i * 20)];
// setBoatLegPosition(boat, (int) payload[29 + (i * 20)]);
// boat.setPenaltiesAwarded((int) payload[30 + (i * 20)]);
// boat.setPenaltiesServed((int) payload[31 + (i * 20)]);
estTimeAtNextMark = bytesToLong( estTimeAtNextMark = bytesToLong(
Arrays.copyOfRange(payload, 32 + (i * 20), 38 + (i * 20))); Arrays.copyOfRange(payload, 32 + (i * 20), 38 + (i * 20)));
// boat.setEstimateTimeTillNextMark(estTimeAtNextMark);
estTimeAtFinish = bytesToLong( estTimeAtFinish = bytesToLong(
Arrays.copyOfRange(payload, 38 + (i * 20), 44 + (i * 20))); Arrays.copyOfRange(payload, 38 + (i * 20), 44 + (i * 20)));
leg = (int) payload[29 + (i * 20)]; leg = (int) payload[29 + (i * 20)];
@@ -14,7 +14,8 @@ import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import seng302.gameServer.GameState; import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread; import seng302.gameServer.MainServerThread;
import seng302.gameServer.messages.BoatAction; import seng302.gameServer.server.messages.BoatAction;
import seng302.gameServer.server.messages.BoatStatus;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.RaceState; import seng302.model.RaceState;
import seng302.model.stream.packets.StreamPacket; import seng302.model.stream.packets.StreamPacket;
@@ -27,6 +28,7 @@ import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData; import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.utilities.StreamParser; import seng302.utilities.StreamParser;
import seng302.utilities.XMLParser; import seng302.utilities.XMLParser;
import seng302.visualiser.controllers.FinishScreenViewController;
import seng302.visualiser.controllers.LobbyController; import seng302.visualiser.controllers.LobbyController;
import seng302.visualiser.controllers.LobbyController.CloseStatus; import seng302.visualiser.controllers.LobbyController.CloseStatus;
import seng302.visualiser.controllers.RaceViewController; import seng302.visualiser.controllers.RaceViewController;
@@ -190,6 +192,8 @@ public class GameClient {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
FinishScreenViewController controller = fxmlLoader.getController();
controller.setFinishers(raceState.getPlayerPositions());
return fxmlLoader; return fxmlLoader;
} }
@@ -235,6 +239,7 @@ public class GameClient {
allBoatsMap.forEach((id, boat) -> allBoatsMap.forEach((id, boat) ->
clientLobbyList.add(id + " " + boat.getBoatName()) clientLobbyList.add(id + " " + boat.getBoatName())
); );
raceState.setBoats(allBoatsMap.values());
break; break;
case RACE_START_STATUS: case RACE_START_STATUS:
@@ -291,26 +296,14 @@ public class GameClient {
*/ */
private void updateMarkRounding(MarkRoundingData roundingData) { private void updateMarkRounding(MarkRoundingData roundingData) {
if (allXMLReceived()) { if (allXMLReceived()) {
ClientYacht yacht = allBoatsMap.get(roundingData.getBoatId()); ClientYacht clientYacht = allBoatsMap.get(roundingData.getBoatId());
int placing = 1; clientYacht.setMarkRoundingTime(roundingData.getTimeStamp());
// int originalPlacing = yacht.getPlacing(); clientYacht.updateTimeSinceLastMarkProperty(
for (ClientYacht otherYacht : allBoatsMap.values()) { raceState.getRaceTime() - roundingData.getTimeStamp());
if (otherYacht != yacht && yacht.getLegNumber() + 1 <= otherYacht.getLegNumber()) { clientYacht.setLastMarkRounded(
placing++; courseData.getCompoundMarks().get(
} roundingData.getMarkId()
} )
// if (placing != originalPlacing) {
yacht.setPlacing(placing);
for (ClientYacht otherYacht : allBoatsMap.values()) {
if (otherYacht.getPlacing() < placing) {
otherYacht.setPlacing(otherYacht.getPlacing() + 1);
}
}
// }
yacht.roundMark(
courseData.getCompoundMarks().get(roundingData.getMarkId()),
roundingData.getTimeStamp(),
raceState.getRaceTime() - roundingData.getTimeStamp()
); );
} }
} }
@@ -320,34 +313,35 @@ public class GameClient {
raceState.updateState(data); raceState.updateState(data);
boolean raceFinished = true; boolean raceFinished = true;
for (ClientYacht yacht : allBoatsMap.values()) { for (ClientYacht yacht : allBoatsMap.values()) {
if (yacht.getBoatStatus() != 3) { if (yacht.getBoatStatus() != BoatStatus.FINISHED.getCode()) {
raceFinished = false; raceFinished = false;
} }
} }
if (raceFinished == true) {
for (long[] boatData : data.getBoatData()) {
ClientYacht clientYacht = allBoatsMap.get((int) boatData[0]);
clientYacht.setEstimateTimeTillNextMark(raceState.getRaceTime() - boatData[1]);
clientYacht.setEstimateTimeAtFinish(boatData[2]);
int legNumber = (int) boatData[3];
clientYacht.setBoatStatus((int) boatData[4]);
if (legNumber != clientYacht.getLegNumber()) {
clientYacht.setLegNumber(legNumber);
updatePlayerPositions();
}
}
if (raceFinished) {
close(); close();
loadFinishScreenView(); loadFinishScreenView();
} }
for (long[] boatData : data.getBoatData()) {
ClientYacht yacht = allBoatsMap.get((int) boatData[0]);
yacht.setEstimateTimeTillNextMark(raceState.getRaceTime() - boatData[1]);
yacht.setEstimateTimeAtFinish(boatData[2]);
int legNumber = (int) boatData[3];
// yacht.setLegNumber(legNumber);
yacht.setBoatStatus((int) boatData[4]);
// if (legNumber != yacht.getLegNumber()) {
// System.out.println("WHAT THE FUCK IT WORKS????");
// int placing = 1;
// for (ClientYacht otherClientYacht : allBoatsMap.values()) {
// if (otherClientYacht.getSourceId() != boatData[0] &&
// yacht.getLegNumber() <= otherClientYacht.getLegNumber())
// placing++;
// }
// yacht.setPlacing(placing);
// }
} }
} }
private void updatePlayerPositions() {
raceState.sortPlayers();
for (ClientYacht yacht : raceState.getPlayerPositions()) {
yacht.setPosition(raceState.getPlayerPositions().indexOf(yacht) + 1);
}
} }
private void close() { private void close() {
@@ -3,6 +3,7 @@ package seng302.visualiser.controllers;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@@ -61,7 +62,7 @@ public class FinishScreenViewController implements Initializable {
finishOrderTable.refresh(); finishOrderTable.refresh();
} }
public void setFinishers(List<ClientYacht> participants) { public void setFinishers(Collection<ClientYacht> participants) {
List<ClientYacht> sorted = new ArrayList<>(participants); List<ClientYacht> sorted = new ArrayList<>(participants);
sorted.sort(Comparator.comparingInt(ClientYacht::getPlacing)); sorted.sort(Comparator.comparingInt(ClientYacht::getPlacing));
finishOrderTable.getItems().setAll(sorted); finishOrderTable.getItems().setAll(sorted);
@@ -11,6 +11,8 @@ import java.util.concurrent.TimeUnit;
import javafx.animation.Timeline; import javafx.animation.Timeline;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
@@ -73,6 +75,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private ComboBox<ClientYacht> yachtSelectionComboBox; private ComboBox<ClientYacht> yachtSelectionComboBox;
@FXML @FXML
private Text fpsDisplay; private Text fpsDisplay;
@FXML
private Text windSpeedText;
//Race Data //Race Data
private Map<Integer, ClientYacht> participants; private Map<Integer, ClientYacht> participants;
private Map<Integer, CompoundMark> markers; private Map<Integer, CompoundMark> markers;
@@ -102,8 +107,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
} }
public void loadRace ( public void loadRace (
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState, ClientYacht player Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
) { ClientYacht player) {
this.participants = participants; this.participants = participants;
this.courseData = raceData; this.courseData = raceData;
this.markers = raceData.getCompoundMarks(); this.markers = raceData.getCompoundMarks();
@@ -115,6 +121,15 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
initialiseBoatSelectionComboBox(); initialiseBoatSelectionComboBox();
initialiseSparkLine(); initialiseSparkLine();
raceState.getPlayerPositions().addListener((ListChangeListener<ClientYacht>) c -> {
while (c.next()) {
if (c.wasPermutated()) {
updateOrder(raceState.getPlayerPositions());
}
}
});
updateOrder(raceState.getPlayerPositions());
gameView = new GameView(); gameView = new GameView();
gameView.setFrameRateFXText(fpsDisplay); gameView.setFrameRateFXText(fpsDisplay);
Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView)); Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView));
@@ -126,6 +141,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
gameView.enableZoom(); gameView.enableZoom();
gameView.setBoatAsPlayer(player); gameView.setBoatAsPlayer(player);
gameView.startRace(); gameView.startRace();
raceState.addCollisionListener(gameView::drawCollision); raceState.addCollisionListener(gameView::drawCollision);
raceState.windDirectionProperty().addListener((obs, oldDirection, newDirection) -> { raceState.windDirectionProperty().addListener((obs, oldDirection, newDirection) -> {
gameView.setWindDir(newDirection.doubleValue()); gameView.setWindDir(newDirection.doubleValue());
@@ -279,7 +295,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* @param yacht The yacht to be updated on the sparkline * @param yacht The yacht to be updated on the sparkline
* @param legNumber the leg number that the position will be assigned to * @param legNumber the leg number that the position will be assigned to
*/ */
void updateClientYachtPositionSparkline(ClientYacht yacht, Integer legNumber){ void updateYachtPositionSparkline(ClientYacht yacht, Integer legNumber){
for (XYChart.Series<String, Double> positionData : sparkLineData) { for (XYChart.Series<String, Double> positionData : sparkLineData) {
positionData.getData().add( positionData.getData().add(
new Data<>( new Data<>(
@@ -363,9 +379,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* Updates the wind direction arrow and text as from info from the StreamParser * Updates the wind direction arrow and text as from info from the StreamParser
* @param direction the from north angle of the wind. * @param direction the from north angle of the wind.
*/ */
private void updateWindDirection(double direction) { private void updateWind() {
windDirectionText.setText(String.format("%.1f°", direction)); windDirectionText.setText(String.format("%.1f°", raceState.getWindDirection()));
windArrowText.setRotate(direction); windArrowText.setRotate(raceState.getWindDirection());
windSpeedText.setText("Speed: " + String.format("%.1f", raceState.getWindSpeed()) + " Knots");
} }
@@ -385,21 +402,20 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* Updates the order of the yachts as from the StreamParser and sets them in the yacht order * Updates the order of the yachts as from the StreamParser and sets them in the yacht order
* section * section
*/ */
private void updateOrder() { private void updateOrder(ObservableList<ClientYacht> yachts) {
List<ClientYacht> sorted = new ArrayList<>(participants.values());
sorted.sort(Comparator.comparingInt(ClientYacht::getPlacing));
List<Text> vboxEntries = new ArrayList<>(); List<Text> vboxEntries = new ArrayList<>();
for (ClientYacht yacht : sorted) { for (int i = 0; i < yachts.size(); i++) {
if (yacht.getBoatStatus() == 3) { // 3 is finish status // System.out.println("yacht == null " + String.valueOf(yacht == null));
Text textToAdd = new Text(yacht.getPlacing() + ". " + if (yachts.get(i).getBoatStatus() == 3) { // 3 is finish status
yacht.getShortName() + " (Finished)"); Text textToAdd = new Text(i + 1 + ". " +
yachts.get(i).getShortName() + " (Finished)");
textToAdd.setFill(Paint.valueOf("#d3d3d3")); textToAdd.setFill(Paint.valueOf("#d3d3d3"));
vboxEntries.add(textToAdd); vboxEntries.add(textToAdd);
} else { } else {
Text textToAdd = new Text(yacht.getPlacing() + ". " + Text textToAdd = new Text(i + 1 + ". " +
yacht.getShortName() + " "); yachts.get(i).getShortName() + " ");
textToAdd.setFill(Paint.valueOf("#d3d3d3")); textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle(""); textToAdd.setStyle("");
vboxEntries.add(textToAdd); vboxEntries.add(textToAdd);
@@ -476,16 +492,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
} }
private Point2D getPointRotation(Point2D ref, Double distance, Double angle){ private Point2D getPointRotation(Point2D ref, Double distance, Double angle) {
Double newX = ref.getX() + (ref.getX() + distance -ref.getX())*Math.cos(angle) - (ref.getY() + distance -ref.getY())*Math.sin(angle); Double newX = ref.getX() + (ref.getX() + distance - ref.getX()) * Math.cos(angle)
Double newY = ref.getY() + (ref.getX() + distance -ref.getX())*Math.sin(angle) + (ref.getY() + distance -ref.getY())*Math.cos(angle); - (ref.getY() + distance - ref.getY()) * Math.sin(angle);
Double newY = ref.getY() + (ref.getX() + distance - ref.getX()) * Math.sin(angle)
+ (ref.getY() + distance - ref.getY()) * Math.cos(angle);
return new Point2D(newX, newY); return new Point2D(newX, newY);
} }
public Line makeLeftLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) { public Line makeLeftLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) {
Point2D ep = getPointRotation(startPoint, 50.0, baseAngle + layLineAngle); Point2D ep = getPointRotation(startPoint, 50.0, baseAngle + layLineAngle);
Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY()); Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY());
return line; return line;