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;
//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();
boolean sentXMLs = false;
@ -82,16 +86,26 @@ public class MockOutput implements RunnableWithFramePeriod {
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.getRegattaXMLMessage());
}
if (lastSentBoatNumber != latestMessages.getBoatXMLMessage().getSequenceNumber()) {
lastSentBoatNumber = latestMessages.getBoatXMLMessage().getSequenceNumber();
outgoingMessages.put(latestMessages.getBoatXMLMessage());
}
sentXMLs = true;
if (lastSentRegattaNumber != latestMessages.getRegattaXMLMessage().getSequenceNumber()) {
lastSentRegattaNumber = latestMessages.getRegattaXMLMessage().getSequenceNumber();
outgoingMessages.put(latestMessages.getRegattaXMLMessage());
}
List<AC35Data> snapshot = latestMessages.getSnapshot();
for (AC35Data message : snapshot) {
outgoingMessages.put(message);

@ -43,7 +43,7 @@ public class MockRace extends RaceState {
/**
* 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;
/**
* 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.
@ -74,9 +80,10 @@ public class MockRace extends RaceState {
this.setRaceDataSource(raceDataSource);
this.setRegattaDataSource(regattaDataSource);
this.polars = polars;
this.scaleFactor = timeScale;
this.boats = this.generateMockBoats(boatDataSource.getBoats(), raceDataSource.getParticipants(), polars);
this.boats = new ArrayList<>();
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.
* @param boats The map of Boats describing boats that are potentially in the race. Maps boat sourceID to boat.
* @param sourceIDs The list of boat sourceIDs describing which specific boats are actually participating.
* @param polars The polars table to be used for boat simulation.
* @return A list of MockBoats that are participating in the race.
* Generates a MockBoat from the BoatDataSource, given a source ID. Also adds it to the participant list.
* @param sourceID The source ID to assign the boat.
* @return A MockBoat that is now participating in the race.
*/
private List<MockBoat> generateMockBoats(Map<Integer, Boat> boats, List<Integer> sourceIDs, Polars polars) {
List<MockBoat> mockBoats = new ArrayList<>(sourceIDs.size());
//For each sourceID participating...
for (int sourceID : sourceIDs) {
public void generateMockBoat(Integer sourceID) {
//Get the boat associated with the sourceID.
Boat boat = boats.get(sourceID);
Boat boat = getBoatDataSource().getBoats().get(sourceID);
//Construct a MockBoat using the Boat and Polars.
MockBoat mockBoat = new MockBoat(boat, polars);
mockBoat.setCurrentLeg(this.getLegs().get(0));
mockBoats.add(mockBoat);
//Update participant list.
getRaceDataSource().getParticipants().add(sourceID);
}
this.boats.add(mockBoat);
return mockBoats;
getRaceDataSource().incrementSequenceNumber();
}
/**
* 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
public void run() {
prestartCountdown();
race.initialiseBoats();
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.
*/

@ -2,6 +2,7 @@ package mock.model;
import mock.exceptions.SourceIDAllocationException;
import network.Messages.Enums.RaceStatusEnum;
import java.util.ArrayList;
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.
* @param unallocatedIDs List of unallocated source IDs.
* Creates a SourceIdAllocator for a given race.
* @param mockRace Race to allocate source IDs for.
*/
public SourceIdAllocator(List<Integer> unallocatedIDs) {
//We need to copy the list.
this.unallocatedIDs.addAll(unallocatedIDs);
public SourceIdAllocator(MockRace mockRace) {
this.mockRace = mockRace;
}
@ -41,11 +36,23 @@ public class SourceIdAllocator {
*/
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()) {
int sourceID = unallocatedIDs.remove(0);
allocatedIDs.add(sourceID);
mockRace.generateMockBoat(sourceID);
return sourceID;
@ -61,10 +68,6 @@ public class SourceIdAllocator {
* @param sourceID Source ID to return.
*/
public void returnSourceID(Integer sourceID) {
//We remove an Integer, not an int, so that we remove by value not by index.
allocatedIDs.remove(sourceID);
unallocatedIDs.add(sourceID);
mockRace.removeMockBoat(sourceID);
}
}

@ -188,7 +188,20 @@ public abstract class RaceState {
* @return List of mark boats.
*/
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