Added empty data sources, to be used by VisualiserRace.

Created FrameRateTracker which can be used to track framerate.
Updated RequestToJoinEnum and JoinAcceptanceEnum to match the agreed connection API.
Added AssignPlayerBoat message, which is used internally on the client to assign the player a source ID once they have connected.
Fixed some race conditions in the MessageRouter.
Updated ConnectionAcceptor.CheckClientConnection to wait slightly longer before removing connection (there was a slight race condition before).
Race no longer has a reference to LatestMessages. LatestMessages no longer has specific messages types in it.
Created RaceState class, which contains the state that is shared between VisualiserRaceState and MockRaceState (currently only used on visualiser).
Split VisualiserRace into VisualiserRaceState and VisualiserRaceService.
Added the VisualiserRace commands (BoatLocatonCommand, RaceStatusCommand, etc...).
Slightly increased the preferred width of race.fxml table columns.
issues #27 #37 #35
#story[1095]
This commit is contained in:
fjc40
2017-08-14 00:53:05 +12:00
parent 89b0aa8b77
commit 7366aba5ec
53 changed files with 2498 additions and 1129 deletions
@@ -13,7 +13,12 @@ import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -36,7 +41,7 @@ public class ConnectionAcceptor implements Runnable {
/**
* List of client connections.
*/
private ArrayBlockingQueue<ClientConnection> clientConnections = new ArrayBlockingQueue<>(16, true);
private BlockingQueue<ClientConnection> clientConnections = new ArrayBlockingQueue<>(16, true);
/**
* Snapshot of the race.
@@ -137,13 +142,13 @@ public class ConnectionAcceptor implements Runnable {
*/
class CheckClientConnection implements Runnable{
private ArrayBlockingQueue<ClientConnection> connections;
private BlockingQueue<ClientConnection> connections;
/**
* Constructor
* @param connections Clients "connected"
*/
public CheckClientConnection(ArrayBlockingQueue<ClientConnection> connections){
public CheckClientConnection(BlockingQueue<ClientConnection> connections){
this.connections = connections;
}
@@ -153,13 +158,29 @@ public class ConnectionAcceptor implements Runnable {
@Override
public void run() {
while(true) {
//System.out.println(connections.size());//used to see current amount of visualisers connected.
ArrayBlockingQueue<ClientConnection> clientConnections = new ArrayBlockingQueue<>(16, true, connections);
//We track the number of times each connection fails the !isAlive() test.
//This is to give a bit of lee-way in case the connection checker checks a connection before its thread has actually started.
Map<ClientConnection, Integer> connectionDeadCount = new HashMap<>();
while(!Thread.interrupted()) {
//Make copy of connections.
List<ClientConnection> clientConnections = new ArrayList<>(connections);
for (ClientConnection client : clientConnections) {
connectionDeadCount.put(client, connectionDeadCount.getOrDefault(client, 0));
if (!client.isAlive()) {
//Add one to fail count.
connectionDeadCount.put(client, connectionDeadCount.get(client) + 1);
}
//We only remove them if they fail 5 times.
if (connectionDeadCount.get(client) > 5) {
connections.remove(client);
connectionDeadCount.remove(client);
client.terminate();
Logger.getGlobal().log(Level.WARNING, "CheckClientConnection is removing the dead connection: " + client);
@@ -127,7 +127,6 @@ public class Event {
boatDataSource,
raceDataSource,
regattaDataSource,
this.latestMessages,
this.boatPolars,
Constants.RaceTimeScale,
windGenerator ),
@@ -245,7 +245,7 @@ public class ClientConnection implements Runnable {
private void sendJoinAcceptanceMessage(int sourceID) throws HandshakeException {
//Send them the source ID.
JoinAcceptance joinAcceptance = new JoinAcceptance(JoinAcceptanceEnum.JOIN_SUCCESSFUL, sourceID);
JoinAcceptance joinAcceptance = new JoinAcceptance(JoinAcceptanceEnum.JOIN_SUCCESSFUL_PARTICIPANT, sourceID);
try {
outputQueue.put(joinAcceptance);
@@ -53,14 +53,13 @@ public class MockRace extends Race {
* @param boatDataSource Data source for boat related data (yachts and marker boats).
* @param raceDataSource Data source for race related data (participating boats, legs, etc...).
* @param regattaDataSource Data source for race related data (course name, location, timezone, etc...).
* @param latestMessages The LatestMessages to send events to.
* @param polars The polars table to be used for boat simulation.
* @param timeScale The timeScale for the race. See {@link Constants#RaceTimeScale}.
* @param windGenerator The wind generator used for the race.
*/
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, LatestMessages latestMessages, Polars polars, int timeScale, WindGenerator windGenerator) {
public MockRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, Polars polars, int timeScale, WindGenerator windGenerator) {
super(boatDataSource, raceDataSource, regattaDataSource, latestMessages);
super(boatDataSource, raceDataSource, regattaDataSource);
this.scaleFactor = timeScale;
@@ -456,7 +455,5 @@ public class MockRace extends Race {
}
public List<CompoundMark> getCompoundMarks() {
return compoundMarks;
}
}