re-implemented existing functionality in UI

- Correct player count is shown in server list
- Servers now advertise their capacity and number of players connected
- Players can click join on the servers in the server list
- Direct connect works
- Can set max players / server name in host dialog
- Server starts correctly when host clicked
- Implemented boat customization
- Implemented 'begin race button', and disabled it for players that aren't hosts
- Added countdown timer in lobby
- Fixed bug where app wouldn't close

Tags: #story[1245]
This commit is contained in:
Michael Rausch
2017-09-08 18:00:09 +12:00
parent b35126ff4e
commit cf4f8813d2
23 changed files with 509 additions and 346 deletions
+5 -5
View File
@@ -85,8 +85,12 @@ public class App extends Application {
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.setOnCloseRequest(e -> {
primaryStage.setOnCloseRequest(e -> closeAll());
decorator.setOnCloseButtonAction(this::closeAll);
}
private void closeAll(){
try {
ServerAdvertiser.getInstance().unregister();
} catch (IOException e1) {
@@ -94,10 +98,6 @@ public class App extends Application {
}
System.exit(0);
});
// ClientState.primaryStage = primaryStage;
primaryStage.setOnCloseRequest(e -> System.exit(0));
}
public static void main(String[] args) {
@@ -23,7 +23,6 @@ import java.util.*;
* Created by wmu16 on 10/07/17.
*/
public class GameState implements Runnable {
@FunctionalInterface
interface NewMessageListener {
@@ -33,7 +32,6 @@ public class GameState implements Runnable {
private Logger logger = LoggerFactory.getLogger(GameState.class);
private static final Integer STATE_UPDATES_PER_SECOND = 60;
public static Integer MAX_PLAYERS = 8;
public static Double ROUNDING_DISTANCE = 50d; // TODO: 14/08/17 wmu16 - Look into this value further
public static final Double MARK_COLLISION_DISTANCE = 15d;
public static final Double YACHT_COLLISION_DISTANCE = 25.0;
@@ -56,6 +54,8 @@ public class GameState implements Runnable {
private static long startTime;
private static Set<Mark> marks;
private static List<Limit> courseLimit;
private static Integer maxPlayers = 8;
private static List<NewMessageListener> markListeners;
@@ -268,8 +268,6 @@ public class GameState implements Runnable {
checkForLegProgression(yacht);
raceFinished = false;
}
}
if (raceFinished) {
@@ -685,10 +683,23 @@ public class GameState implements Runnable {
customizationFlag = false;
}
public static Integer getSpacesLeft(){
Integer numberOfPlayers = GameState.getPlayers().size();
Integer maxPlayers = GameState.MAX_PLAYERS;
public static Integer getNumberOfPlayers(){
Integer numPlayers = 0;
return maxPlayers - numberOfPlayers - 1;
for(Player p : getPlayers()){
if(p.getSocket().isConnected()){
numPlayers++;
}
}
return numPlayers;
}
public static Integer getCapacity(){
return maxPlayers;
}
public static void setMaxPlayers(Integer newMax){
maxPlayers = newMax;
}
}
@@ -50,8 +50,9 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
private ServerSocket serverSocket = null;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
private Logger logger = LoggerFactory.getLogger(MainServerThread.class);
private static Integer capacity;
private void startAdvertisingServer(){
private void startAdvertisingServer() {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
Document doc;
@@ -70,16 +71,19 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
RegattaXMLData regattaXMLData = XMLParser.parseRegatta(doc);
Integer spacesLeft = GameState.getSpacesLeft();
Integer capacity = GameState.getCapacity();
Integer numPlayers = GameState.getNumberOfPlayers();
Integer spacesLeft = capacity - numPlayers;
// No spaces left on server
if (spacesLeft < 1){
if (spacesLeft < 1) {
return;
}
// Start advertising server
try{
ServerAdvertiser.getInstance().setMapName(regattaXMLData.getCourseName()).setSpacesLeft(spacesLeft);
try {
ServerAdvertiser.getInstance().setMapName(regattaXMLData.getCourseName()).setCapacity(capacity).setNumberOfPlayers(numPlayers);
ServerAdvertiser.getInstance().registerGame(PORT, regattaXMLData.getRegattaName());
} catch (IOException e) {
logger.warn("Could not register server");
@@ -229,7 +233,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
serverToClientThread.addDisconnectListener(this::clientDisconnected);
try {
ServerAdvertiser.getInstance().setSpacesLeft(GameState.getSpacesLeft());
ServerAdvertiser.getInstance().setNumberOfPlayers(GameState.getNumberOfPlayers());
} catch (IOException e) {
logger.warn("Couldn't update advertisement");
}
@@ -261,7 +265,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
serverToClientThreads.remove(closedConnection);
try {
ServerAdvertiser.getInstance().setSpacesLeft(GameState.getSpacesLeft());
ServerAdvertiser.getInstance().setNumberOfPlayers(GameState.getNumberOfPlayers());
} catch (IOException e) {
logger.warn("Couldn't update advertisement");
}
@@ -273,7 +277,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
try {
ServerAdvertiser.getInstance().unregister();
} catch (IOException e) {
logger.warn("Error unregistered server");
logger.warn("Error unregistering server");
}
initialiseBoatPositions();
@@ -41,6 +41,8 @@ public class ServerAdvertiser {
props = new Hashtable<>();
props.put("map", "");
props.put("spacesLeft", "0");
props.put("capacity", "0");
props.put("players", "0");
}
/**
@@ -72,12 +74,27 @@ public class ServerAdvertiser {
}
/**
* Set the spaces left on the server and broadcast an update on the network
* @param spacesLeft The number of spaces left on the server
* Set the number of players on the server and broadcast an update on the network
* @param numPlayers The number of players on the server
* @return The current ServerAdvertiser instance
*/
public ServerAdvertiser setSpacesLeft(Integer spacesLeft){
props.replace("spacesLeft", spacesLeft.toString());
public ServerAdvertiser setNumberOfPlayers(Integer numPlayers){
props.replace("players", numPlayers.toString());
if (serviceInfo != null){
serviceInfo.setText(props);
}
return instance;
}
/**
* Set the max capacity of the server and broadcast an update on the network
* @param capacity The maximum capacity of the server
* @return The current ServerAdvertiser instance
*/
public ServerAdvertiser setCapacity(Integer capacity){
props.replace("capacity", capacity.toString());
if (serviceInfo != null){
serviceInfo.setText(props);
@@ -1,18 +1,20 @@
package seng302.gameServer;
public class ServerDescription {
private Integer capacity;
private String address;
private Integer portNum;
private String serverName;
private String mapName;
private Integer spacesLeft;
private Integer numPlayers;
public ServerDescription(String serverName, String mapName, Integer spacesLeft, String address, Integer portNum){
public ServerDescription(String serverName, String mapName, Integer numPlayers, Integer capacity, String address, Integer portNum){
this.serverName = serverName;
this.mapName = mapName;
this.spacesLeft = spacesLeft;
this.numPlayers = numPlayers;
this.address = address;
this.portNum = portNum;
this.capacity = capacity;
}
@@ -32,8 +34,12 @@ public class ServerDescription {
return address;
}
public Integer spacesLeft() {
return spacesLeft;
public Integer getNumPlayers() {
return numPlayers;
}
public Integer getCapacity(){
return capacity;
}
@Override
@@ -62,6 +68,10 @@ public class ServerDescription {
return false;
}
if (!this.getCapacity().equals(other.getCapacity())){
return false;
}
return true;
}
@@ -132,7 +132,7 @@ public class ServerToClientThread implements Runnable, Observer {
return;
}
if (GameState.getPlayers().size() >= GameState.MAX_PLAYERS){
if (GameState.getPlayers().size() >= GameState.getCapacity()){
RegistrationResponseMessage responseMessage = new RegistrationResponseMessage(0, RegistrationResponseStatus.FAILURE_FULL);
os.write(responseMessage.getBuffer());
return;
@@ -74,4 +74,12 @@ public class Regatta {
public Double getMagneticVariation(){
return magneticVariation;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public void setRegattaName(String regattaName) {
this.name = regattaName;
}
}
@@ -22,11 +22,11 @@ public class XMLGenerator {
private static final String BOATS_TEMPLATE_NAME = "boats.ftlh";
private static final String RACE_TEMPLATE_NAME = "race.ftlh";
private Configuration configuration;
private Regatta regatta = null;
private static Regatta regatta = null;
private Race race;
public static Regatta DEFAULT_REGATTA = new Regatta("Party Parrot Test Server " + new Random().nextInt(100),
"Bermuda Test Course",
"Bermuda",
57.6679590,
11.8503233);
@@ -167,4 +167,12 @@ public class XMLGenerator {
return result;
}
public static void setDefaultRaceName(String raceName){
DEFAULT_REGATTA.setRegattaName(raceName);
}
public static void setDefaultMapName(String mapName){
DEFAULT_REGATTA.setCourseName(mapName);
}
}
@@ -359,7 +359,7 @@ public class ClientToServerThread implements Runnable {
}
}
int getClientId () {
public int getClientId () {
return clientId;
}
}
@@ -3,6 +3,8 @@ package seng302.visualiser;
import java.io.IOException;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import javafx.application.Platform;
@@ -30,12 +32,10 @@ import seng302.model.stream.parser.YachtEventData;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.utilities.StreamParser;
import seng302.utilities.XMLGenerator;
import seng302.utilities.XMLParser;
import seng302.visualiser.controllers.FinishScreenViewController;
import seng302.visualiser.controllers.LobbyController_old;
import seng302.visualiser.controllers.*;
import seng302.visualiser.controllers.LobbyController_old.CloseStatus;
import seng302.visualiser.controllers.RaceViewController;
import seng302.visualiser.controllers.ViewManager;
/**
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
@@ -53,7 +53,7 @@ public class GameClient {
private RegattaXMLData regattaData;
private RaceXMLData courseData;
private RaceState raceState = new RaceState();
private LobbyController_old lobbyController;
private LobbyController lobbyController;
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
@@ -80,24 +80,23 @@ public class GameClient {
// Platform.runLater(this::loadStartScreen);
// });
socketThread.addStreamObserver(this::parsePackets);
ViewManager.getInstance().setPlayerList(clientLobbyList);
if (regattaData != null){
while (regattaData == null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName());
ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName());
}
else{
ViewManager.getInstance().setProperty("serverName", ipAddress);
ViewManager.getInstance().setProperty("mapName", "");
}
// TODO disable ready button;
//LobbyController_old lobbyController = loadLobby();
//lobbyController.setSocketThread(socketThread);
//lobbyController.setPlayerID(socketThread.getClientId());
@@ -107,7 +106,8 @@ public class GameClient {
// lobbyController.addCloseListener((exitCause) -> this.loadStartScreen());
// this.lobbyController = lobbyController;
this.lobbyController = ViewManager.getInstance().goToLobby(true);
} catch (IOException ioe) {
showConnectionError("Unable to find server");
//Platform.runLater(this::loadStartScreen);
@@ -119,7 +119,10 @@ public class GameClient {
* @param ipAddress IP to connect to.
* @param portNumber Port to connect to.
*/
public ServerDescription runAsHost(String ipAddress, Integer portNumber) {
public ServerDescription runAsHost(String ipAddress, Integer portNumber, String serverName, Integer maxPlayers) {
XMLGenerator.setDefaultRaceName(serverName);
GameState.setMaxPlayers(maxPlayers);
server = new MainServerThread();
try {
@@ -128,9 +131,6 @@ public class GameClient {
showConnectionError("Cannot connect to server as host");
}
String serverName = "";
String courseName = "";
while (regattaData == null){
try {
Thread.sleep(100);
@@ -139,12 +139,10 @@ public class GameClient {
}
}
this.lobbyController = ViewManager.getInstance().goToLobby(false);
ViewManager.getInstance().setPlayerList(clientLobbyList);
serverName = regattaData.getRegattaName();
courseName = regattaData.getCourseName();
return new ServerDescription(serverName, courseName, 0, ipAddress, 4942);
return new ServerDescription(serverName, regattaData.getCourseName(), GameState.getNumberOfPlayers(), GameState.getCapacity(), ipAddress, 4942);
}
private void loadStartScreen() {
@@ -232,7 +230,6 @@ public class GameClient {
switch (packet.getType()) {
case RACE_STATUS:
processRaceStatusUpdate(StreamParser.extractRaceStatus(packet));
if (raceState.getTimeTillStart() <= 5000) {
startRaceIfAllDataReceived();
}
@@ -273,7 +270,7 @@ public class GameClient {
case RACE_START_STATUS:
raceState.updateState(StreamParser.extractRaceStartStatus(packet));
if (lobbyController != null) lobbyController.updateRaceState(raceState);
if (lobbyController != null) Platform.runLater(() -> lobbyController.updateRaceState(raceState));
break;
case BOAT_LOCATION:
@@ -293,7 +290,10 @@ public class GameClient {
private void startRaceIfAllDataReceived() {
if (allXMLReceived() && raceView == null) {
loadRaceView();
raceView = ViewManager.getInstance().loadRaceView();
ClientYacht player = allBoatsMap.get(socketThread.getClientId());
raceView.loadRace(allBoatsMap, courseData, raceState, player);
}
}
@@ -379,7 +379,7 @@ public class GameClient {
* Handle the key-pressed event from the text field.
* @param e The key event triggering this call
*/
private void keyPressed(KeyEvent e) {
public void keyPressed(KeyEvent e) {
switch (e.getCode()) {
case SPACE: // align with vmg
socketThread.sendBoatAction(BoatAction.VMG); break;
@@ -393,7 +393,7 @@ public class GameClient {
}
private void keyReleased(KeyEvent e) {
public void keyReleased(KeyEvent e) {
switch (e.getCode()) {
//TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
case SHIFT: // sails in/sails out
@@ -423,4 +423,21 @@ public class GameClient {
);
}
}
public void startGame(){
server.startGame();
}
public ClientToServerThread getServerThread() {
return socketThread;
}
public List<String> getPlayerNames(){
return Collections.unmodifiableList(clientLobbyList.sorted());
}
public void stopGame() {
if (server != null) server.terminate();
if (socketThread != null) socketThread.setSocketToClose();
}
}
@@ -99,6 +99,11 @@ public class GameView extends Pane {
double scaleFactor = 1;
public void setRes(Integer x, Integer y){
this.panelHeight = y;
this.panelWidth = x;
}
private void zoomOut() {
scaleFactor = 0.1;
if (this.getScaleX() > 0.5) {
@@ -550,7 +555,7 @@ public class GameView extends Pane {
}
private void drawFps(Double fps) {
Platform.runLater(() -> fpsDisplay.setText(String.format("%d FPS", Math.round(fps))));
//Platform.runLater(() -> fpsDisplay.setText(String.format("%d FPS", Math.round(fps))));
}
/**
@@ -76,14 +76,16 @@ public class ServerListener{
String serverName = event.getInfo().getName();
String mapName = event.getInfo().getPropertyString("map");
Integer spacesLeft = Integer.parseInt(event.getInfo().getPropertyString("spacesLeft"));
ServerDescription serverDescription = new ServerDescription(serverName, mapName, spacesLeft, address, portNum);
Integer capacity = Integer.parseInt(event.getInfo().getPropertyString("capacity"));
Integer numPlayers = Integer.parseInt(event.getInfo().getPropertyString("players"));
ServerDescription serverDescription = new ServerDescription(serverName, mapName, numPlayers, capacity, address, portNum);
servers.remove(serverDescription);
servers.add(serverDescription);
delegate.serverDetected(serverDescription, new ArrayList<ServerDescription>(servers));
delegate.serverDetected(serverDescription, new ArrayList<>(servers));
}
}
@@ -108,6 +110,4 @@ public class ServerListener{
public void setDelegate(ServerListenerDelegate delegate){
this.delegate = delegate;
}
}
@@ -1,10 +1,15 @@
package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXColorPicker;
import com.jfoenix.controls.JFXTextField;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import seng302.gameServer.messages.CustomizeRequestType;
import seng302.visualiser.ClientToServerThread;
import java.net.URL;
import java.util.ResourceBundle;
@@ -14,6 +19,19 @@ public class BoatCustomizeController implements Initializable{
@FXML
private JFXColorPicker colorPicker;
@FXML
private JFXButton submitBtn;
@FXML
private JFXTextField boatName;
private ClientToServerThread socketThread;
private LobbyController lobbyController;
public BoatCustomizeController(){
}
@FXML
void colorChanged(ActionEvent event) {
Color color = colorPicker.getValue();
@@ -22,5 +40,45 @@ public class BoatCustomizeController implements Initializable{
@Override
public void initialize(URL location, ResourceBundle resources) {
colorPicker.setValue(Color.BISQUE);
submitBtn.setOnMouseReleased(event -> {
submitCustomization();
lobbyController.closeCustomizationDialog();
});
}
@FXML
public void submitCustomization() {
socketThread.sendCustomizationRequest(CustomizeRequestType.NAME, boatName.getText().getBytes());
// TODO: 16/08/17 ajm412: Turn colors into byte array.
Color color = colorPicker.getValue();
short red = (short) (color.getRed() * 255);
short green = (short) (color.getGreen() * 255);
short blue = (short) (color.getBlue() * 255);
byte[] colorArray = new byte[3];
colorArray[0] = (byte) red;
colorArray[1] = (byte) green;
colorArray[2] = (byte) blue;
socketThread.sendCustomizationRequest(CustomizeRequestType.COLOR, colorArray);
lobbyController.closeCustomizationDialog();
}
public void setPlayerName(String name) {
this.boatName.setText(name);
}
public void setPlayerColor(Color playerColor) {
this.colorPicker.setValue(playerColor);
}
public void setServerThread(ClientToServerThread ctsThread) {
this.socketThread = ctsThread;
}
public void setParentController(LobbyController lobbyController){
this.lobbyController = lobbyController;
}
}
@@ -19,8 +19,12 @@ import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import seng302.gameServer.GameStages;
import seng302.gameServer.GameState;
import seng302.model.Colors;
import seng302.model.RaceState;
import seng302.visualiser.ServerListener;
public class LobbyController implements Initializable {
@@ -31,7 +35,7 @@ public class LobbyController implements Initializable {
private ScrollPane playerListScrollpane;
@FXML
private JFXButton customizeButton, leaveLobbyButton;
private JFXButton customizeButton, leaveLobbyButton, beginRaceButton;
@FXML
private StackPane serverListMainStackPane;
@@ -43,39 +47,44 @@ public class LobbyController implements Initializable {
private Label mapName;
private List<LobbyController_old.LobbyCloseListener> lobbyListeners = new ArrayList<>();
private RaceState raceState;
private JFXDialog customizationDialog;
@Override
public void initialize(URL location, ResourceBundle resources) {
leaveLobbyButton.setOnMouseReleased(event -> leaveLobby());
beginRaceButton.setOnMouseReleased(event -> beginRace());
Platform.runLater(() -> {
serverName.setText(ViewManager.getInstance().getProperty("serverName"));
mapName.setText(ViewManager.getInstance().getProperty("mapName"));
ViewManager.getInstance().getPlayerList().addListener((ListChangeListener<String>) c -> {
Platform.runLater(this::refreshPlayerList);
});
ViewManager.getInstance().getPlayerList().addListener((ListChangeListener<String>) c -> Platform.runLater(this::refreshPlayerList));
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
});
Platform.runLater(() -> {
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
"/views/dialogs/BoatCustomizeDialog.fxml"));
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
String name = ViewManager.getInstance().getGameClient().getPlayerNames().get(playerId - 1);
try {
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
DialogTransition.CENTER);
customizeButton.setOnAction(action -> dialog.show());
} catch (IOException e) {
e.printStackTrace();
}
Color playerColor = Colors.getColor( playerId - 1);
customizationDialog = ViewManager.getInstance().loadCustomizationDialog(serverListMainStackPane, this, playerColor, name);
customizeButton.setOnMouseReleased(event -> customizationDialog.show());
});
}
private void beginRace() {
beginRaceButton.setDisable(true);
customizeButton.setDisable(true);
GameState.setCurrentStage(GameStages.PRE_RACE);
GameState.resetStartTime();
Platform.runLater(()-> ViewManager.getInstance().getGameClient().startGame());
}
private void refreshPlayerList() {
playerListVBox.getChildren().clear();
@@ -90,6 +99,7 @@ public class LobbyController implements Initializable {
try {
pane = loader.load();
} catch (IOException e) {
// TODO replace with logger
e.printStackTrace();
}
@@ -102,8 +112,21 @@ public class LobbyController implements Initializable {
GameState.setCurrentStage(GameStages.CANCELLED);
// for (LobbyController_old.LobbyCloseListener readyListener : lobbyListeners)
// readyListener.notify(LobbyController_old.CloseStatus.LEAVE);
//TODO close threads and figure out what the above lines do;
ViewManager.getInstance().getGameClient().stopGame();
ViewManager.getInstance().goToStartView();
}
public void disableReadyButton() {
this.beginRaceButton.setDisable(true);
this.beginRaceButton.setText("Waiting for host...");
}
public void updateRaceState(RaceState raceState){
this.raceState = raceState;
this.beginRaceButton.setText("Starting in: " + raceState.getRaceTimeStr());
}
public void closeCustomizationDialog() {
customizationDialog.close();
}
}
@@ -241,6 +241,7 @@ public class LobbyController_old {
readyButton.setVisible(false);
}
//TODO here newui
public void setPlayersColor(Color playerColor) {
this.playersColor = playerColor;
}
@@ -27,6 +27,7 @@ import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
@@ -64,7 +65,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
@FXML
private Text timerLabel;
@FXML
private AnchorPane contentAnchorPane;
private StackPane contentAnchorPane;
@FXML
private AnchorPane rvAnchorPane;
@FXML
private Text windArrowText, windDirectionText;
@FXML
@@ -92,19 +95,21 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
public void initialize() {
// Load a default important annotation state
importantAnnotations = new ImportantAnnotationsState();
//importantAnnotations = new ImportantAnnotationsState();
//Formatting the y axis of the sparkline
// raceSparkLine.getYAxis().setRotate(180);
// raceSparkLine.getYAxis().setTickLabelRotation(180);
// raceSparkLine.getYAxis().setTranslateX(-5);
raceSparkLine.visibleProperty().setValue(false);
raceSparkLine.getYAxis().setAutoRanging(false);
sparklineYAxis.setTickMarkVisible(false);
//raceSparkLine.visibleProperty().setValue(false);
//raceSparkLine.getYAxis().setAutoRanging(false);
//sparklineYAxis.setTickMarkVisible(false);
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
//positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
//selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
rvAnchorPane.prefWidthProperty().bind(ViewManager.getInstance().getDecorator().widthProperty());
rvAnchorPane.prefHeightProperty().bind(ViewManager.getInstance().getDecorator().heightProperty());
}
public void loadRace (
@@ -133,8 +138,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
updateOrder(raceState.getPlayerPositions());
gameView = new GameView();
gameView.setFrameRateFXText(fpsDisplay);
Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView));
//gameView.setFrameRateFXText(fpsDisplay);
Platform.runLater(() -> contentAnchorPane.getChildren().add(gameView));
gameView.setBoats(new ArrayList<>(participants.values()));
gameView.updateBorder(raceData.getCourseLimit());
gameView.updateCourse(
@@ -196,46 +201,46 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
private void initialiseFPSCheckBox() {
toggleFps.selectedProperty().addListener((obs, oldVal, newVal) ->
gameView.setFPSVisibility(toggleFps.isSelected())
);
// toggleFps.selectedProperty().addListener((obs, oldVal, newVal) ->
// gameView.setFPSVisibility(toggleFps.isSelected())
// );
}
private void initialiseAnnotationSlider() {
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
@Override
public String toString(Double n) {
if (n == 0) {
return "None";
}
if (n == 1) {
return "Important";
}
if (n == 2) {
return "All";
}
return "All";
}
@Override
public Double fromString(String s) {
switch (s) {
case "None":
return 0d;
case "Important":
return 1d;
case "All":
return 2d;
default:
return 2d;
}
}
});
annotationSlider.setValue(2);
annotationSlider.valueProperty().addListener((obs, oldVal, newVal) ->
setAnnotations((int) annotationSlider.getValue())
);
// annotationSlider.setLabelFormatter(new StringConverter<Double>() {
// @Override
// public String toString(Double n) {
// if (n == 0) {
// return "None";
// }
// if (n == 1) {
// return "Important";
// }
// if (n == 2) {
// return "All";
// }
// return "All";
// }
//
// @Override
// public Double fromString(String s) {
// switch (s) {
// case "None":
// return 0d;
// case "Important":
// return 1d;
// case "All":
// return 2d;
//
// default:
// return 2d;
// }
// }
// });
// annotationSlider.setValue(2);
// annotationSlider.valueProperty().addListener((obs, oldVal, newVal) ->
// setAnnotations((int) annotationSlider.getValue())
// );
}
@@ -243,52 +248,52 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* Used to add any new yachts into the race that may have started late or not have had data received yet
*/
private void updateSparkLine(){
// TODO: 2/08/17 there is about 0 chance of this working. Once we are keeping track of boat positions it can be fixed.
// Collect the racing yachts that aren't already in the chart
sparkLineData.clear();
List<ClientYacht> sparkLineCandidates = new ArrayList<>(participants.values());
// Create a new data series for new yachts
sparkLineCandidates
.stream()
.filter(yacht -> yacht.getPosition() != null)
.forEach(yacht -> {
Series<String, Double> yachtData = new Series<>();
yachtData.setName(yacht.getSourceId().toString());
yachtData.getData().add(
new Data<>(
Integer.toString(yacht.getLegNumber()),
1.0 + participants.size() - yacht.getPosition()
)
);
sparkLineData.add(yachtData);
});
// Lambda function to sort the series in order of leg (later legs shown more to the right)
sparkLineData.sort((o1, o2) -> {
Integer leg1 = Integer.parseInt(o1.getData().get(o1.getData().size()-1).getXValue());
Integer leg2 = Integer.parseInt(o2.getData().get(o2.getData().size()-1).getXValue());
if (leg2 < leg1){
return 1;
} else {
return -1;
}
});
// Adds the new data series to the sparkline (and set the colour of the series)
Platform.runLater(() -> {
sparkLineData
.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()));
});
});
// // TODO: 2/08/17 there is about 0 chance of this working. Once we are keeping track of boat positions it can be fixed.
// // Collect the racing yachts that aren't already in the chart
// sparkLineData.clear();
// List<ClientYacht> sparkLineCandidates = new ArrayList<>(participants.values());
// // Create a new data series for new yachts
// sparkLineCandidates
// .stream()
// .filter(yacht -> yacht.getPosition() != null)
// .forEach(yacht -> {
// Series<String, Double> yachtData = new Series<>();
// yachtData.setName(yacht.getSourceId().toString());
// yachtData.getData().add(
// new Data<>(
// Integer.toString(yacht.getLegNumber()),
// 1.0 + participants.size() - yacht.getPosition()
// )
// );
// sparkLineData.add(yachtData);
// });
//
// // Lambda function to sort the series in order of leg (later legs shown more to the right)
// sparkLineData.sort((o1, o2) -> {
// Integer leg1 = Integer.parseInt(o1.getData().get(o1.getData().size()-1).getXValue());
// Integer leg2 = Integer.parseInt(o2.getData().get(o2.getData().size()-1).getXValue());
// if (leg2 < leg1){
// return 1;
// } else {
// return -1;
// }
// });
//
// // Adds the new data series to the sparkline (and set the colour of the series)
// Platform.runLater(() -> {
// sparkLineData
// .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()));
// });
// });
}
private void initialiseSparkLine() {
sparklineYAxis.setUpperBound(participants.size() + 1);
raceSparkLine.setCreateSymbols(false);
// sparklineYAxis.setUpperBound(participants.size() + 1);
// raceSparkLine.setCreateSymbols(false);
}
/**
@@ -381,8 +386,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* @param direction the from north angle of the wind.
*/
private void updateWindDirection(double direction) {
windDirectionText.setText(String.format("%.1f°", direction));
windArrowText.setRotate(direction);
// windDirectionText.setText(String.format("%.1f°", direction));
// windArrowText.setRotate(direction);
}
/**
@@ -390,7 +395,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* @param windSpeed Windspeed in knots.
*/
private void updateWindSpeed(double windSpeed) {
windSpeedText.setText("Speed: " + String.format("%.1f", windSpeed) + " Knots");
// windSpeedText.setText("Speed: " + String.format("%.1f", windSpeed) + " Knots");
}
@@ -402,7 +407,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// timerLabel.setFill(Color.RED);
// timerLabel.setText("Race Finished!");
// } else {
timerLabel.setText(raceState.getRaceTimeStr());
// timerLabel.setText(raceState.getRaceTimeStr());
// }
}
@@ -411,28 +416,28 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* section
*/
private void updateOrder(ObservableList<ClientYacht> yachts) {
List<Text> vboxEntries = new ArrayList<>();
for (int i = 0; i < yachts.size(); i++) {
// System.out.println("yacht == null " + String.valueOf(yacht == null));
if (yachts.get(i).getBoatStatus() == BoatStatus.FINISHED
.getCode()) { // 3 is finish status
Text textToAdd = new Text(i + 1 + ". " +
yachts.get(i).getShortName() + " (Finished)");
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
vboxEntries.add(textToAdd);
} else {
Text textToAdd = new Text(i + 1 + ". " +
yachts.get(i).getShortName() + " ");
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
textToAdd.setStyle("");
vboxEntries.add(textToAdd);
}
}
Platform.runLater(() ->
positionVbox.getChildren().setAll(vboxEntries)
);
// List<Text> vboxEntries = new ArrayList<>();
//
// for (int i = 0; i < yachts.size(); i++) {
//// System.out.println("yacht == null " + String.valueOf(yacht == null));
// if (yachts.get(i).getBoatStatus() == BoatStatus.FINISHED
// .getCode()) { // 3 is finish status
// Text textToAdd = new Text(i + 1 + ". " +
// yachts.get(i).getShortName() + " (Finished)");
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
// vboxEntries.add(textToAdd);
//
// } else {
// Text textToAdd = new Text(i + 1 + ". " +
// yachts.get(i).getShortName() + " ");
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
// textToAdd.setStyle("");
// vboxEntries.add(textToAdd);
// }
// }
// Platform.runLater(() ->
// positionVbox.getChildren().setAll(vboxEntries)
// );
}
@@ -533,15 +538,15 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
* for the combobox to take action upon selection
*/
private void initialiseBoatSelectionComboBox() {
yachtSelectionComboBox.setItems(
FXCollections.observableArrayList(participants.values())
);
//Null check is if the listener is fired but nothing selected
yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
if (selectedBoat != null) {
gameView.selectBoat(selectedBoat);
}
});
// yachtSelectionComboBox.setItems(
// FXCollections.observableArrayList(participants.values())
// );
// //Null check is if the listener is fired but nothing selected
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
// if (selectedBoat != null) {
// gameView.selectBoat(selectedBoat);
// }
// });
}
/**
@@ -16,6 +16,7 @@ import javafx.scene.effect.DropShadow;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import seng302.gameServer.ServerDescription;
import seng302.visualiser.GameClient;
public class ServerCell implements Initializable {
@@ -39,7 +40,7 @@ public class ServerCell implements Initializable {
private String name;
private String mapNameString;
private Integer currPlayerCount;
private String currPlayerCount;
private String hostName;
private Integer portNumber;
@@ -47,7 +48,8 @@ public class ServerCell implements Initializable {
public ServerCell(ServerDescription server) {
this.name = server.getName();
this.currPlayerCount = server.spacesLeft();
this.currPlayerCount = server.getNumPlayers().toString() + "/" + server.getCapacity().toString();
this.mapNameString = server.getMapName();
this.hostName = server.getAddress();
@@ -57,7 +59,8 @@ public class ServerCell implements Initializable {
public void initialize(URL location, ResourceBundle resources) {
serverName.setText(name);
serverPlayerCount.setText(Integer.toString(currPlayerCount));
serverPlayerCount.setText(currPlayerCount);
mapName.setText(mapNameString);
serverConnButton.setOnMouseReleased(event -> joinServer());
}
@@ -65,12 +68,8 @@ public class ServerCell implements Initializable {
public void joinServer() {
// TODO: 7/09/17 ajm412: Connect to a server here with the values stored in the hostName/portNumber variables.
System.out.println("Connecting to " + serverName.getText());
try {
Parent root = FXMLLoader.load(StartScreenController.class.getResource("/views/LobbyView.fxml"));
ViewManager.getInstance().setScene(root);
} catch (IOException e) {
e.printStackTrace();
}
ViewManager.getInstance().getGameClient().runAsClient(hostName, portNumber);
}
}
@@ -41,18 +41,11 @@ public class ServerCreationController implements Initializable {
}
public void createServer() {
try {
ServerDescription serverDescription = ViewManager.getInstance().getGameClient().runAsHost("localhost", 4941);
ServerDescription serverDescription = ViewManager.getInstance().getGameClient().runAsHost("localhost", 4941, serverName.getText(), (int) maxPlayers.getValue());
ViewManager.getInstance().setProperty("serverName", serverDescription.getName());
ViewManager.getInstance().setProperty("mapName", serverDescription.getMapName());
Parent root = FXMLLoader.load(StartScreenController.class.getResource("/views/LobbyView.fxml"));
ViewManager.getInstance().setScene(root);
} catch (IOException e) {
e.printStackTrace();
}
}
private void updateMaxPlayerLabel() {
@@ -18,6 +18,7 @@ import javafx.scene.layout.VBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.ServerDescription;
import seng302.visualiser.GameClient;
import seng302.visualiser.ServerListener;
import seng302.visualiser.ServerListenerDelegate;
@@ -55,6 +56,7 @@ public class ServerListController implements Initializable, ServerListenerDelega
try {
ServerListener.getInstance().setDelegate(this);
System.out.println("Setting DH");
} catch (IOException e) {
logger.warn("Could not start Server Listener Delegate");
}
@@ -74,9 +76,8 @@ public class ServerListController implements Initializable, ServerListenerDelega
}
private void goToDirectConnectLobby() {
// TODO: 7/09/17 ajm412: Implement ability to connect to a lobby.
serverHostName.setText("Invalid Host Name or Port Number");
serverPortNumber.setText("");
// TODO: 7/09/17 Error handling
ViewManager.getInstance().getGameClient().runAsClient(serverHostName.getText(), Integer.parseInt(serverPortNumber.getText()));
}
@Override
@@ -41,7 +41,7 @@ public class StartScreenController_old implements Initializable {
@FXML
public void hostButtonPressed() {
gameClient = new GameClient(holder);
gameClient.runAsHost(getLocalHostIp(), 4942);
//gameClient.runAsHost(getLocalHostIp(), 4942);
}
/**
@@ -1,10 +1,17 @@
package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXDecorator;
import com.jfoenix.controls.JFXDialog;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.model.ClientYacht;
import seng302.visualiser.GameClient;
import java.io.IOException;
@@ -17,12 +24,19 @@ public class ViewManager {
private JFXDecorator decorator;
private HashMap<String, String> props; //TODO is this the best way to do this??
private ObservableList<String> playerList;
private Logger logger = LoggerFactory.getLogger(ViewManager.class);
private ViewManager(){
props = new HashMap<>();
gameClient = new GameClient(decorator);
}
private FXMLLoader loadFxml(String fxmlLocation) {
return new FXMLLoader(
getClass().getResource(fxmlLocation)
);
}
public static ViewManager getInstance(){
if (instance == null){
instance = new ViewManager();
@@ -40,7 +54,7 @@ public class ViewManager {
}
public void setScene(Node scene){
decorator.setContent(scene);
Platform.runLater(() -> decorator.setContent(scene));
}
public void goToStartView() {
@@ -50,7 +64,6 @@ public class ViewManager {
} catch (IOException e) {
e.printStackTrace();
}
}
public GameClient getGameClient(){
@@ -72,4 +85,61 @@ public class ViewManager {
public ObservableList<String> getPlayerList(){
return playerList;
}
public LobbyController goToLobby(Boolean disableReadyButton){
FXMLLoader loader = loadFxml("/views/LobbyView.fxml");
try {
setScene(loader.load());
} catch (IOException e) {
logger.error("Could not load lobby view");
}
if (disableReadyButton){
LobbyController lobbyController = loader.getController();
lobbyController.disableReadyButton();
}
return loader.getController();
}
public RaceViewController loadRaceView() {
FXMLLoader loader = loadFxml("/views/RaceView.fxml");
try {
setScene(loader.load());
} catch (IOException e) {
e.printStackTrace();
}
decorator.getScene().setOnKeyPressed((ke) -> gameClient.keyPressed(ke));
decorator.getScene().setOnKeyReleased((ke) -> gameClient.keyReleased(ke));
return loader.getController();
}
public JFXDialog loadCustomizationDialog(StackPane parent, LobbyController lobbyController, Color playerColor, String name) {
FXMLLoader dialog = loadFxml("/views/dialogs/BoatCustomizeDialog.fxml");
JFXDialog customizationDialog = null;
try {
customizationDialog = new JFXDialog(parent, dialog.load(),
JFXDialog.DialogTransition.CENTER);
} catch (IOException e) {
e.printStackTrace();
}
BoatCustomizeController controller = dialog.getController();
controller.setParentController(lobbyController);
controller.setPlayerColor(playerColor);
controller.setPlayerName(name);
controller.setServerThread(gameClient.getServerThread());
return customizationDialog;
}
}
+24 -91
View File
@@ -1,106 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="998.0" prefWidth="1530.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.RaceViewController">
<AnchorPane fx:id="rvAnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.RaceViewController">
<children>
<AnchorPane layoutX="322.0" layoutY="130.0" prefHeight="998.0" prefWidth="1281.0"
style="-fx-background-color: skyblue;" AnchorPane.bottomAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<GridPane prefHeight="998.0" prefWidth="1281.0" AnchorPane.bottomAnchor="0.0"
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0"
AnchorPane.topAnchor="0.0">
<StackPane fx:id="contentAnchorPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
</StackPane>
<GridPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="630.0" minWidth="10.0"
prefWidth="68.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1213.0" minWidth="10.0"
prefWidth="1213.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="394.0" minWidth="10.0" prefWidth="218.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="554.0" minWidth="10.0" prefWidth="371.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="539.0" minWidth="10.0" prefWidth="271.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="489.0" minHeight="1.0" prefHeight="24.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="997.0" minHeight="10.0" prefHeight="974.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="191.0" minHeight="0.0" prefHeight="18.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="485.0" minHeight="10.0" prefHeight="467.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<AnchorPane fx:id="contentAnchorPane" prefHeight="200.0" prefWidth="200.0"
GridPane.columnSpan="2" GridPane.rowSpan="2"/>
<Text fx:id="fpsDisplay" strokeType="OUTSIDE" strokeWidth="0.0" text="60 FPS"
GridPane.halignment="CENTER" GridPane.valignment="CENTER"/>
<GridPane style="-fx-b: rgba(255,255,255,0.5);">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="93.0" minWidth="10.0" prefWidth="47.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="160.0" minWidth="10.0" prefWidth="151.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<GridPane.margin>
<Insets />
</GridPane.margin>
</GridPane>
</children>
</GridPane>
</children>
</AnchorPane>
<AnchorPane prefHeight="960.0" prefWidth="250.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label layoutX="11.0" layoutY="283.0" text="Team Position" textFill="WHITE" />
<Label layoutX="13.0" layoutY="432.0" text="Settings" textFill="WHITE" />
<Label layoutX="11.0" layoutY="41.0" text="Timer" textFill="WHITE" />
<Label layoutX="11.0" layoutY="112.0" text="Wind direction" textFill="WHITE" />
<Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#3dcdc8" layoutX="110.0" layoutY="190.0" radius="35.0" stroke="#d7d7d7" strokeType="INSIDE" strokeWidth="3.0" />
<Text fx:id="windArrowText" fill="#a8a8a8" layoutX="86.0" layoutY="210.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↓">
<font>
<Font name="AdobeArabic-Regular" size="55.0" />
</font>
</Text>
<Text fx:id="windDirectionText" fill="#d3d3d3" layoutX="171.0" layoutY="238.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0°" textAlignment="RIGHT">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Text>
<Text fx:id="windSpeedText" fill="#d3d3d3" layoutX="12.0" layoutY="237.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0 Knot" textAlignment="RIGHT">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Text>
<CheckBox fx:id="toggleFps" focusTraversable="false" graphicTextGap="0.0" layoutX="21.0" layoutY="453.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="143.0" selected="true" styleClass="ui-checkbox" text="Show FPS" textFill="WHITE" />
<VBox fx:id="positionVbox" layoutX="12.0" layoutY="304.0" prefHeight="116.0" prefWidth="200.0" styleClass="text-white" />
<Pane layoutX="11.0" layoutY="39.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="193.0">
<children>
<Text fx:id="timerLabel" fill="#f8f8f8" layoutX="-26.0" layoutY="51.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="246.0">
<font>
<Font size="25.0" />
</font>
</Text>
</children>
</Pane>
<Slider fx:id="annotationSlider" blockIncrement="1.0" layoutX="38.0" layoutY="527.0" majorTickUnit="1.0" max="2.0" minorTickCount="0" prefHeight="51.0" prefWidth="170.0" showTickLabels="true" showTickMarks="true" snapToTicks="true" styleClass="ui-slider" />
<Label layoutX="10.0" layoutY="499.0" text="Annotations" textFill="WHITE" />
<Button fx:id="selectAnnotationBtn" focusTraversable="false" layoutX="35.0" layoutY="578.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="170.0" styleClass="blue-ui-btn" text="Select Annotations" textFill="WHITE" />
<Text fill="WHITE" layoutX="11.0" layoutY="649.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Boat Selection" />
<ComboBox fx:id="yachtSelectionComboBox" focusTraversable="false" layoutX="37.0" layoutY="664.0" prefHeight="25.0" prefWidth="170.0" promptText="Select Yacht" styleClass="combo-box-base" />
<LineChart fx:id="raceSparkLine" layoutX="-1.0" layoutY="719.0" legendVisible="false" prefHeight="277.0" prefWidth="246.0" title="Boat Positions">
<xAxis>
<CategoryAxis label="Leg Number" side="BOTTOM" styleClass="spark-line-xaxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="sparklineYAxis" minorTickCount="1" minorTickLength="1.0" side="LEFT" styleClass="spark-line-yaxis" tickLabelGap="1.0" tickUnit="1.0" upperBound="7.0" />
</yAxis>
</LineChart>
</children>
</AnchorPane>
</children>
</AnchorPane>
@@ -8,40 +8,40 @@ import static org.junit.Assert.assertTrue;
public class TestServerDesc {
@Test
public void testEquals(){
ServerDescription one = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription one = new ServerDescription("a", "b", 10, 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, 10, "asd", 1234);
assertTrue(one.equals(two));
}
@Test
public void testNotEqualName(){
ServerDescription one = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription two = new ServerDescription("a2", "b", 10, "asd", 1234);
ServerDescription one = new ServerDescription("a", "b", 10, 10, "asd", 1234);
ServerDescription two = new ServerDescription("a2", "b", 10, 10, "asd", 1234);
assertTrue(!one.equals(two));
}
@Test
public void testNotEqualMap(){
ServerDescription one = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "ba", 10, "asd", 1234);
ServerDescription one = new ServerDescription("a", "b", 10, 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "ba", 10, 10, "asd", 1234);
assertTrue(!one.equals(two));
}
@Test
public void testNotEqualPort(){
ServerDescription one = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, "asd", 12341);
ServerDescription one = new ServerDescription("a", "b", 10, 10, "asd", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, 10, "asd", 12341);
assertTrue(!one.equals(two));
}
@Test
public void testNotEqualAddress(){
ServerDescription one = new ServerDescription("a", "b", 10, "as1d", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, "asd", 1234);
ServerDescription one = new ServerDescription("a", "b", 10, 10, "as1d", 1234);
ServerDescription two = new ServerDescription("a", "b", 10, 10, "asd", 1234);
assertTrue(!one.equals(two));
}