Merge branch 'master' into story_61
Also got client-server handshake working. Multiple clients can connect and control their own boat. The client's boat has a larger black triangle drawn around it. Probably needs tidying up. Added isClientBoat boolean to VisualiserBoat. WindGenerator is now an interface, implemented by ConstantWindGenerator (useful for testing) and RandomWindGenerator. Added ConstantWindGeneratorTest. RandomWindGenerator was formerly WindGenerator. The WindGenerator is passed in to MockRace. CommandFactory throws a CommandConstructionException if it cannot create a command. MessageSerialiser and MessageDeserialiser correctly terminate on error. Readded VisualiserInput's switch statement in the main loop, pending a refactor. Removed the sleep statement from LobbyController - it was blocking javaFX thread. Lobby.fxml: moved buttons and text input into grid panes, so they don't break when you resize screen. Added some test object creation functions in several test classes (MockRaceTest.createMockRace(), BoatXMLReaderTest.createBoatDataSource(), etc...). #story[1095]
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
package mock.app;
|
||||
|
||||
import mock.enums.ConnectionStateEnum;
|
||||
import mock.model.RaceLogic;
|
||||
import mock.model.ClientConnection;
|
||||
import mock.model.SourceIdAllocator;
|
||||
import mock.model.commandFactory.CompositeCommand;
|
||||
import network.Messages.Enums.XMLMessageType;
|
||||
import network.Messages.LatestMessages;
|
||||
import network.Messages.RaceSnapshot;
|
||||
import network.Messages.XMLMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -65,19 +64,23 @@ public class ConnectionAcceptor implements Runnable {
|
||||
private short boatXMLSequenceNumber;
|
||||
//regatta xml sequence number
|
||||
private short regattaXMLSequenceNumber;
|
||||
//
|
||||
private RaceLogic raceLogic = null;
|
||||
|
||||
/**
|
||||
* Connection Acceptor Constructor
|
||||
* @param latestMessages Latest messages to be sent
|
||||
* @param compositeCommand Collection of commands for race to execute.
|
||||
* @param sourceIdAllocator Object used to allocate source IDs for clients.
|
||||
* @param raceLogic The race the client will connect to.
|
||||
* @throws IOException if a server socket cannot be instantiated.
|
||||
*/
|
||||
public ConnectionAcceptor(LatestMessages latestMessages, CompositeCommand compositeCommand, SourceIdAllocator sourceIdAllocator) throws IOException {
|
||||
public ConnectionAcceptor(LatestMessages latestMessages, CompositeCommand compositeCommand, SourceIdAllocator sourceIdAllocator, RaceLogic raceLogic) throws IOException {
|
||||
|
||||
this.latestMessages = latestMessages;
|
||||
this.compositeCommand = compositeCommand;
|
||||
this.sourceIdAllocator = sourceIdAllocator;
|
||||
this.raceLogic = raceLogic;
|
||||
|
||||
this.serverSocket = new ServerSocket(serverPort);
|
||||
CheckClientConnection checkClientConnection = new CheckClientConnection(clientConnections);
|
||||
@@ -93,6 +96,8 @@ public class ConnectionAcceptor implements Runnable {
|
||||
return serverPort;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run the Acceptor
|
||||
*/
|
||||
@@ -103,11 +108,13 @@ public class ConnectionAcceptor implements Runnable {
|
||||
|
||||
try {
|
||||
|
||||
System.out.println("Waiting for a connection...");//TEMP DEBUG REMOVE
|
||||
|
||||
Socket mockSocket = serverSocket.accept();
|
||||
|
||||
ClientConnection clientConnection = new ClientConnection(mockSocket, sourceIdAllocator, latestMessages, compositeCommand);
|
||||
Logger.getGlobal().log(Level.INFO, String.format("Client connected. client ip/port = %s. Local ip/port = %s.", mockSocket.getRemoteSocketAddress(), mockSocket.getLocalSocketAddress()));
|
||||
|
||||
|
||||
ClientConnection clientConnection = new ClientConnection(mockSocket, sourceIdAllocator, latestMessages, compositeCommand, raceLogic);
|
||||
|
||||
clientConnections.add(clientConnection);
|
||||
|
||||
@@ -153,6 +160,7 @@ public class ConnectionAcceptor implements Runnable {
|
||||
for (ClientConnection client : clientConnections) {
|
||||
if (!client.isAlive()) {
|
||||
connections.remove(client);
|
||||
client.terminate();
|
||||
|
||||
Logger.getGlobal().log(Level.WARNING, "CheckClientConnection is removing the dead connection: " + client);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ package mock.app;
|
||||
|
||||
import mock.dataInput.PolarParser;
|
||||
import mock.exceptions.EventConstructionException;
|
||||
import mock.model.MockRace;
|
||||
import mock.model.Polars;
|
||||
import mock.model.RaceLogic;
|
||||
import mock.model.SourceIdAllocator;
|
||||
import mock.model.*;
|
||||
import mock.model.commandFactory.CompositeCommand;
|
||||
import network.Messages.LatestMessages;
|
||||
import network.Messages.RaceSnapshot;
|
||||
@@ -15,6 +12,7 @@ import shared.exceptions.InvalidBoatDataException;
|
||||
import shared.exceptions.InvalidRaceDataException;
|
||||
import shared.exceptions.InvalidRegattaDataException;
|
||||
import shared.exceptions.XMLReaderException;
|
||||
import shared.model.Bearing;
|
||||
import shared.model.Constants;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
@@ -67,15 +65,27 @@ public class Event {
|
||||
|
||||
/**
|
||||
* Constructs an event, using various XML files.
|
||||
* @param singlePlayer Whether or not to create a single player event.
|
||||
* @throws EventConstructionException Thrown if we cannot create an Event for any reason.
|
||||
*/
|
||||
public Event() throws EventConstructionException {
|
||||
public Event(boolean singlePlayer) throws EventConstructionException {
|
||||
|
||||
singlePlayer = false;
|
||||
|
||||
String raceXMLFile = "mock/mockXML/raceTest.xml";
|
||||
String boatsXMLFile = "mock/mockXML/boatTest.xml";
|
||||
String regattaXMLFile = "mock/mockXML/regattaTest.xml";
|
||||
|
||||
if (singlePlayer) {
|
||||
raceXMLFile = "mock/mockXML/raceSinglePlayer.xml";
|
||||
boatsXMLFile = "mock/mockXML/boatsSinglePlayer.xml";
|
||||
}
|
||||
|
||||
//Read XML files.
|
||||
try {
|
||||
this.raceXML = getRaceXMLAtCurrentTime(XMLReader.readXMLFileToString("mock/mockXML/raceTest.xml", StandardCharsets.UTF_8));
|
||||
this.boatXML = XMLReader.readXMLFileToString("mock/mockXML/boatsSinglePlayer.xml", StandardCharsets.UTF_8);
|
||||
this.regattaXML = XMLReader.readXMLFileToString("mock/mockXML/regattaTest.xml", StandardCharsets.UTF_8);
|
||||
this.raceXML = getRaceXMLAtCurrentTime(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8));
|
||||
this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8);
|
||||
this.regattaXML = XMLReader.readXMLFileToString(regattaXMLFile, StandardCharsets.UTF_8);
|
||||
|
||||
} catch (TransformerException | XMLReaderException e) {
|
||||
throw new EventConstructionException("Could not read XML files.", e);
|
||||
@@ -98,17 +108,48 @@ public class Event {
|
||||
|
||||
}
|
||||
|
||||
//Create connection acceptor.
|
||||
this.sourceIdAllocator = new SourceIdAllocator(raceDataSource.getParticipants());
|
||||
this.compositeCommand = new CompositeCommand();
|
||||
this.latestMessages = new LatestMessages();
|
||||
|
||||
//Create and start race.
|
||||
WindGenerator windGenerator = new RandomWindGenerator(
|
||||
Bearing.fromDegrees(225),
|
||||
Bearing.fromDegrees(215),
|
||||
Bearing.fromDegrees(235),
|
||||
12d,
|
||||
8d,
|
||||
16d );
|
||||
RaceLogic newRace = new RaceLogic(
|
||||
new MockRace(
|
||||
boatDataSource,
|
||||
raceDataSource,
|
||||
regattaDataSource,
|
||||
this.latestMessages,
|
||||
this.boatPolars,
|
||||
Constants.RaceTimeScale,
|
||||
windGenerator ),
|
||||
this.latestMessages,
|
||||
this.compositeCommand);
|
||||
|
||||
new Thread(newRace, "Event.Start()->RaceLogic thread").start();
|
||||
|
||||
|
||||
//Create connection acceptor.
|
||||
|
||||
try {
|
||||
this.connectionAcceptor = new ConnectionAcceptor(latestMessages, compositeCommand, sourceIdAllocator);
|
||||
this.connectionAcceptor = new ConnectionAcceptor(latestMessages, compositeCommand, sourceIdAllocator, newRace);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new EventConstructionException("Could not create ConnectionAcceptor.", e);
|
||||
}
|
||||
|
||||
|
||||
new Thread(connectionAcceptor, "Event.Start()->ConnectionAcceptor thread").start();
|
||||
|
||||
sendXMLs();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -125,16 +166,8 @@ public class Event {
|
||||
* Sends the initial race data and then begins race simulation.
|
||||
*/
|
||||
public void start() {
|
||||
new Thread(connectionAcceptor, "Event.Start()->ConnectionAcceptor thread").start();
|
||||
|
||||
sendXMLs();
|
||||
|
||||
|
||||
|
||||
//Create and start race.
|
||||
RaceLogic newRace = new RaceLogic(new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.latestMessages, this.boatPolars, Constants.RaceTimeScale), this.latestMessages, this.compositeCommand);
|
||||
|
||||
new Thread(newRace, "Event.Start()->RaceLogic thread").start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user