fixed issue with multiple boat classes per event; added test case for that

This commit is contained in:
Axel Uhl committed 2011-06-17 23:47:05 +02:00
1 parent ce3f8fc54d
commit ca128d74ce
6 files changed
+128 -15

No files matched your search

@@ -24,8 +24,12 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.TrackedEvent;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindStore;
import com.sap.sailing.domain.tracking.WindTrack;
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl;
import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver;
import com.tractrac.clientmodule.Competitor;
import com.tractrac.clientmodule.CompetitorClass;
import com.tractrac.clientmodule.ControlPoint;
@@ -70,9 +74,34 @@ public interface DomainFactory {
/**
* Creates an {@link com.sap.sailing.domain.base.Event event} from a
* TracTrac event description. It doesn't have {@link RaceDefinition}s yet.
* A new {@link com.sap.sailing.domain.base.Event} is created if no event by
* an equal name with a boat class with an equal name as the <code>event</code>'s
* boat class exists yet.
*/
com.sap.sailing.domain.base.Event createEvent(Event event);
/**
* Creates a race tracked for the specified URL/URIs and starts receiving all available existing and future push
* data from there. Receiving continues until {@link RaceTracker#stop()} is called.
* <p>
*
* A race tracker uses the <code>paramURL</code> for the TracTrac Java client to register for push data about one
* race. The {@link RaceDefinition} for that race, however, isn't created until the {@link Course} has been
* received. Therefore, the {@link RaceCourseReceiver} will create the {@link RaceDefinition} and will add it to the
* {@link com.sap.sailing.domain.base.Event}.
* <p>
*
* The link to the {@link RaceDefinition} is created in the {@link DomainFactory} when the
* {@link RaceCourseReceiver} creates the {@link TrackedRace} object. Starting then, the {@link DomainFactory} will
* respond with the {@link RaceDefinition} when its {@link DomainFactory#getRace(Event)} is called with the TracTrac
* {@link Event} as argument that is used for its tracking.
* <p>
*
* @param windStore
* Provides the capability to obtain the {@link WindTrack}s for the different wind sources. A trivial
* implementation is {@link EmptyWindStore} which simply provides new, empty tracks. This is always
* available but loses track of the wind, e.g., during server restarts.
*/
RaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, WindStore windStore) throws MalformedURLException,
FileNotFoundException, URISyntaxException;
@@ -61,6 +61,7 @@ import com.sap.sailing.domain.tractracadapter.JSONService;
import com.sap.sailing.domain.tractracadapter.RaceTracker;
import com.sap.sailing.domain.tractracadapter.Receiver;
import com.sap.sailing.domain.tractracadapter.ReceiverType;
import com.sap.sailing.util.Util.Pair;
import com.tractrac.clientmodule.CompetitorClass;
import com.tractrac.clientmodule.ControlPoint;
import com.tractrac.clientmodule.Race;
@@ -99,10 +100,10 @@ public class DomainFactoryImpl implements DomainFactory {
private final Map<CompetitorClass, BoatClass> classCache = new HashMap<CompetitorClass, BoatClass>();
/**
* Caches events by their name
* Caches events by their name and their boat class's name
*/
private final Map<String, com.sap.sailing.domain.base.Event> eventCache =
new HashMap<String, com.sap.sailing.domain.base.Event>();
private final Map<Pair<String, String>, com.sap.sailing.domain.base.Event> eventCache =
new HashMap<Pair<String, String>, com.sap.sailing.domain.base.Event>();
private final Map<com.tractrac.clientmodule.Event, RaceDefinition> tractracEventToRaceDefinitionMap = new HashMap<com.tractrac.clientmodule.Event, RaceDefinition>();
@@ -292,10 +293,26 @@ public class DomainFactoryImpl implements DomainFactory {
@Override
public Event createEvent(com.tractrac.clientmodule.Event event) {
synchronized (eventCache) {
Event result = eventCache.get(event.getName());
// FIXME Dialog with Lasse by Skype on 2011-06-17:
// [6:20:04 PM] Axel Uhl: Lasse, can Event.getCompetitorClassList() ever produce more than one result?
// [6:20:20 PM] Axel Uhl: Or is it similar to Event.getRaceList() which always delivers one Race?
// [6:22:19 PM] Lasse Staffensen: It can deliver several classes, if more classes are present in a race.
// [6:27:20 PM] Axel Uhl: Will that happen at Kiel Week?
// [6:27:58 PM] Lasse Staffensen: No
// [6:28:34 PM] Axel Uhl: Good :)
// This means that currently it is permissible to assume that we'll get at most one
// boat class per TracTrac event. Generally, however, we have to assume that
// one TracTrac event may map to multiple domain Event objects with one BoatClass each
Collection<CompetitorClass> competitorClassList = event.getCompetitorClassList();
BoatClass boatClass = null;
if (competitorClassList != null && !competitorClassList.isEmpty()) {
boatClass = getBoatClass(competitorClassList.iterator().next());
}
Pair<String, String> key = new Pair<String, String>(event.getName(), boatClass==null?null:boatClass.getName());
Event result = eventCache.get(key);
if (result == null) {
result = new EventImpl(event.getName());
eventCache.put(event.getName(), result);
result = new EventImpl(event.getName(), boatClass);
eventCache.put(key, result);
}
return result;
}
@@ -47,6 +47,12 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue<ControlPoint
super(domainFactory);
this.tractracEvent = tractracEvent;
// assumption: there is currently only one race per TracTrac Event object
if (tractracEvent.getRaceList().isEmpty()) {
throw new IllegalArgumentException("Can't receive mark positions from event "+tractracEvent.getName()+" that has no race");
}
if (tractracEvent.getRaceList().size() > 1) {
logger.warning("Received event "+tractracEvent.getName()+" that has more than one race ("+tractracEvent.getRaceList().size()+")");
}
final Race race = tractracEvent.getRaceList().iterator().next();
new Thread("MarkPositionReceiver waiting for RaceDefinition for "+race.getName()) {
public void run() {