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