Began fixing bugs with caused by asynchronous listener calls.

#bug
This commit is contained in:
Calum
2017-07-30 20:12:19 +12:00
parent 7894e31926
commit 6cae338c1e
67 changed files with 1370 additions and 1602 deletions
+5 -3
View File
@@ -17,7 +17,9 @@ public class App extends Application {
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
primaryStage.setTitle("RaceVision");
primaryStage.setScene(new Scene(root, 1530, 960));
Scene scene = new Scene(root, 1530, 960);
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
primaryStage.setScene(scene);
// primaryStage.setMaxWidth(1530);
// primaryStage.setMaxHeight(960);
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
@@ -27,11 +29,11 @@ public class App extends Application {
primaryStage.setOnCloseRequest(e -> {
// ClientPacketParser.appClose();
StreamReceiver.noMoreBytes();
ClientPacketParser.appClose();
// ClientPacketParser.appClose();
System.exit(0);
});
ClientState.primaryStage = primaryStage;
// ClientState.primaryStage = primaryStage;
}
public static void main(String[] args) {
File diff suppressed because it is too large Load Diff
+74 -74
View File
@@ -1,77 +1,77 @@
package seng302.client;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import seng302.model.Yacht;
import javafx.stage.Stage;
import seng302.models.Yacht;
/**
* Used by the client to store static variables to be used in game.
*/
public class ClientState {
// private static String hostIp = "";
// private static Boolean isHost = false;
// private static Boolean raceStarted = false;
// private static Boolean connectedToHost = false;
// private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
// private static Boolean dirtyState = true;
// private static String clientSourceId = "";
//package seng302.client;
//
// public static String getHostIp() {
// return hostIp;
// }
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//import seng302.model.Yacht;
//import javafx.stage.Stage;
//import seng302.models.Yacht;
//
// public static void setHostIp(String hostIp) {
// ClientState.hostIp = hostIp;
// }
///**
// * Used by the client to store static variables to be used in game.
// */
//public class ClientState {
//
// public static Boolean isHost() {
// return isHost;
// }
//
// public static void setHost(Boolean isHost) {
// ClientState.isHost = isHost;
// }
//
// public static Boolean isRaceStarted() {
// return raceStarted;
// }
//
// public static void setRaceStarted(Boolean raceStarted) {
// ClientState.raceStarted = raceStarted;
// }
//
// public static Boolean isConnectedToHost() {
// return connectedToHost;
// }
//
// public static void setConnectedToHost(Boolean connectedToHost) {
// ClientState.connectedToHost = connectedToHost;
// }
//
// public static Map<Integer, Yacht> getBoats() {
// return boats;
// }
//
// public static Boolean isDirtyState() {
// return dirtyState;
// }
//
// public static void setDirtyState(Boolean dirtyState) {
// ClientState.dirtyState = dirtyState;
// }
//
// public static String getClientSourceId() {
// return clientSourceId;
// }
//
// public static void setClientSourceId(String clientSourceId) {
// ClientState.clientSourceId = clientSourceId;
// }
//
// public static void setBoats(Map<Integer, Yacht> boats) {
// ClientState.boats = boats;
// }
}
//// private static String hostIp = "";
//// private static Boolean isHost = false;
//// private static Boolean raceStarted = false;
//// private static Boolean connectedToHost = false;
//// private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
//// private static Boolean dirtyState = true;
//// private static String clientSourceId = "";
////
//// public static String getHostIp() {
//// return hostIp;
//// }
////
//// public static void setHostIp(String hostIp) {
//// ClientState.hostIp = hostIp;
//// }
////
//// public static Boolean isHost() {
//// return isHost;
//// }
////
//// public static void setHost(Boolean isHost) {
//// ClientState.isHost = isHost;
//// }
////
//// public static Boolean isRaceStarted() {
//// return raceStarted;
//// }
////
//// public static void setRaceStarted(Boolean raceStarted) {
//// ClientState.raceStarted = raceStarted;
//// }
////
//// public static Boolean isConnectedToHost() {
//// return connectedToHost;
//// }
////
//// public static void setConnectedToHost(Boolean connectedToHost) {
//// ClientState.connectedToHost = connectedToHost;
//// }
////
//// public static Map<Integer, Yacht> getBoats() {
//// return boats;
//// }
////
//// public static Boolean isDirtyState() {
//// return dirtyState;
//// }
////
//// public static void setDirtyState(Boolean dirtyState) {
//// ClientState.dirtyState = dirtyState;
//// }
////
//// public static String getClientSourceId() {
//// return clientSourceId;
//// }
////
//// public static void setClientSourceId(String clientSourceId) {
//// ClientState.clientSourceId = clientSourceId;
//// }
////
//// public static void setBoats(Map<Integer, Yacht> boats) {
//// ClientState.boats = boats;
//// }
//}
@@ -1,235 +1,235 @@
package seng302.controllers;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import seng302.client.ClientState;
import seng302.client.ClientStateQueryingRunnable;
import seng302.gameServer.GameStages;
import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread;
/**
* A class describing the actions of the lobby screen
* Created by wmu16 on 10/07/17.
*/
public class LobbyController implements Initializable, Observer{
@FXML
private GridPane lobbyScreen;
@FXML
private Text lobbyIpText;
@FXML
private Button readyButton;
@FXML
private ListView firstListView;
@FXML
private ListView secondListView;
@FXML
private ListView thirdListView;
@FXML
private ListView fourthListView;
@FXML
private ListView fifthListView;
@FXML
private ListView sixthListView;
@FXML
private ListView seventhListView;
@FXML
private ListView eighthListView;
@FXML
private ImageView firstImageView;
@FXML
private ImageView secondImageView;
@FXML
private ImageView thirdImageView;
@FXML
private ImageView fourthImageView;
@FXML
private ImageView fifthImageView;
@FXML
private ImageView sixthImageView;
@FXML
private ImageView seventhImageView;
@FXML
private ImageView eighthImageView;
private static List<ObservableList<String>> competitors = new ArrayList<>();
private static ObservableList<String> firstCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> secondCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> thirdCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> fourthCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> fifthCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> sixthCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> seventhCompetitor = FXCollections.observableArrayList();
private static ObservableList<String> eighthCompetitor = FXCollections.observableArrayList();
private ClientStateQueryingRunnable clientStateQueryingRunnable;
private static List<ImageView> imageViews;
private static List<ListView> listViews;
private int MAX_NUM_PLAYERS = 8;
private Boolean switchedPane = false;
private MainServerThread mainServerThread;
private Controller controller;
private void setContentPane(String jfxUrl) {
try {
AnchorPane contentPane = (AnchorPane) lobbyScreen.getParent();
contentPane.getChildren().removeAll();
contentPane.getChildren().clear();
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
contentPane.getChildren()
.addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
} catch (javafx.fxml.LoadException e) {
System.out.println("[Controller] FXML load exception");
} catch (IOException e) {
System.out.println("[Controller] IO exception");
} catch (NullPointerException e) {
// System.out.println("[Controller] Null Pointer Exception");
}
}
@Override
public void initialize(URL location, ResourceBundle resources) {
if (ClientState.isHost()) {
lobbyIpText.setText("Lobby Host IP: " + ClientState.getHostIp());
readyButton.setDisable(false);
}
else {
lobbyIpText.setText("Connected to IP: " + ClientState.getHostIp());
readyButton.setDisable(true);
}
// put all javafx objects in lists, so we can iterate though conveniently
imageViews = new ArrayList<>();
Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView,
fifthImageView, sixthImageView, seventhImageView, eighthImageView);
listViews = new ArrayList<>();
Collections.addAll(listViews, firstListView, secondListView, thirdListView, fourthListView, fifthListView,
sixthListView, seventhListView, eighthListView);
competitors = new ArrayList<>();
Collections.addAll(competitors, firstCompetitor, secondCompetitor, thirdCompetitor,
fourthCompetitor, fifthCompetitor, sixthCompetitor, seventhCompetitor, eighthCompetitor);
initialiseListView();
initialiseImageView(); // parrot gif init
// set up client state query thread, so that when it receives the race-started packet
// it can switch to the race view
ClientStateQueryingRunnable clientStateQueryingRunnable = new ClientStateQueryingRunnable();
clientStateQueryingRunnable.addObserver(this);
Thread clientStateQueryingThread = new Thread(clientStateQueryingRunnable, "Client State querying thread");
clientStateQueryingThread.setDaemon(true);
clientStateQueryingThread.start();
}
/**
* Observers "ClientStateQueryingRunnable".
* When the clients state has been marked to "race start", the querying thread
* will notify this lobby to change the view
* @param o
* @param arg
*/
@Override
public void update(Observable o, Object arg) {
Platform.runLater(new Runnable() {
@Override
public void run() {
if (arg.equals("game started") && !switchedPane) {
switchToRaceView();
}
if (arg.equals(("update players"))) {
initialiseListView();
}
}
});
}
/**
* Reset all ListViews and ImageViews according to the current competitors
*/
private void initialiseListView() {
listViews.forEach(listView -> listView.getItems().clear());
imageViews.forEach(gif -> gif.setVisible(false));
competitors.forEach(ol -> ol.removeAll());
List<Integer> ids = new ArrayList<>(ClientState.getBoats().keySet());
for (int i = 0; i < ids.size(); i++) {
competitors.get(i).add(ClientState.getBoats().get(ids.get(i)).getBoatName());
listViews.get(i).setItems(competitors.get(i));
imageViews.get(i).setVisible(true);
}
}
/**
* Loads preset images into imageViews
*/
private void initialiseImageView() {
for (int i = 0; i < MAX_NUM_PLAYERS; i++) {
imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png")));
}
// Image image1 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// firstImageView.setImage(image1);
// Image image2 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// secondImageView.setImage(image2);
// Image image3 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// thirdImageView.setImage(image3);
// Image image4 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// fourthImageView.setImage(image4);
// Image image5 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// fifthImageView.setImage(image5);
// Image image6 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// sixthImageView.setImage(image6);
// Image image7 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// seventhImageView.setImage(image7);
// Image image8 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
// eighthImageView.setImage(image8);
}
@FXML
public void leaveLobbyButtonPressed() {
if (ClientState.isHost()) {
GameState.setCurrentStage(GameStages.CANCELLED);
mainServerThread.terminate();
}
ClientState.setConnectedToHost(false);
controller.setUpStartScreen();
}
@FXML
public void readyButtonPressed() {
GameState.setCurrentStage(GameStages.RACING);
mainServerThread.startGame();
}
private void switchToRaceView() {
if (!switchedPane) {
switchedPane = true;
setContentPane("/views/RaceView.fxml");
}
}
public void setMainServerThread(MainServerThread mainServerThread) {
this.mainServerThread = mainServerThread;
}
public void setController(Controller controller) {
this.controller = controller;
}
}
//package seng302.controllers;
//
//import java.io.IOException;
//import java.net.URL;
//import java.util.*;
//
//import javafx.application.Platform;
//import javafx.collections.FXCollections;
//import javafx.collections.ObservableList;
//import javafx.fxml.FXML;
//import javafx.fxml.FXMLLoader;
//import javafx.fxml.Initializable;
//import javafx.scene.control.Button;
//import javafx.scene.control.ListView;
//import javafx.scene.image.Image;
//import javafx.scene.image.ImageView;
//import javafx.scene.layout.AnchorPane;
//import javafx.scene.layout.GridPane;
//import javafx.scene.layout.Pane;
//import javafx.scene.text.Text;
//import seng302.client.ClientState;
//import seng302.client.ClientStateQueryingRunnable;
//import seng302.gameServer.GameStages;
//import seng302.gameServer.GameState;
//import seng302.gameServer.MainServerThread;
//
///**
// * A class describing the actions of the lobby screen
// * Created by wmu16 on 10/07/17.
// */
//public class LobbyController implements Initializable, Observer{
// @FXML
// private GridPane lobbyScreen;
// @FXML
// private Text lobbyIpText;
// @FXML
// private Button readyButton;
// @FXML
// private ListView firstListView;
// @FXML
// private ListView secondListView;
// @FXML
// private ListView thirdListView;
// @FXML
// private ListView fourthListView;
// @FXML
// private ListView fifthListView;
// @FXML
// private ListView sixthListView;
// @FXML
// private ListView seventhListView;
// @FXML
// private ListView eighthListView;
// @FXML
// private ImageView firstImageView;
// @FXML
// private ImageView secondImageView;
// @FXML
// private ImageView thirdImageView;
// @FXML
// private ImageView fourthImageView;
// @FXML
// private ImageView fifthImageView;
// @FXML
// private ImageView sixthImageView;
// @FXML
// private ImageView seventhImageView;
// @FXML
// private ImageView eighthImageView;
//
// private static List<ObservableList<String>> competitors = new ArrayList<>();
// private static ObservableList<String> firstCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> secondCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> thirdCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> fourthCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> fifthCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> sixthCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> seventhCompetitor = FXCollections.observableArrayList();
// private static ObservableList<String> eighthCompetitor = FXCollections.observableArrayList();
// private ClientStateQueryingRunnable clientStateQueryingRunnable;
// private static List<ImageView> imageViews;
// private static List<ListView> listViews;
//
// private int MAX_NUM_PLAYERS = 8;
//
// private Boolean switchedPane = false;
// private MainServerThread mainServerThread;
// private Controller controller;
//
// private void setContentPane(String jfxUrl) {
// try {
// AnchorPane contentPane = (AnchorPane) lobbyScreen.getParent();
// contentPane.getChildren().removeAll();
// contentPane.getChildren().clear();
// contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// contentPane.getChildren()
// .addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
// } catch (javafx.fxml.LoadException e) {
// System.out.println("[Controller] FXML load exception");
// } catch (IOException e) {
// System.out.println("[Controller] IO exception");
// } catch (NullPointerException e) {
//// System.out.println("[Controller] Null Pointer Exception");
// }
// }
//
// @Override
// public void initialize(URL location, ResourceBundle resources) {
// if (ClientState.isHost()) {
// lobbyIpText.setText("Lobby Host IP: " + ClientState.getHostIp());
// readyButton.setDisable(false);
// }
// else {
// lobbyIpText.setText("Connected to IP: " + ClientState.getHostIp());
// readyButton.setDisable(true);
// }
//
// // put all javafx objects in lists, so we can iterate though conveniently
// imageViews = new ArrayList<>();
// Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView,
// fifthImageView, sixthImageView, seventhImageView, eighthImageView);
// listViews = new ArrayList<>();
// Collections.addAll(listViews, firstListView, secondListView, thirdListView, fourthListView, fifthListView,
// sixthListView, seventhListView, eighthListView);
// competitors = new ArrayList<>();
// Collections.addAll(competitors, firstCompetitor, secondCompetitor, thirdCompetitor,
// fourthCompetitor, fifthCompetitor, sixthCompetitor, seventhCompetitor, eighthCompetitor);
//
// initialiseListView();
// initialiseImageView(); // parrot gif init
//
// // set up client state query thread, so that when it receives the race-started packet
// // it can switch to the race view
// ClientStateQueryingRunnable clientStateQueryingRunnable = new ClientStateQueryingRunnable();
// clientStateQueryingRunnable.addObserver(this);
// Thread clientStateQueryingThread = new Thread(clientStateQueryingRunnable, "Client State querying thread");
// clientStateQueryingThread.setDaemon(true);
// clientStateQueryingThread.start();
// }
//
// /**
// * Observers "ClientStateQueryingRunnable".
// * When the clients state has been marked to "race start", the querying thread
// * will notify this lobby to change the view
// * @param o
// * @param arg
// */
// @Override
// public void update(Observable o, Object arg) {
// Platform.runLater(new Runnable() {
// @Override
// public void run() {
// if (arg.equals("game started") && !switchedPane) {
// switchToRaceView();
// }
// if (arg.equals(("update players"))) {
// initialiseListView();
// }
// }
// });
// }
//
// /**
// * Reset all ListViews and ImageViews according to the current competitors
// */
// private void initialiseListView() {
// listViews.forEach(listView -> listView.getItems().clear());
// imageViews.forEach(gif -> gif.setVisible(false));
// competitors.forEach(ol -> ol.removeAll());
//
// List<Integer> ids = new ArrayList<>(ClientState.getBoats().keySet());
// for (int i = 0; i < ids.size(); i++) {
// competitors.get(i).add(ClientState.getBoats().get(ids.get(i)).getBoatName());
// listViews.get(i).setItems(competitors.get(i));
// imageViews.get(i).setVisible(true);
// }
// }
//
// /**
// * Loads preset images into imageViews
// */
// private void initialiseImageView() {
// for (int i = 0; i < MAX_NUM_PLAYERS; i++) {
// imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png")));
// }
//// Image image1 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// firstImageView.setImage(image1);
//// Image image2 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// secondImageView.setImage(image2);
//// Image image3 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// thirdImageView.setImage(image3);
//// Image image4 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// fourthImageView.setImage(image4);
//// Image image5 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// fifthImageView.setImage(image5);
//// Image image6 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// sixthImageView.setImage(image6);
//// Image image7 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// seventhImageView.setImage(image7);
//// Image image8 = new Image(getClass().getResourceAsStream("/pics/sail.png"));
//// eighthImageView.setImage(image8);
// }
//
// @FXML
// public void leaveLobbyButtonPressed() {
// if (ClientState.isHost()) {
// GameState.setCurrentStage(GameStages.CANCELLED);
// mainServerThread.terminate();
// }
// ClientState.setConnectedToHost(false);
// controller.setUpStartScreen();
// }
//
// @FXML
// public void readyButtonPressed() {
// GameState.setCurrentStage(GameStages.RACING);
// mainServerThread.startGame();
// }
//
//
// private void switchToRaceView() {
// if (!switchedPane) {
// switchedPane = true;
// setContentPane("/views/RaceView.fxml");
// }
// }
//
// public void setMainServerThread(MainServerThread mainServerThread) {
// this.mainServerThread = mainServerThread;
// }
//
// public void setController(Controller controller) {
// this.controller = controller;
// }
//}
@@ -1,12 +1,13 @@
package seng302.gameServer;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import seng302.model.Player;
import seng302.model.Yacht;
import seng302.model.stream.packets.StreamPacket;
import seng302.server.messages.BoatActionType;
/**
@@ -26,6 +27,7 @@ public class GameState implements Runnable {
private static Map<Integer, Yacht> yachts;
private static Boolean isRaceStarted;
private static GameStages currentStage;
private static long startTime;
// TODO: 26/07/17 cir27 - Super hackish fix until something more permanent can be made.
private static ObservableList<String> observablePlayers = FXCollections.observableArrayList();
@@ -170,7 +172,6 @@ public class GameState implements Runnable {
}
}
/**
* Generates a new ID based off the size of current players + 1
* @return a playerID to be allocated to a new connetion
@@ -1,12 +1,13 @@
package seng302.gameServer;
import java.io.IOException;
import java.util.Stack;
import java.util.Timer;
import java.util.TimerTask;
import seng302.model.Player;
import seng302.server.messages.Heartbeat;
import seng302.server.messages.Message;
import java.io.IOException;
import java.util.*;
/**
* Send Heartbeat messages to connected player at a specified interval
* Will call .clientDisconnected on the delegate when a heartbeat message
@@ -1,20 +1,13 @@
package seng302.gameServer;
import java.time.LocalDateTime;
import java.util.Observable;
import seng302.client.ClientPacketParser;
import seng302.models.Player;
import seng302.models.stream.PacketBufferDelegate;
import seng302.models.stream.packets.StreamPacket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.logging.Logger;
import seng302.model.Player;
/**
* A class describing the overall server, which creates and collects server threads for each client
@@ -3,7 +3,6 @@ package seng302.gameServer;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -15,7 +14,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.zip.CRC32;
@@ -26,13 +24,12 @@ import seng302.model.stream.packets.PacketType;
import seng302.model.stream.packets.StreamPacket;
import seng302.model.stream.xml.generator.Race;
import seng302.model.stream.xml.generator.Regatta;
import seng302.model.stream.xml.generator.XMLGenerator;
import seng302.utilities.XMLGenerator;
import seng302.server.messages.BoatActionType;
import seng302.server.messages.BoatLocationMessage;
import seng302.server.messages.BoatStatus;
import seng302.server.messages.BoatSubMessage;
import seng302.server.messages.Message;
import seng302.server.messages.RaceStatus;
import seng302.server.messages.RaceStatusMessage;
import seng302.server.messages.RaceType;
@@ -270,6 +267,7 @@ public class ServerToClientThread implements Runnable, Observer {
currentByte = is.read();
crcBuffer.write(currentByte);
} catch (IOException e) {
e.printStackTrace();
serverLog("Socket read failed", 1);
}
if (currentByte == -1) {
-2
View File
@@ -1,7 +1,5 @@
package seng302.model;
import org.w3c.dom.Node;
/**
* Stores the data for the cornering of a mark.
*/
+27 -29
View File
@@ -1,22 +1,19 @@
package seng302.model;
import static seng302.utilities.GeoUtility.getGeoCoordinate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.scene.control.ListView;
import javafx.scene.paint.Color;
import seng302.model.mark.Mark;
import static seng302.utilities.GeoUtility.getGeoCoordinate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import javafx.scene.paint.Color;
import seng302.client.ClientPacketParser;
import seng302.controllers.RaceViewController;
import seng302.gameServer.GameState;
import seng302.model.mark.Mark;
import seng302.utilities.GeoPoint;
/**
@@ -32,6 +29,11 @@ public class Yacht {
void notifyLocation(Yacht yacht, double lat, double lon, double heading, double velocity);
}
@FunctionalInterface
public interface YachtPositionListener {
void notifyPosition(int position);
}
//BOTH AFAIK
private String boatType;
private Integer sourceId;
@@ -137,7 +139,7 @@ public class Yacht {
Double windSpeedKnots = GameState.getWindSpeedKnots();
Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
Double maxBoatSpeed = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000;
Double maxBoatSpeed = boatSpeedInKnots / 1.943844492 * 1000;
if (sailIn && velocity <= maxBoatSpeed && maxBoatSpeed != 0d) {
if (velocity < maxBoatSpeed) {
@@ -159,30 +161,22 @@ public class Yacht {
velocity = 0d;
}
}
if (sailIn) {
Double secondsElapsed = timeInterval / 1000000.0;
Double windSpeedKnots = GameState.getWindSpeedKnots();
Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
velocity = boatSpeedInKnots / 1.943844492 * 1000; // TODO: 26/07/17 cir27 - Remove magic number
Double metersCovered = velocity * secondsElapsed;
location = getGeoCoordinate(location, heading, metersCovered);
} else {
velocity = 0d;
}
}
}
// if (sailIn) {
// Double secondsElapsed = timeInterval / 1000000.0;
// Double windSpeedKnots = GameState.getWindSpeedKnots();
// Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
// Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
// velocity = boatSpeedInKnots / 1.943844492 * 1000; // TODO: 26/07/17 cir27 - Remove magic number
// Double metersCovered = velocity * secondsElapsed;
// location = getGeoCoordinate(location, heading, metersCovered);
// } else {
// velocity = 0d;
// }
Double metersCovered = velocity * secondsElapsed;
location = getGeoCoordinate(location, heading, metersCovered);
}
public Double getHeading() {
return heading;
}
public void adjustHeading(Double amount) {
Double newVal = heading + amount;
lastHeading = heading;
@@ -501,4 +495,8 @@ public class Yacht {
public void addLocationListener (YachtLocationListener listener) {
locationListeners.add(listener);
}
public void addPositionListener (YachtPositionListener listener) {
}
}
@@ -1,7 +0,0 @@
package seng302.model.stream;
import seng302.model.stream.packets.StreamPacket;
public interface PacketBufferDelegate {
boolean addToBuffer(StreamPacket streamPacket);
}
@@ -1,130 +0,0 @@
package seng302.model.stream;
import seng302.model.stream.packets.StreamPacket;
import java.io.*;
import java.net.Socket;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
public class StreamReceiver extends Thread {
private InputStream inputStream;
private OutputStream outputStream;
private Socket host;
private ByteArrayOutputStream crcBuffer;
private Thread t;
private String threadName;
public static PriorityBlockingQueue<StreamPacket> packetBuffer;
private static boolean moreBytes;
public StreamReceiver(String hostAddress, int hostPort, String threadName) {
this.threadName = threadName;
this.setDaemon(true);
try {
host = new Socket(hostAddress, hostPort);
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public void run(){
PriorityBlockingQueue<StreamPacket> pq = new PriorityBlockingQueue<>(256, new Comparator<StreamPacket>() {
@Override
public int compare(StreamPacket s1, StreamPacket s2) {
return (int) (s1.getTimeStamp() - s2.getTimeStamp());
}
});
packetBuffer = pq;
connect();
}
public void start () {
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
public StreamReceiver(Socket host, PriorityBlockingQueue packetBuffer){
this.host=host;
this.packetBuffer = packetBuffer;
}
public void connect(){
// int sync1;
// int sync2;
// moreBytes = true;
// while(moreBytes) {
// try {
// crcBuffer = new ByteArrayOutputStream();
// sync1 = readByte();
// sync2 = readByte();
// //checking if it is the start of the packet
// if(sync1 == 0x47 && sync2 == 0x83) {
// int type = readByte();
// //No. of milliseconds since Jan 1st 1970
// long timeStamp = bytesToLong(getBytes(6));
// skipBytes(4);
// long payloadLength = bytesToLong(getBytes(2));
// byte[] payload = getBytes((int) payloadLength);
// Checksum checksum = new CRC32();
// checksum.update(crcBuffer.toByteArray(), 0, crcBuffer.size());
// long computedCrc = checksum.getValue();
// long packetCrc = bytesToLong(getBytes(4));
// if (computedCrc == packetCrc) {
// packetBuffer.add(new StreamPacket(type, payloadLength, timeStamp, payload));
// } else {
// System.err.println("Packet has been dropped");
// }
// }
// } catch (Exception e) {
// moreBytes = false;
// }
// }
}
private int readByte() throws Exception {
int currentByte = -1;
try {
currentByte = inputStream.read();
crcBuffer.write(currentByte);
} catch (IOException e) {
e.printStackTrace();
}
if (currentByte == -1){
throw new Exception();
}
return currentByte;
}
private byte[] getBytes(int n) throws Exception{
byte[] bytes = new byte[n];
for (int i = 0; i < n; i++){
bytes[i] = (byte) readByte();
}
return bytes;
}
private void skipBytes(long n) throws Exception{
for (int i=0; i < n; i++){
readByte();
}
}
public static void main(String[] args) {
StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1");
//StreamReceiver sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread2");
sr.start();
}
public static void noMoreBytes(){
moreBytes = false;
}
}
@@ -11,7 +11,7 @@ public class MarkRoundingData {
private int roundingSide;
private long timeStamp;
MarkRoundingData(int boatId, int markId, int roundingSide, long timeStamp) {
public MarkRoundingData(int boatId, int markId, int roundingSide, long timeStamp) {
this.boatId = boatId;
this.markId = markId;
this.roundingSide = roundingSide;
@@ -14,7 +14,7 @@ public class PositionUpdateData {
private double heading;
private double groundSpeed;
PositionUpdateData(int deviceId, DeviceType type, double lat, double lon,
public PositionUpdateData(int deviceId, DeviceType type, double lat, double lon,
double heading, double groundSpeed) {
this.deviceId = deviceId;
this.type = type;
@@ -10,7 +10,7 @@ public class RaceStartData {
private int notificationType;
private long timeStamp;
RaceStartData (long raceId, long raceStartTime, int notificationType, long timeStamp) {
public RaceStartData (long raceId, long raceStartTime, int notificationType, long timeStamp) {
this.raceId = raceId;
this.raceStartTime = raceStartTime;
this.notificationType = notificationType;
@@ -19,7 +19,7 @@ public class RaceStatusData {
private long expectedStartTime;
private List<long[]> boatData = new ArrayList<>();
RaceStatusData(
public RaceStatusData(
long windDir, long rawWindSpeed, int raceStatus, long currentTime, long expectedStartTime) {
windDirection = windDir / WIND_DIR_FACTOR;
@@ -29,8 +29,8 @@ public class RaceStatusData {
this.expectedStartTime = expectedStartTime;
}
void addBoatData (long boatID, long estTimeToNextMark, long estTimeToFinish, int leg) {
boatData.add(new long[] {boatID, estTimeToNextMark, estTimeToFinish, leg});
public void addBoatData (long boatID, long estTimeToNextMark, long estTimeToFinish, int leg, int boatStatus) {
boatData.add(new long[] {boatID, estTimeToNextMark, estTimeToFinish, leg, boatStatus});
}
public double getWindDirection() {
@@ -18,7 +18,7 @@ public class RaceXMLData {
private List<Limit> courseLimit;
private Map<Integer, Mark> individualMarks;
RaceXMLData(List<Integer> participants, List<Mark> compoundMarks, List<Corner> markSequence,
public RaceXMLData(List<Integer> participants, List<Mark> compoundMarks, List<Corner> markSequence,
List<Limit> courseLimit) {
this.participants = participants;
this.markSequence = markSequence;
@@ -12,7 +12,7 @@ public class RegattaXMLData {
private Double centralLng;
private Integer utcOffset;
RegattaXMLData (Integer regattaID, String regattaName, String courseName,
public RegattaXMLData (Integer regattaID, String regattaName, String courseName,
Double centralLat, Double centralLng, Integer utcOffset) {
this.regattaID = regattaID;
this.regattaName = regattaName;
@@ -1,9 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
/**
* Created by kre39 on 12/07/17.
*/
@@ -1,8 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
public class BoatLocationMessage extends Message {
private final int MESSAGE_SIZE = 56;
@@ -1,9 +1,6 @@
package seng302.server.messages;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Collections;
public class Header {
// From API spec
@@ -1,8 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
public class Heartbeat extends Message {
private final int MESSAGE_SIZE = 4;
@@ -1,8 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
public class MarkRoundingMessage extends Message{
private final long MESSAGE_VERSION_NUMBER = 1;
private final int MESSAGE_SIZE = 21;
@@ -1,7 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
@@ -1,8 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
public class RaceStartStatusMessage extends Message {
private final int MESSAGE_SIZE = 20;
@@ -1,7 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.zip.CRC32;
@@ -1,8 +1,5 @@
package seng302.server.messages;
import java.io.IOException;
import java.io.OutputStream;
public class XMLMessage extends Message{
private final MessageType MESSAGE_TYPE = MessageType.XML_MESSAGE;
private final int MESSAGE_VERSION = 1; //Always set to 1
@@ -1,15 +1,14 @@
package seng302.server.simulator;
import java.util.List;
import java.util.Observable;
import java.util.concurrent.ThreadLocalRandom;
import seng302.server.simulator.mark.Corner;
import seng302.server.simulator.mark.Mark;
import seng302.server.simulator.parsers.RaceParser;
import seng302.utilities.GeoPoint;
import seng302.utilities.GeoUtility;
import java.util.List;
import java.util.Observable;
import java.util.concurrent.ThreadLocalRandom;
public class Simulator extends Observable implements Runnable {
private List<Corner> course;
@@ -1,7 +1,6 @@
package seng302.server.simulator.parsers;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
/**
@@ -1,5 +1,9 @@
package seng302.server.simulator.parsers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -9,11 +13,6 @@ import seng302.server.simulator.mark.Corner;
import seng302.server.simulator.mark.Mark;
import seng302.server.simulator.mark.RoundingType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Parses the race xml file to get course details
* Created by Haoming Yin (hyi25) on 16/3/2017
@@ -1,12 +1,11 @@
package seng302.server.simulator.parsers;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* Created by Haoming Yin (hyi25) on 16/3/2017
@@ -1,5 +1,7 @@
package seng302.server.simulator.parsers;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -7,9 +9,6 @@ import org.w3c.dom.NodeList;
import seng302.server.simulator.Boat;
import seng302.server.simulator.mark.Corner;
import java.util.ArrayList;
import java.util.List;
/**
* Parses the race xml file to get course details
* Created by Haoming Yin (hyi25) on 16/3/2017
@@ -1,6 +1,5 @@
package seng302.model.stream.parser;
package seng302.utilities;
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
@@ -14,6 +13,11 @@ import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import seng302.model.stream.packets.PacketType;
import seng302.model.stream.packets.StreamPacket;
import seng302.model.stream.parser.MarkRoundingData;
import seng302.model.stream.parser.PositionUpdateData;
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
import seng302.model.stream.parser.RaceStartData;
import seng302.model.stream.parser.RaceStatusData;
/**
* StreamParser is a utilities class for taking byte data, formatted according to the AC35
@@ -87,22 +91,24 @@ public class StreamParser {
//
int noBoats = payload[22];
int raceType = payload[23];
long boatID, estTimeAtNextMark, estTimeAtFinish;
int leg, boatStatus;
for (int i = 0; i < noBoats; i++) {
long boatID = bytesToLong(
boatID = bytesToLong(
Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20)));
// boat.setBoatStatus((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)]);
Long estTimeAtNextMark = bytesToLong(
estTimeAtNextMark = bytesToLong(
Arrays.copyOfRange(payload, 32 + (i * 20), 38 + (i * 20)));
// boat.setEstimateTimeTillNextMark(estTimeAtNextMark);
Long estTimeAtFinish = bytesToLong(
estTimeAtFinish = bytesToLong(
Arrays.copyOfRange(payload, 38 + (i * 20), 44 + (i * 20)));
int leg = (int) payload[29 + (i * 20)];
leg = (int) payload[29 + (i * 20)];
// boat.setEstimateTimeAtFinish(estTimeAtFinish);
data.addBoatData(boatID, estTimeAtNextMark, estTimeAtFinish, leg);
data.addBoatData(boatID, estTimeAtNextMark, estTimeAtFinish, leg, boatStatus);
}
return data;
}
@@ -1,12 +1,16 @@
package seng302.model.stream.xml.generator;
package seng302.utilities;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import seng302.model.stream.xml.generator.Race;
import seng302.model.stream.xml.generator.Regatta;
import seng302.server.messages.XMLMessageSubType;
import java.io.*;
/**
* An XML generator to generate the Race, Boat, and Regatta XML dynamically
*/
@@ -1,4 +1,5 @@
package seng302.model.stream.xml.parser;
package seng302.utilities;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -7,13 +8,15 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import seng302.model.Yacht;
import seng302.model.Corner;
import seng302.model.Limit;
import seng302.model.Yacht;
import seng302.model.mark.GateMark;
import seng302.model.mark.Mark;
import seng302.model.mark.MarkType;
import seng302.model.mark.SingleMark;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
/**
* Utilities for parsing XML documents
@@ -1,11 +0,0 @@
package seng302.visualiser;
import seng302.model.stream.packets.StreamPacket;
/**
* Functional interface for receiving packets from client socket.
*/
@FunctionalInterface
public interface ClientSocketListener {
void newPacket(StreamPacket packet);
}
@@ -5,14 +5,16 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.time.LocalDateTime;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import seng302.model.stream.packets.StreamPacket;
import seng302.server.messages.BoatActionMessage;
import seng302.server.messages.Message;
@@ -22,6 +24,21 @@ import seng302.server.messages.Message;
* its own thread.
*/
public class ClientToServerThread implements Runnable {
/**
* Functional interface for receiving packets from client socket.
*/
@FunctionalInterface
public interface ClientSocketListener {
void newPacket();
}
private class ByteReadException extends Exception {
private ByteReadException(String message) {
super(message);
}
}
private static final int LOG_LEVEL = 1;
private Queue<StreamPacket> streamPackets = new ConcurrentLinkedQueue<>();
@@ -34,8 +51,9 @@ public class ClientToServerThread implements Runnable {
private int clientId;
private Boolean updateClient = true;
// private Boolean updateClient = true;
private ByteArrayOutputStream crcBuffer;
private boolean socketOpen = true;
/**
* Constructor for ClientToServerThread which takes in ipAddress and portNumber and attempts to
@@ -53,7 +71,6 @@ public class ClientToServerThread implements Runnable {
socket = new Socket(ipAddress, portNumber);
is = socket.getInputStream();
os = socket.getOutputStream();
Integer allocatedID = threeWayHandshake();
if (allocatedID != null) {
clientId = allocatedID;
@@ -90,8 +107,19 @@ public class ClientToServerThread implements Runnable {
int sync1;
int sync2;
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
while(true) { /**REMOVED SOMETHING HERE ClientState.isConnectedToHost() */
while(socketOpen) { /**REMOVED SOMETHING HERE ClientState.isConnectedToHost() */
System.out.println("socket.isConnected() = " + socket.isConnected());
try {
//Perform a write if it is time to as delegated by the MainServerThread
// if (updateClient) {
// // TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
//// try {
//// GameState.outputState(os);
//// } catch (IOException e) {
//// System.out.println("IO error in server thread upon writing to output stream");
//// }
// updateClient = false;
// }
crcBuffer = new ByteArrayOutputStream();
sync1 = readByte();
sync2 = readByte();
@@ -109,29 +137,33 @@ public class ClientToServerThread implements Runnable {
long packetCrc = Message.bytesToLong(getBytes(4));
if (computedCrc == packetCrc) {
// streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
for (ClientSocketListener csl : listeners)
csl.newPacket(new StreamPacket(type, payloadLength, timeStamp, payload));
// for (ClientSocketListener csl : listeners)
// csl.newPacket(new StreamPacket(type, payloadLength, timeStamp, payload));
if (streamPackets.size() > 0) {
streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
} else {
streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
for (ClientSocketListener csl : listeners)
csl.newPacket();
}
} else {
clientLog("Packet has been dropped", 1);
}
}
} catch (Exception e) {
} catch (ByteReadException e) {
closeSocket();
Platform.runLater(new Runnable() {
@Override
public void run() {
Alert alert = new Alert(AlertType.ERROR);
alert.setHeaderText("Host has disconnected");
alert.setContentText("Cannot find Server");
alert.showAndWait();
}
});
clientLog("Disconnected from server", 1);
Platform.runLater(() -> {
Alert alert = new Alert(AlertType.ERROR);
alert.setHeaderText("Host has disconnected");
alert.setContentText("Cannot find Server");
alert.showAndWait();
});
clientLog(e.getMessage(), 1);
return;
}
}
// closeSocket();
// clientLog("Disconnected from server", 0);
closeSocket();
clientLog("Closed connection to Server", 0);
}
@@ -147,7 +179,6 @@ public class ClientToServerThread implements Runnable {
ourSourceID = is.read();
} catch (IOException e) {
clientLog("Three way handshake failed", 1);
}
if (ourSourceID != null) {
try {
@@ -174,7 +205,7 @@ public class ClientToServerThread implements Runnable {
}
public void closeSocket() {
private void closeSocket() {
try {
socket.close();
} catch (IOException e) {
@@ -182,6 +213,14 @@ public class ClientToServerThread implements Runnable {
}
}
public void setSocketToClose () {
socketOpen = false;
}
public Queue<StreamPacket> getPacketQueue () {
return streamPackets;
}
public void addStreamObserver (ClientSocketListener streamListener) {
listeners.add(streamListener);
}
@@ -190,7 +229,7 @@ public class ClientToServerThread implements Runnable {
listeners.remove(streamListener);
}
private int readByte() throws Exception {
private int readByte() throws ByteReadException {
int currentByte = -1;
try {
currentByte = is.read();
@@ -199,12 +238,12 @@ public class ClientToServerThread implements Runnable {
clientLog("Read byte failed", 1);
}
if (currentByte == -1) {
throw new Exception();
throw new ByteReadException("InputStream reach end of stream");
}
return currentByte;
}
private byte[] getBytes(int n) throws Exception {
private byte[] getBytes(int n) throws ByteReadException {
byte[] bytes = new byte[n];
for (int i = 0; i < n; i++) {
bytes[i] = (byte) readByte();
@@ -212,7 +251,7 @@ public class ClientToServerThread implements Runnable {
return bytes;
}
private void skipBytes(long n) throws Exception {
private void skipBytes(long n) throws ByteReadException {
for (int i = 0; i < n; i++) {
readByte();
}
@@ -3,29 +3,28 @@ package seng302.visualiser;
import java.io.IOException;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread;
import seng302.model.Yacht;
import seng302.model.RaceState;
import seng302.model.Yacht;
import seng302.model.mark.Mark;
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
import seng302.model.stream.parser.MarkRoundingData;
import seng302.model.stream.parser.RaceStatusData;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.parser.StreamParser;
import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.model.stream.xml.parser.XMLParser;
import seng302.model.stream.parser.PositionUpdateData;
import seng302.model.stream.packets.StreamPacket;
import seng302.visualiser.ClientToServerThread;
import seng302.model.stream.parser.MarkRoundingData;
import seng302.model.stream.parser.PositionUpdateData;
import seng302.model.stream.parser.PositionUpdateData.DeviceType;
import seng302.model.stream.parser.RaceStatusData;
import seng302.utilities.StreamParser;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.utilities.XMLParser;
import seng302.visualiser.controllers.LobbyController;
import seng302.visualiser.controllers.LobbyController.CloseStatus;
import seng302.visualiser.controllers.RaceViewController;
@@ -61,9 +60,10 @@ public class GameClient {
}
LobbyController lobbyController = loadLobby("/views/LobbyView.fxml");
lobbyController.setPlayerListSource(lobbyList);
lobbyController.disableReadyButton();
lobbyController.setTitle("Connected to host - IP : " + ipAddress + " Port : " + portNumber);
lobbyController.addCloseListener((exitCause) -> this.loadStartScreen());
socketThread.addStreamObserver(this::parsePacket);
socketThread.addStreamObserver(this::parsePackets);
}
public void runAsHost (String ipAddress, Integer portNumber) {
@@ -74,13 +74,13 @@ public class GameClient {
ioe.printStackTrace();
System.out.println("Unable to make local connection to host...");
}
LobbyController lobbyController = loadLobby("/views/HostLobbyView.fxml");
socketThread.addStreamObserver(this::parsePackets);
LobbyController lobbyController = loadLobby("/views/LobbyView.fxml");
lobbyController.setPlayerListSource(GameState.getObservablePlayers());
lobbyController.setTitle("Hosting Lobby - IP : " + ipAddress + " Port : " + portNumber);
lobbyController.addCloseListener(exitCause -> {
if (exitCause == CloseStatus.READY) {
server.startGame();
socketThread.addStreamObserver(this::parsePacket);
} else if (exitCause == CloseStatus.LEAVE) {
loadStartScreen();
}
@@ -88,11 +88,11 @@ public class GameClient {
}
private void loadStartScreen () {
socketThread.closeSocket();
socketThread.setSocketToClose();
socketThread = null;
if (server != null) {
// TODO: 26/07/17 cir27 - handle disconnecting
server.shutDown();
// server.shutDown();
server = null;
}
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/views/StartScreenView.fxml"));
@@ -125,68 +125,78 @@ public class GameClient {
// if (courseData.getParticipants().contains(id))
// racingBoats.put(id, boat);
// });
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/views/RaceView.fxml"));
raceView = fxmlLoader.getController();
FXMLLoader fxmlLoader = new FXMLLoader(RaceViewController.class.getResource("/views/RaceView.fxml"));
// raceView = fxmlLoader.getController();
try {
holderPane.getChildren().add(fxmlLoader.load());
Node node = fxmlLoader.load();
Platform.runLater(() -> {
holderPane.getChildren().clear();
holderPane.getChildren().add(node);
});
} catch (IOException e) {
e.printStackTrace();
}
raceView = fxmlLoader.getController();
raceView.loadRace(allBoatsMap, courseData, raceState);
}
private void parsePacket(StreamPacket packet) {
switch (packet.getType()) {
case RACE_STATUS:
processRaceStatusUpdate(StreamParser.extractRaceStatus(packet));
break;
private void parsePackets() {
while (socketThread.getPacketQueue().peek() != null) {
StreamPacket packet = socketThread.getPacketQueue().poll();
switch (packet.getType()) {
case RACE_STATUS:
processRaceStatusUpdate(StreamParser.extractRaceStatus(packet));
startRaceIfAllDataReceived();
break;
case REGATTA_XML:
System.out.println("REGATTA XML");
regattaData = XMLParser.parseRegatta(
StreamParser.extractXmlMessage(packet)
);
raceState.setTimeZone(
TimeZone.getTimeZone(
ZoneId.ofOffset("UTC", ZoneOffset.ofHours(regattaData.getUtcOffset()))
)
);
startRaceIfAllDataReceived();
break;
case REGATTA_XML:
System.out.println("REGATTA XML");
regattaData = XMLParser.parseRegatta(
StreamParser.extractXmlMessage(packet)
);
raceState.setTimeZone(
TimeZone.getTimeZone(
ZoneId.ofOffset("UTC", ZoneOffset.ofHours(regattaData.getUtcOffset()))
)
);
// startRaceIfAllDataReceived();
break;
case RACE_XML:
System.out.println("RACE XML");
courseData = XMLParser.parseRace(
StreamParser.extractXmlMessage(packet)
);
if (raceView != null) {
raceView.updateRaceData(courseData);
}
startRaceIfAllDataReceived();
break;
case RACE_XML:
System.out.println("RACE XML");
courseData = XMLParser.parseRace(
StreamParser.extractXmlMessage(packet)
);
if (raceView != null) {
raceView.updateRaceData(courseData);
}
// startRaceIfAllDataReceived();
break;
case BOAT_XML:
System.out.println("BOAT XML");
allBoatsMap = XMLParser.parseBoats(
StreamParser.extractXmlMessage(packet)
);
lobbyList.clear();
allBoatsMap.forEach((id, boat) -> lobbyList.add(id.toString() + boat.getBoatName()));
allBoatsMap.forEach((i, b) -> System.out.println(b.getBoatName()));
startRaceIfAllDataReceived();
break;
case BOAT_XML:
System.out.println("BOAT XML");
allBoatsMap = XMLParser.parseBoats(
StreamParser.extractXmlMessage(packet)
);
lobbyList.clear();
allBoatsMap
.forEach((id, boat) -> lobbyList.add(id.toString() + boat.getBoatName()));
allBoatsMap.forEach((i, b) -> System.out.println(b.getBoatName()));
// startRaceIfAllDataReceived();
break;
case RACE_START_STATUS:
raceState.updateState(StreamParser.extractRaceStartStatus(packet));
break;
case RACE_START_STATUS:
raceState.updateState(StreamParser.extractRaceStartStatus(packet));
break;
case BOAT_LOCATION:
updatePosition(StreamParser.extractBoatLocation(packet));
break;
case BOAT_LOCATION:
updatePosition(StreamParser.extractBoatLocation(packet));
break;
case MARK_ROUNDING:
updateMarkRounding(StreamParser.extractMarkRounding(packet));
break;
case MARK_ROUNDING:
updateMarkRounding(StreamParser.extractMarkRounding(packet));
break;
}
}
}
@@ -243,6 +253,7 @@ public class GameClient {
yacht.setEstimateTimeAtFinish(boatData[2]);
int legNumber = (int) boatData[3];
yacht.setLegNumber(legNumber);
yacht.setBoatStatus((int) boatData[4]);
if (legNumber != yacht.getLegNumber()) {
int placing = 1;
for (Yacht otherYacht : allBoatsMap.values()) {
@@ -257,7 +268,7 @@ public class GameClient {
}
private void close () {
socketThread.closeSocket();
socketThread.setSocketToClose();
}
// /** Handle the key-pressed event from the text field. */
+31 -28
View File
@@ -22,20 +22,18 @@ import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import seng302.model.Limit;
import seng302.visualiser.fxObjects.AnnotationBox;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.visualiser.fxObjects.MarkObject;
import seng302.model.Colors;
import seng302.model.Limit;
import seng302.model.Yacht;
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.utilities.GeoPoint;
import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.AnnotationBox;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.visualiser.fxObjects.MarkObject;
/**
* Created by cir27 on 20/07/17.
@@ -45,11 +43,11 @@ public class GameView extends Pane {
private ObservableList<Node> gameObjects;
private ImageView mapImage;
private final int BUFFER_SIZE = 50;
private final int PANEL_WIDTH = 1260; // it should be 1280 but, minors 40 to cancel the bias.
private final int PANEL_HEIGHT = 960;
private final int CANVAS_WIDTH = 1100;
private final int CANVAS_HEIGHT = 920;
private double bufferSize = 50;
private double panelWidth = 1260; // it should be 1280 but, minors 40 to cancel the bias.
private double panelHeight = 960;
private double canvasWidth = 1100;
private double canvasHeight = 920;
private boolean horizontalInversion = false;
private double distanceScaleFactor;
@@ -63,13 +61,14 @@ public class GameView extends Pane {
private double metersPerPixelX;
private double metersPerPixelY;
private Map<SingleMark, MarkObject> markObjects = new HashMap<>();
private Map<Yacht, BoatObject> boatObjects = new HashMap<>();
private List<AnnotationBox> annotations = new ArrayList<>();
private Text fpsDisplay = new Text();
private Polygon raceBorder = new Polygon();
/* Note that if either of these is null then values for it have not been added and the other
should be used as the limits of the map. */
private Polygon raceBorder;
private Map<SingleMark, MarkObject> markObjects = new HashMap<>();
//FRAME RATE
private Double frameRate = 60.0;
@@ -205,9 +204,13 @@ public class GameView extends Pane {
* in a compound mark etc..
*/
public void updateBorder(List<Limit> border) {
raceBorder.setStroke(new Color(0.0f, 0.0f, 0.74509807f, 1));
raceBorder.setStrokeWidth(3);
raceBorder.setFill(new Color(0,0,0,0));
if (raceBorder == null) {
raceBorder = new Polygon();
raceBorder.setStroke(new Color(0.0f, 0.0f, 0.74509807f, 1));
raceBorder.setStrokeWidth(3);
raceBorder.setFill(new Color(0,0,0,0));
findCanvasScaling();
}
List<Double> boundaryPoints = new ArrayList<>();
for (Limit limit : border) {
Point2D location = findScaledXY(limit.getLat(), limit.getLng());
@@ -393,24 +396,24 @@ public class GameView extends Pane {
if (scaleDirection == ScaleDirection.HORIZONTAL) {
referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, minLonPoint));
referencePointX = BUFFER_SIZE + distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint);
referencePointX = bufferSize + distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint);
referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, maxLatPoint));
referencePointY = canvasHeight - (BUFFER_SIZE + BUFFER_SIZE);
referencePointY = canvasHeight - (bufferSize + bufferSize);
referencePointY -= distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint);
referencePointY = referencePointY / 2;
referencePointY += BUFFER_SIZE;
referencePointY += bufferSize;
referencePointY += distanceScaleFactor * Math.cos(referenceAngle) * Mark.calculateDistance(referencePoint, maxLatPoint);
} else {
referencePointY = canvasHeight - BUFFER_SIZE;
referencePointY = canvasHeight - bufferSize;
referenceAngle = Math.abs(Mark.calculateHeadingRad(referencePoint, minLonPoint));
referencePointX = BUFFER_SIZE;
referencePointX = bufferSize;
referencePointX += distanceScaleFactor * Math.sin(referenceAngle) * Mark.calculateDistance(referencePoint, minLonPoint);
referencePointX += ((canvasWidth - (BUFFER_SIZE + BUFFER_SIZE)) - (minLonToMaxLon * distanceScaleFactor)) / 2;
referencePointX += ((canvasWidth - (bufferSize + bufferSize)) - (minLonToMaxLon * distanceScaleFactor)) / 2;
}
if(horizontalInversion) {
referencePointX = canvasWidth - BUFFER_SIZE - (referencePointX - BUFFER_SIZE);
referencePointX = canvasWidth - bufferSize - (referencePointX - bufferSize);
}
}
@@ -434,10 +437,10 @@ public class GameView extends Pane {
double horiDistance =
Math.cos(horiAngle) * Mark.calculateDistance(minLonPoint, maxLonPoint);
double vertScale = (canvasHeight - (BUFFER_SIZE + BUFFER_SIZE)) / vertDistance;
double vertScale = (canvasHeight - (bufferSize + bufferSize)) / vertDistance;
if ((horiDistance * vertScale) > (canvasWidth - (BUFFER_SIZE + BUFFER_SIZE))) {
distanceScaleFactor = (canvasWidth - (BUFFER_SIZE + BUFFER_SIZE)) / horiDistance;
if ((horiDistance * vertScale) > (canvasWidth - (bufferSize + bufferSize))) {
distanceScaleFactor = (canvasWidth - (bufferSize + bufferSize)) / horiDistance;
scaleDirection = ScaleDirection.HORIZONTAL;
} else {
distanceScaleFactor = vertScale;
@@ -479,7 +482,7 @@ public class GameView extends Pane {
yAxisLocation += Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
}
if(horizontalInversion) {
xAxisLocation = canvasWidth - BUFFER_SIZE - (xAxisLocation - BUFFER_SIZE);
xAxisLocation = canvasWidth - bufferSize - (xAxisLocation - bufferSize);
}
return new Point2D(xAxisLocation, yAxisLocation);
}
@@ -18,7 +18,6 @@ import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import seng302.model.Yacht;
import seng302.model.stream.parser.StreamParser;
public class FinishScreenViewController implements Initializable {
@@ -2,8 +2,9 @@ package seng302.visualiser.controllers;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
@@ -11,7 +12,6 @@ import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
@@ -36,9 +36,6 @@ public class LobbyController implements Initializable {
void notify(CloseStatus exitCause);
}
@FXML
private ListView<String> competitorsListView;
@FXML
private GridPane lobbyScreen;
@FXML
@@ -259,10 +256,13 @@ public class LobbyController implements Initializable {
@FXML
public void leaveLobbyButtonPressed() {
// TODO: 10/07/17 wmu16 - Finish function!
setContentPane("/views/StartScreenView.fxml");
// setContentPane("/views/StartScreenView.fxml");
GameState.setCurrentStage(GameStages.CANCELLED);
// TODO: 20/07/17 wmu16 - Implement some way of terminating the game
// ClientState.setConnectedToHost(false);
for (LobbyCloseListener readyListener : lobbyListeners)
readyListener.notify(CloseStatus.LEAVE);
}
@FXML
@@ -309,11 +309,15 @@ public class LobbyController implements Initializable {
}
public void setPlayerListSource (ObservableList<String> players) {
if (competitorsListView != null)
competitorsListView.setItems(players);
if (firstListView != null) {
// if (competitorsListView != null)
// competitorsListView.setItems(players);
// if (firstListView != null) {
firstListView.setItems(players);
firstImageView.setVisible(false);
}
// }
}
public void disableReadyButton () {
readyButton.setDisable(true);
}
}
@@ -1,5 +1,11 @@
package seng302.visualiser.controllers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
@@ -9,7 +15,6 @@ import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
@@ -30,7 +35,9 @@ import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import javafx.util.StringConverter;
import seng302.model.Corner;
import seng302.model.RaceState;
import seng302.model.Yacht;
import seng302.model.mark.Mark;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.visualiser.GameView;
import seng302.visualiser.controllers.annotations.Annotation;
@@ -38,11 +45,6 @@ import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.model.*;
import seng302.model.mark.Mark;
import java.io.IOException;
import java.util.*;
/**
* Controller class that manages the display of a race
@@ -92,6 +94,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
raceSparkLine.getYAxis().setAutoRanging(false);
sparklineYAxis.setTickMarkVisible(false);
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
}
@@ -189,11 +193,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
}
});
annotationSlider.setValue(2);
annotationSlider.valueProperty().addListener((obs, oldVal, newVal) ->
setAnnotations((int) annotationSlider.getValue())
);
annotationSlider.setValue(2);
}
@@ -368,14 +371,15 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
*/
private void updateOrder() {
positionVbox.getChildren().clear();
positionVbox.getChildren().removeAll();
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// positionVbox.getChildren().removeAll();
// positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
// list of racing yacht id
List<Yacht> sorted = new ArrayList<>(participants.values());
sorted.sort(Comparator.comparingInt(Yacht::getPositionInteger));
for (Yacht yacht : sorted) {
// System.out.println("yacht == null " + String.valueOf(yacht == null));
if (yacht.getBoatStatus() == 3) { // 3 is finish status
Text textToAdd = new Text(yacht.getPositionInteger() + ". " +
yacht.getShortName() + " (Finished)");
@@ -389,6 +393,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
textToAdd.setStyle("");
positionVbox.getChildren().add(textToAdd);
}
// System.out.println("finished a loop :))))))))))))");
}
// participants.forEach((id, yacht) ->{
// Text textToAdd = new Text(yacht.getPosition() + ". " +
@@ -1,25 +1,17 @@
package seng302.visualiser.controllers;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import seng302.client.ClientState;
import seng302.visualiser.ClientToServerThread;
import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread;
import java.io.IOException;
import java.net.InetAddress;
import seng302.visualiser.GameClient;
/**
@@ -1,5 +1,7 @@
package seng302.visualiser.controllers.annotations;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
@@ -7,8 +9,7 @@ import javafx.scene.control.CheckBox;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import java.net.URL;;
import java.util.ResourceBundle;
;
public class ImportantAnnotationController implements Initializable {
@@ -1,16 +1,14 @@
package seng302.visualiser.fxObjects;
import java.util.ArrayList;
import javafx.geometry.Point2D;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import seng302.model.Yacht;
/**
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
@@ -64,52 +62,49 @@ public class BoatObject extends Group {
* polygon.
*/
public BoatObject(double... points) {
public BoatGroup(Yacht boat, Color color, double... points) {
this.colour = colour;
destinationSet = false;
this.boat = boat;
initChildren(color, points);
initChildren(points);
}
/**
* Creates the javafx objects that will be the in the group by default.
*
* @param color The colour of the boat polygon and the trailing line.
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat
* polygon.
*/
private void initChildren(Color color, double... points) {
this.color = color;
private void initChildren(double... points) {
// this.colour = color;
boatPoly = new Polygon(points);
boatPoly.setFill(colour);
boatPoly.setFill(this.color);
boatPoly.setFill(this.colour);
boatPoly.setOnMouseEntered(event -> {
boatPoly.setFill(Color.FLORALWHITE);
boatPoly.setStroke(Color.RED);
});
boatPoly.setOnMouseExited(event -> {
boatPoly.setFill(colour);
boatPoly.setFill(this.color);
boatPoly.setFill(this.colour);
boatPoly.setStroke(Color.BLACK);
});
boatPoly.setOnMouseClicked(event -> setIsSelected(!isSelected));
boatPoly.setCache(true);
boatPoly.setCacheHint(CacheHint.SPEED);
annotationBox = new AnnotationBox();
annotationBox.setFill(colour);
boatAnnotations = new BoatAnnotations(boat, this.color);
// annotationBox = new AnnotationBox();
// annotationBox.setFill(colour);
leftLayLine = new Line();
rightLayline = new Line();
wake = new Wake(0, -BOAT_HEIGHT);
super.getChildren().addAll(boatPoly, annotationBox);
super.getChildren().addAll(boatPoly);//, annotationBox);
}
public void setFill (Paint value) {
this.colour = value;
boatPoly.setFill(colour);
annotationBox.setFill(colour);
// annotationBox.setFill(colour);
}
/**
@@ -207,14 +202,14 @@ public class BoatObject extends Group {
wake.setRotation(rotation, groundSpeed);
// yacht.setVelocity(groundSpeed);
lastTimeValid = timeValid;
boat.setVelocity(groundSpeed);
// boat.setVelocity(groundSpeed);
isStopped = false;
lastRotation = rotation;
boatAnnotations.update();
// boatAnnotations.update();
distanceTravelled += Math.sqrt((dx * dx) + (dy * dy));
if (distanceTravelled > 10 && isPlayer) {
if (distanceTravelled > 10){// && isPlayer) {
distanceTravelled = 0d;
if (lastPoint != null) {
@@ -225,7 +220,7 @@ public class BoatObject extends Group {
boatPoly.getLayoutY()
);
l.getStrokeDashArray().setAll(3d, 7d);
l.setStroke(boat.getColour());
l.setStroke(this.colour);
l.setCache(true);
l.setCacheHint(CacheHint.SPEED);
lineGroup.getChildren().add(l);
@@ -280,8 +275,7 @@ public class BoatObject extends Group {
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.setVisible(teamName, velocity, estTime, legTime);
// boatAnnotations.setVisible(teamName, velocity, estTime, legTime);
this.wake.setVisible(wake);
this.lineGroup.setVisible(trail);
}
@@ -336,23 +330,18 @@ public class BoatObject extends Group {
return isStopped;
}
@Override
public String toString() {
return boat.toString();
}
/**
* Sets this boat to appear highlighted
*/
public void setAsPlayer() {
boatPoly.getPoints().setAll(
-BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75,
0.0, -BOAT_HEIGHT / 1.75,
BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75
);
boatPoly.setStroke(Color.BLACK);
boatPoly.setStrokeWidth(3);
boatAnnotations.setAsPlayer();
isPlayer = true;
// boatPoly.getPoints().setAll(
// -BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75,
// 0.0, -BOAT_HEIGHT / 1.75,
// BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75
// );
// boatPoly.setStroke(Color.BLACK);
// boatPoly.setStrokeWidth(3);
// boatAnnotations.setAsPlayer();
// isPlayer = true;
}
}
@@ -1,4 +1,4 @@
package seng302.model.map;
package seng302.visualiser.map;
/**
* The Boundary class represents a rectangle territorial boundary on a map. It
@@ -7,11 +7,11 @@ package seng302.model.map;
*
* Created by Haoming on 10/5/17
*/
public class Boundary {
class Boundary {
private double northLat, eastLng, southLat, westLng;
public Boundary(double northLat, double eastLng, double southLat, double westLng) {
Boundary(double northLat, double eastLng, double southLat, double westLng) {
this.northLat = northLat;
this.eastLng = eastLng;
this.southLat = southLat;
@@ -1,13 +1,10 @@
package seng302.model.map;
package seng302.visualiser.map;
import java.net.URL;
import javafx.geometry.Point2D;
import javafx.scene.image.Image;
import seng302.utilities.GeoPoint;
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
import java.lang.Math;
import seng302.utilities.GeoPoint;
/**
* CanvasMap retrieves a map image with given geo boundary from Google Map server.
@@ -25,12 +22,12 @@ public class CanvasMap {
private String KEY = "AIzaSyC-5oOShMCY5Oy_9L7guYMPUPFHDMr37wE";
public CanvasMap(Boundary boundary) {
CanvasMap(Boundary boundary) {
this.boundary = boundary;
calculateOptimalMapSize();
}
public Image getMapImage() {
Image getMapImage() {
try {
URL url = new URL(getRequest());
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
@@ -1,4 +1,4 @@
package seng302.model.map;
package seng302.visualiser.map;
import javafx.geometry.Point2D;
import seng302.utilities.GeoPoint;
@@ -28,7 +28,7 @@ public class MercatorProjection {
* @param geo GeoPoint (lat, lng) location to be projected
* @return the projection Point2D (x, y) on planar
*/
public static Point2D toMapPoint(GeoPoint geo) {
static Point2D toMapPoint(GeoPoint geo) {
double x, y;
Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0);
x = (origin.getX() + geo.getLng() * pixelsPerLngDegree);
@@ -1,13 +1,12 @@
package seng302.model.map;
package seng302.visualiser.map;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import java.net.URL;
import java.util.ResourceBundle;
public class TestMapController implements Initializable{
@FXML
+10 -6
View File
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<GridPane fx:id="finishScreenGridPane" maxHeight="837.0" maxWidth="837.0" minHeight="837.0" minWidth="837.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="837.0" prefWidth="837.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.FinishScreenViewController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
+8 -4
View File
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<GridPane fx:id="lobbyScreen" nodeOrientation="LEFT_TO_RIGHT" prefHeight="533.0" prefWidth="802.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
+10 -6
View File
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<GridPane fx:id="lobbyScreen" nodeOrientation="LEFT_TO_RIGHT" prefHeight="960.0" prefWidth="1530.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
+19 -9
View File
@@ -1,12 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<?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?>
<GridPane prefHeight="960.0" prefWidth="1530.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.RaceViewController">
<columnConstraints>
<ColumnConstraints maxWidth="246.0" minWidth="246.0" prefWidth="246.0" />
@@ -55,7 +65,7 @@
<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="boatSelectionComboBox" focusTraversable="false" layoutX="37.0" layoutY="664.0" prefHeight="25.0" prefWidth="170.0" promptText="Select Boat" styleClass="combo-box-base" />
<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" />
@@ -66,7 +76,7 @@
</LineChart>
</children>
</AnchorPane>
<AnchorPane fx:id="contentAnchorPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" style="-fx-background-color: skyblue;" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2147483647" GridPane.valignment="TOP">
<AnchorPane fx:id="contentAnchorPane" style="-fx-background-color: skyblue;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2147483647" GridPane.valignment="TOP">
</AnchorPane>
</children>
+10 -6
View File
@@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="holder" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="960.0" prefWidth="1530.0" style="-fx-background-color: #2C2c36;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.StartScreenController">
<children>
<GridPane fx:id="startScreen2" layoutX="365.0" layoutY="285.0" nodeOrientation="LEFT_TO_RIGHT" prefWidth="800.0" style="-fx-background-color: #2C2c36;">
+3 -6
View File
@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.canvas.*?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="960.0" prefWidth="1280.0" style="-fx-background-color: #ddd;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.model.map.TestMapController">
<?import javafx.scene.canvas.Canvas?>
<?import javafx.scene.layout.Pane?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="960.0" prefWidth="1280.0" style="-fx-background-color: #ddd;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.map.TestMapController">
<children>
<Canvas fx:id="mapCanvas" height="960.0" width="1280.0" />
</children>
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="annotationSelectWindow" maxHeight="270.0" maxWidth="469.0" minHeight="270.0" minWidth="469.0" prefHeight="270.0" prefWidth="469.0" styleClass="background-blue" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Text fill="WHITE" layoutX="26.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Select important annotations">
-3
View File
@@ -5,9 +5,6 @@ import org.junit.Assert;
import org.junit.Test;
import seng302.model.Colors;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class ColorsTest {
@Test
+3 -2
View File
@@ -1,12 +1,13 @@
package seng302;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import javafx.geometry.Point2D;
import org.junit.Before;
import org.junit.Test;
import seng302.utilities.GeoUtility;
import static org.junit.Assert.*;
/**
* Test Class for the GeometryUtils class
* Created by wmu16 on 24/05/17.
-3
View File
@@ -1,9 +1,6 @@
package seng302;
import org.junit.Test;
import seng302.visualiser.controllers.RaceViewController;
import static org.junit.Assert.assertTrue;
public class TestRaceTimer {
@@ -1,10 +1,11 @@
package seng302.model.mark;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by Haoming on 17/3/17.
*/
@@ -1,106 +0,0 @@
package seng302.model.stream;
import org.junit.Before;
import org.junit.Test;
import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import seng302.model.stream.packets.StreamPacket;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Created by ptg19 on 26/04/17.
*/
public class StreamReceiverTest {
private PriorityBlockingQueue pq;
private byte[] brokenPacket = {0x47, (byte) 0x83, 37, // sync1 sync2 and message type
0b00000000, 0b01000000, 0b00100010, 0b00100100, 0b00011000, 0b00000000, //timestamp
0b00000000, 0b00010000, 0b01000000, 0b00000000, //source id
0b00100010, 0b00101000, // message length
0b00010010, 0b00010010, 0b00010010}; //random start of payload
private byte[] workingPacket = {0x47, (byte) 0x83, 37, // sync1 sync2 and message type
0b00000000, 0b01000000, 0b00100010, 0b00100100, 0b00011000, 0b00000000, //timestamp
0b00000000, 0b00010000, 0b01000000, 0b00000000, //source id
0b00000010, 0b00000000, // message length
0b00010010, 0b00010010, // payload
0b00100110, (byte)0b10000111, 0b00110101, 0b01111000}; //crc
private byte[] crcMismatchPacket = {0x47, (byte) 0x83, 37, // sync1 sync2 and message type
0b00000000, 0b01000000, 0b00100010, 0b00100100, 0b00011000, 0b00000000, //timestamp
0b00000000, 0b00000000, 0b01000000, 0b00000000, //source id
0b00000010, 0b00000000, // message length
0b00010010, 0b00010010, // payload
0b00100110, (byte)0b10000111, 0b00110101, 0b01111000}; //crc
@Before
public void setup(){
pq = new PriorityBlockingQueue<>(256, new Comparator<StreamPacket>() {
@Override
public int compare(StreamPacket s1, StreamPacket s2) {
return (int) (s1.getTimeStamp() - s2.getTimeStamp());
}
});
}
@Test
public void connectExitsOnUnexpectedStreamEnd() throws Exception {
Socket host=mock(Socket.class);
InputStream stream = new ByteArrayInputStream(brokenPacket);
when(host.getInputStream()).thenReturn(stream);
StreamReceiver streamReceiver = new StreamReceiver(host, pq);
streamReceiver.connect();
assert pq.size() == 0;
}
// @Test
// public void connectReadsAPacket() throws Exception {
// Socket host=mock(Socket.class);
// InputStream stream = new ByteArrayInputStream(workingPacket);
// when(host.getInputStream()).thenReturn(stream);
// StreamReceiver streamReceiver = new StreamReceiver(host, pq);
//
// streamReceiver.connect();
// assert pq.size() == 1;
// }
@Test
public void connectDropsAMismatchedCrc() throws Exception {
Socket host=mock(Socket.class);
InputStream stream = new ByteArrayInputStream(crcMismatchPacket);
when(host.getInputStream()).thenReturn(stream);
StreamReceiver streamReceiver = new StreamReceiver(host, pq);
streamReceiver.connect();
assert pq.size() == 0;
}
@Test
public void bytestoLongTest() {
Socket host=mock(Socket.class);
StreamReceiver streamReceiver = new StreamReceiver(host, pq);
try {
Class[] args = new Class[1];
args[0] = byte[].class;
Method bytesToLong = streamReceiver.getClass().getDeclaredMethod("bytesToLong", args);
bytesToLong.setAccessible(true);
byte[] sevenBtyeNumber = {0b01100100, 0b00110100, 0b00010100, 0b00000000, 0b00000000, 0b00000000, (byte)0b10000000};
assert bytesToLong.invoke(streamReceiver, sevenBtyeNumber).equals(36028797020288100L);
byte[] eightByteNumber = {0b01100100, 0b00110100, 0b00010100, 0b00000000, 0b00000000, 0b00000000, (byte)0b10000000, 0b00100101};
assert bytesToLong.invoke(streamReceiver, eightByteNumber).equals(-1L);
byte[] emptyArray = {};
assert bytesToLong.invoke(streamReceiver, emptyArray).equals(0L);
} catch (Exception e){
e.printStackTrace();
}
}
}
@@ -1,10 +1,10 @@
package seng302.server;
import static junit.framework.TestCase.assertEquals;
import org.junit.Test;
import seng302.server.messages.BoatLocationMessage;
import static junit.framework.TestCase.assertEquals;
/**
* Test conversions used by the boat location messages
*/
+4 -3
View File
@@ -1,10 +1,11 @@
package seng302.server;
import org.junit.Test;
import seng302.server.messages.*;
import static junit.framework.TestCase.assertTrue;
import org.junit.Test;
import seng302.server.messages.Header;
import seng302.server.messages.MessageType;
/**
* Tests message header
*/
@@ -1,17 +1,13 @@
package seng302.server;
import org.junit.Test;
import seng302.server.messages.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import org.junit.Test;
import seng302.server.messages.Message;
import seng302.server.messages.XMLMessage;
import seng302.server.messages.XMLMessageSubType;
public class TestMessage {
private static int XML_MESSAGE_LEN = 14;
private static int CRC_LEN = 4;
@@ -1,11 +1,11 @@
package seng302.server.simulator;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import seng302.utilities.GeoPoint;
import seng302.utilities.GeoUtility;
import static org.junit.Assert.*;
/**
* To test methods in GeoUtility.
* Created by Haoming on 28/04/17.
@@ -1,10 +1,10 @@
package seng302.model.map;
package seng302.visualiser.map;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import seng302.utilities.GeoPoint;
import static org.junit.Assert.*;
/**
* Unit test for Mercator Project class.
* Created by hyi25 on 15/05/17.
@@ -1,13 +1,13 @@
package seng302.visualizer.annotations;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import seng302.visualiser.controllers.annotations.Annotation;
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
import static org.junit.Assert.assertEquals;
public class TestImportantAnnotationState {
private ImportantAnnotationsState importantAnnotationsState;