SourceIdAllocator now allocates from the BoatDataSource and RaceDataSource exposed by MockRace, instead of having its own source IDs. Can only allocate ids during PRESTART period.

RaceLogic now calls MockRace.initialiseBoats() after the prestart period has finished.
MockRace create a VisualiserBoat when a source ID is allocated.
MockOutput now sends updated XML messages during the race, instead of only at the start.
#story[1188]
main
fjc40 8 years ago
parent 3176e76c8c
commit d0eebcdb2f

@ -27,7 +27,12 @@ public class MockOutput implements RunnableWithFramePeriod {
*/ */
private LatestMessages latestMessages; private LatestMessages latestMessages;
//These sequence number track the last race/boat/regatta xml message we've sent.
private int lastSentRaceNumber = -1;
private int lastSentBoatNumber = -1;
private int lastSentRegattaNumber = -1;
@ -69,7 +74,6 @@ public class MockOutput implements RunnableWithFramePeriod {
long previousFrameTime = System.currentTimeMillis(); long previousFrameTime = System.currentTimeMillis();
boolean sentXMLs = false;
@ -82,16 +86,26 @@ public class MockOutput implements RunnableWithFramePeriod {
previousFrameTime = currentFrameTime; previousFrameTime = currentFrameTime;
//Send XML messages.
if (!sentXMLs) {
//Send XML messages if needed.
if (lastSentRaceNumber != latestMessages.getRaceXMLMessage().getSequenceNumber()) {
lastSentRaceNumber = latestMessages.getRaceXMLMessage().getSequenceNumber();
outgoingMessages.put(latestMessages.getRaceXMLMessage()); outgoingMessages.put(latestMessages.getRaceXMLMessage());
outgoingMessages.put(latestMessages.getRegattaXMLMessage()); }
if (lastSentBoatNumber != latestMessages.getBoatXMLMessage().getSequenceNumber()) {
lastSentBoatNumber = latestMessages.getBoatXMLMessage().getSequenceNumber();
outgoingMessages.put(latestMessages.getBoatXMLMessage()); outgoingMessages.put(latestMessages.getBoatXMLMessage());
}
sentXMLs = true; if (lastSentRegattaNumber != latestMessages.getRegattaXMLMessage().getSequenceNumber()) {
lastSentRegattaNumber = latestMessages.getRegattaXMLMessage().getSequenceNumber();
outgoingMessages.put(latestMessages.getRegattaXMLMessage());
} }
List<AC35Data> snapshot = latestMessages.getSnapshot(); List<AC35Data> snapshot = latestMessages.getSnapshot();
for (AC35Data message : snapshot) { for (AC35Data message : snapshot) {
outgoingMessages.put(message); outgoingMessages.put(message);

@ -43,7 +43,7 @@ public class MockRace extends RaceState {
/** /**
* Registry for all collider object in this race * Registry for all collider object in this race
*/ */
protected ColliderRegistry colliderRegistry; private ColliderRegistry colliderRegistry;
/** /**
@ -58,6 +58,12 @@ public class MockRace extends RaceState {
private WindGenerator windGenerator; private WindGenerator windGenerator;
/**
* The polars file to use for each boat.
*/
private Polars polars;
/** /**
* Constructs a race object with a given RaceDataSource, BoatDataSource, and RegattaDataSource and sends events to the given mockOutput. * Constructs a race object with a given RaceDataSource, BoatDataSource, and RegattaDataSource and sends events to the given mockOutput.
@ -74,9 +80,10 @@ public class MockRace extends RaceState {
this.setRaceDataSource(raceDataSource); this.setRaceDataSource(raceDataSource);
this.setRegattaDataSource(regattaDataSource); this.setRegattaDataSource(regattaDataSource);
this.polars = polars;
this.scaleFactor = timeScale; this.scaleFactor = timeScale;
this.boats = this.generateMockBoats(boatDataSource.getBoats(), raceDataSource.getParticipants(), polars); this.boats = new ArrayList<>();
this.shrinkBoundary = GPSCoordinate.getShrinkBoundary(this.getBoundary()); this.shrinkBoundary = GPSCoordinate.getShrinkBoundary(this.getBoundary());
@ -100,31 +107,35 @@ public class MockRace extends RaceState {
/** /**
* Generates a list of MockBoats given a list of Boats, and a list of participating boats. * Generates a MockBoat from the BoatDataSource, given a source ID. Also adds it to the participant list.
* @param boats The map of Boats describing boats that are potentially in the race. Maps boat sourceID to boat. * @param sourceID The source ID to assign the boat.
* @param sourceIDs The list of boat sourceIDs describing which specific boats are actually participating. * @return A MockBoat that is now participating in the race.
* @param polars The polars table to be used for boat simulation.
* @return A list of MockBoats that are participating in the race.
*/ */
private List<MockBoat> generateMockBoats(Map<Integer, Boat> boats, List<Integer> sourceIDs, Polars polars) { public void generateMockBoat(Integer sourceID) {
List<MockBoat> mockBoats = new ArrayList<>(sourceIDs.size());
//For each sourceID participating... //Get the boat associated with the sourceID.
for (int sourceID : sourceIDs) { Boat boat = getBoatDataSource().getBoats().get(sourceID);
//Get the boat associated with the sourceID. //Construct a MockBoat using the Boat and Polars.
Boat boat = boats.get(sourceID); MockBoat mockBoat = new MockBoat(boat, polars);
mockBoat.setCurrentLeg(this.getLegs().get(0));
//Construct a MockBoat using the Boat and Polars. //Update participant list.
MockBoat mockBoat = new MockBoat(boat, polars); getRaceDataSource().getParticipants().add(sourceID);
mockBoats.add(mockBoat); this.boats.add(mockBoat);
} getRaceDataSource().incrementSequenceNumber();
}
return mockBoats;
/**
* Removes a MockBoat from the race, by sourceID. Also removes it from the participant list.
* @param sourceID Source ID of boat to remove.
*/
public void removeMockBoat(Integer sourceID) {
this.boats.removeIf(mockBoat -> mockBoat.getSourceID() == sourceID);
getRaceDataSource().getParticipants().remove(sourceID);
getRaceDataSource().incrementSequenceNumber();
} }

@ -48,6 +48,9 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer {
*/ */
@Override @Override
public void run() { public void run() {
prestartCountdown();
race.initialiseBoats(); race.initialiseBoats();
countdown(); countdown();
@ -60,6 +63,35 @@ public class RaceLogic implements RunnableWithFramePeriod, Observer {
} }
/**
* The countdown timer until the prestart period is finished. This timer will stop 3 minutes before the race starts, and players can no longer start participating.
*/
private void prestartCountdown() {
long previousFrameTime = System.currentTimeMillis();
while (((race.getRaceStatusEnum() == RaceStatusEnum.PRESTART)
|| (race.getRaceStatusEnum() == RaceStatusEnum.NOT_ACTIVE)) && loopBool) {
long currentTime = System.currentTimeMillis();
//Update race time.
race.updateRaceTime(currentTime);
//Update the race status based on the current time.
race.updateRaceStatusEnum();
//Provide boat's with an estimated time at next mark until the race starts.
race.setBoatsTimeNextMark(race.getRaceClock().getCurrentTime());
//Parse the race snapshot.
server.parseSnapshot();
waitForFramePeriod(previousFrameTime, currentTime, 50);
previousFrameTime = currentTime;
}
}
/** /**
* Countdown timer until race starts. * Countdown timer until race starts.
*/ */

@ -2,6 +2,7 @@ package mock.model;
import mock.exceptions.SourceIDAllocationException; import mock.exceptions.SourceIDAllocationException;
import network.Messages.Enums.RaceStatusEnum;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -13,24 +14,18 @@ public class SourceIdAllocator {
/** /**
* This list contains all unallocated source IDs. * The race we are allocating for.
*/ */
List<Integer> unallocatedIDs = new ArrayList<>(); private MockRace mockRace;
/**
* This list contains all allocated source IDs.
*/
List<Integer> allocatedIDs = new ArrayList<>();
/** /**
* Creates a source ID allocator, using the given list of unallocated source IDs. * Creates a SourceIdAllocator for a given race.
* @param unallocatedIDs List of unallocated source IDs. * @param mockRace Race to allocate source IDs for.
*/ */
public SourceIdAllocator(List<Integer> unallocatedIDs) { public SourceIdAllocator(MockRace mockRace) {
//We need to copy the list. this.mockRace = mockRace;
this.unallocatedIDs.addAll(unallocatedIDs);
} }
@ -41,11 +36,23 @@ public class SourceIdAllocator {
*/ */
public synchronized int allocateSourceID() throws SourceIDAllocationException { public synchronized int allocateSourceID() throws SourceIDAllocationException {
if (mockRace.getRaceStatusEnum() != RaceStatusEnum.PRESTART) {
throw new SourceIDAllocationException("Could not allocate a source ID. Can only allocate during pre-start period. It is currently: " + mockRace.getRaceStatusEnum());
}
List<Integer> allocatedIDs = mockRace.getRaceDataSource().getParticipants();
List<Integer> allIDs = new ArrayList<>(mockRace.getBoatDataSource().getBoats().keySet());
//Get list of unallocated ids.
List<Integer> unallocatedIDs = new ArrayList<>(allIDs);
unallocatedIDs.removeAll(allocatedIDs);
if (!unallocatedIDs.isEmpty()) { if (!unallocatedIDs.isEmpty()) {
int sourceID = unallocatedIDs.remove(0); int sourceID = unallocatedIDs.remove(0);
allocatedIDs.add(sourceID); mockRace.generateMockBoat(sourceID);
return sourceID; return sourceID;
@ -61,10 +68,6 @@ public class SourceIdAllocator {
* @param sourceID Source ID to return. * @param sourceID Source ID to return.
*/ */
public void returnSourceID(Integer sourceID) { public void returnSourceID(Integer sourceID) {
mockRace.removeMockBoat(sourceID);
//We remove an Integer, not an int, so that we remove by value not by index.
allocatedIDs.remove(sourceID);
unallocatedIDs.add(sourceID);
} }
} }

@ -188,7 +188,20 @@ public abstract class RaceState {
* @return List of mark boats. * @return List of mark boats.
*/ */
public List<Mark> getMarks() { public List<Mark> getMarks() {
return new ArrayList<>(boatDataSource.getMarkerBoats().values()); //BoatDataSource contains a collection of Marks, and RaceDataSource contains a collection of Compound marks (which contain marks). RaceDataSource is the "definitive" source of mark data.
List<Mark> marks = new ArrayList<>(getCompoundMarks().size() * 2);
for (CompoundMark compoundMark : getCompoundMarks()) {
if (compoundMark.getMark1() != null) {
marks.add(compoundMark.getMark1());
}
if (compoundMark.getMark2() != null) {
marks.add(compoundMark.getMark2());
}
}
return marks;
} }
/** /**

Loading…
Cancel
Save