diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java index 1f07eeeb332..bf2a28428b4 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/MultipleClassesInEventTest.java @@ -49,25 +49,25 @@ public class MultipleClassesInEventTest { new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=cce678c8-97e6-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); kiwotest2 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=11290bd6-97e7-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); kiwotest3 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=39635b24-97e7-11e0-9aed-406186cbf87c"), new URI(liveURI), new URI(storedURI), - EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); weym470may112014_2 = domainFactory .createRaceTracker( new URL( httpAndHost+"/events/event_20110505_SailingTea/clientparams.php?event=event_20110505_SailingTea&race=04498426-7dfd-11e0-8236-406186cbf87c"), new URI(liveURI), new URI(storedURI), - EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); assertEquals("STG", kiwotest1.getEvent().getBoatClass().getName()); assertEquals("505", kiwotest2.getEvent().getBoatClass().getName()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java index 677cebeb860..60cf9d4b98f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java @@ -90,7 +90,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest { setStoredDataLoaded(false); ArrayList receivers = new ArrayList(); for (Receiver r : domainFactory.getUpdateReceivers(trackedEvent, getEvent(), EmptyWindStore.INSTANCE, - new DynamicRaceDefinitionSet() { + /* startOfTracking */ null, /* endOfTracking */ null, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java index a8eec2d351d..12d36808624 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveMarkPassingDataTest.java @@ -94,11 +94,11 @@ public class ReceiveMarkPassingDataTest extends AbstractTracTracLiveTest { receivers.add(receiver); for (Receiver r : DomainFactory.INSTANCE.getUpdateReceivers( new DynamicTrackedEventImpl(DomainFactory.INSTANCE.getOrCreateEvent(getEvent())), - getEvent(), EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { + getEvent(), EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, + new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) {} - }, ReceiverType.RACECOURSE, - ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) { + }, ReceiverType.RACECOURSE, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS)) { receivers.add(r); } addListenersForStoredDataAndStartController(receivers); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java index 1ac525d3ac8..0caff97a8af 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java @@ -76,8 +76,8 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { public void raceRemoved(TrackedRace trackedRace) { } }); - for (Receiver receiver : domainFactory.getUpdateReceivers(trackedEvent, getEvent(), EmptyWindStore.INSTANCE, - new DynamicRaceDefinitionSet() { + for (Receiver receiver : domainFactory.getUpdateReceivers(trackedEvent, getEvent(), /* start of tracking */ null, + /* end of tracking */ null, EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } @@ -87,7 +87,7 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { } } addListenersForStoredDataAndStartController(domainFactory.getUpdateReceivers(trackedEvent, getEvent(), - EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { + /* start of tracking */ null, /* end of tracking */ null, EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java index 94df1cf5b24..0cbe8182f01 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/UnicodeCharactersInCompetitorNamesTest.java @@ -45,7 +45,7 @@ public class UnicodeCharactersInCompetitorNamesTest { "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110609_KielerWoch/clientparams.php?event=event_20110609_KielerWoch&race=5b08a9ee-9933-11e0-85be-406186cbf87c"), tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_LIVE) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_LIVE), tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED), - EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); + /* startOfTracking */ null, /* endOfTracking */ null, EmptyWindStore.INSTANCE, new DummyTrackedEventRegistry()); Iterable competitors = fourtyninerYellow_2.getRacesHandle().getRaces().iterator().next().getCompetitors(); for (Competitor competitor : competitors) { diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index 4eb88745e0b..271fbd63102 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -100,17 +100,26 @@ public interface DomainFactory { * * 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#getRaces(Event)} is called with the TracTrac - * {@link Event} as argument that is used for its tracking. + * respond with the {@link RaceDefinition} when its {@link DomainFactory#getRaces(Event)} is called with the + * TracTrac {@link Event} as argument that is used for its tracking. *

+ * + * @param startOfTracking + * if null, all stored data from the "beginning of time" will be loaded that the event has + * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this start time. + * @param endOfTracking + * if null, all stored data until the "end of time" will be loaded that the event has + * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this end time. * @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. - * @param trackedEventRegistry TODO */ - TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, TrackedEventRegistry trackedEventRegistry) throws MalformedURLException, - FileNotFoundException, URISyntaxException; + TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking, + TimePoint endOfTracking, WindStore windStore, TrackedEventRegistry trackedEventRegistry) + throws MalformedURLException, FileNotFoundException, URISyntaxException; BoatClass getOrCreateBoatClass(CompetitorClass competitorClass); @@ -125,12 +134,20 @@ public interface DomainFactory { * must have been created before through * {@link #getOrCreateTrackedEvent(com.sap.sailing.domain.base.Event)} because otherwise the link to the * {@link Event} can't be established + * @param startOfTracking + * if null, all stored data from the "beginning of time" will be loaded that the event has + * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this start time. + * @param endOfTracking + * if null, all stored data until the "end of time" will be loaded that the event has to + * provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this end time. * @param tokenToRetrieveAssociatedRace * used to update the set of{@link RaceDefinition}s received by the * {@link RaceCourseReceiver} created by this call */ - Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, Event tractracEvent, WindStore windStore, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate); + Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, Event tractracEvent, TimePoint startOfTracking, + TimePoint endOfTracking, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate); /** * Creates a {@link RaceDefinition} from a TracTrac {@link Race} and a domain {@link Course} definition. The @@ -165,7 +182,7 @@ public interface DomainFactory { MarkPassing createMarkPassing(TimePoint timePoint, Waypoint passed, com.sap.sailing.domain.base.Competitor competitor); Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, Event tractracEvent, WindStore windStore, - DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types); + TimePoint startOfTracking, TimePoint endOfTracking, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types); DynamicTrackedRace trackRace(DynamicTrackedEvent trackedEvent, RaceDefinition raceDefinition, WindStore windStore, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 28671d108b7..0e5ef96b4a4 100644 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -269,8 +269,9 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, com.tractrac.clientmodule.Event tractracEvent, - WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types) { + public Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, + com.tractrac.clientmodule.Event tractracEvent, WindStore windStore, TimePoint startOfTracking, + TimePoint endOfTracking, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types) { Collection result = new ArrayList(); for (ReceiverType type : types) { switch (type) { @@ -281,7 +282,7 @@ public class DomainFactoryImpl implements DomainFactory { break; case MARKPOSITIONS: result.add(new MarkPositionReceiver( - trackedEvent, tractracEvent, this)); + trackedEvent, tractracEvent, startOfTracking, endOfTracking, this)); break; case RAWPOSITIONS: result.add(new RawPositionReceiver( @@ -302,10 +303,10 @@ public class DomainFactoryImpl implements DomainFactory { @Override public Iterable getUpdateReceivers(DynamicTrackedEvent trackedEvent, - com.tractrac.clientmodule.Event tractracEvent, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { - return getUpdateReceivers(trackedEvent, tractracEvent, windStore, raceDefinitionSetToUpdate, ReceiverType.RACECOURSE, - ReceiverType.MARKPASSINGS, ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, - ReceiverType.RAWPOSITIONS); + com.tractrac.clientmodule.Event tractracEvent, TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) { + return getUpdateReceivers(trackedEvent, tractracEvent, windStore, startOfTracking, endOfTracking, + raceDefinitionSetToUpdate, ReceiverType.RACECOURSE, ReceiverType.MARKPASSINGS, + ReceiverType.MARKPOSITIONS, ReceiverType.RACESTARTFINISH, ReceiverType.RAWPOSITIONS); } @Override @@ -450,10 +451,11 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, - TrackedEventRegistry trackedEventRegistry) throws MalformedURLException, FileNotFoundException, - URISyntaxException { - return new TracTracRaceTrackerImpl(this, paramURL, liveURI, storedURI, windStore, trackedEventRegistry); + public TracTracRaceTracker createRaceTracker(URL paramURL, URI liveURI, URI storedURI, TimePoint startOfTracking, + TimePoint endOfTracking, WindStore windStore, TrackedEventRegistry trackedEventRegistry) + throws MalformedURLException, FileNotFoundException, URISyntaxException { + return new TracTracRaceTrackerImpl(this, paramURL, liveURI, storedURI, startOfTracking, endOfTracking, + windStore, trackedEventRegistry); } @Override diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java index b59a3cc5167..32939b9dbb7 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MarkPositionReceiver.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.base.Buoy; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; import com.sap.sailing.domain.tracking.DynamicTrackedEvent; @@ -42,9 +43,36 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueuenull, all stored data from the "beginning of time" will be loaded that the event has to provide, + * particularly for the mark positions which are stored per event, not per race; otherwise, particularly the mark + * position loading will be constrained to this start time. + */ + private final TimePoint startOfTracking; + + /** + * if null, all stored data until the "end of time" will be loaded that the event has to provide, + * particularly for the mark positions which are stored per event, not per race; otherwise, particularly the mark + * position loading will be constrained to this end time. + */ + private final TimePoint endOfTracking; + + /** + * @param startOfTracking + * if null, all stored data from the "beginning of time" will be loaded that the event has + * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this start time. + * @param endOfTracking + * if null, all stored data until the "end of time" will be loaded that the event has to + * provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this end time. + */ + public MarkPositionReceiver(final DynamicTrackedEvent trackedEvent, com.tractrac.clientmodule.Event tractracEvent, + TimePoint startOfTracking, TimePoint endOfTracking, final DomainFactory domainFactory) { super(domainFactory, tractracEvent, trackedEvent); + this.startOfTracking = startOfTracking; + this.endOfTracking = endOfTracking; // 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"); @@ -66,7 +94,8 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue(controlPoint, record, isLiveData)); } - }, /* fromTime */0l, /* toTime */Long.MAX_VALUE); + }, /* fromTime */ startOfTracking == null ? 0l : startOfTracking.asMillis(), + /* toTime */ endOfTracking == null ? Long.MAX_VALUE : endOfTracking.asMillis()); result.add(controlPointListener); setAndStartThread(new Thread(this, getClass().getName())); return result; diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index 09cb9ae7b42..60409483e1f 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.Buoy; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; +import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.tracking.AbstractRaceTrackerImpl; @@ -75,26 +76,37 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements *

* * A race tracker uses the paramURL for the TracTrac Java client to register for push data about one - * race. The {@link DomainFactory} is asked to retrieve an existing or create a new {@link com.sap.sailing.domain.base.Event} - * based on the TracTrac event. The {@link RaceDefinition} for the 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}. + * race. The {@link DomainFactory} is asked to retrieve an existing or create a new + * {@link com.sap.sailing.domain.base.Event} based on the TracTrac event. The {@link RaceDefinition} for the 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}. *

* * 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#getRaces(Event)} is called with the TracTrac - * {@link Event} as argument that is used for its tracking. + * respond with the {@link RaceDefinition} when its {@link DomainFactory#getRaces(Event)} is called with the + * TracTrac {@link Event} as argument that is used for its tracking. *

+ * + * @param startOfTracking + * if null, all stored data from the "beginning of time" will be loaded that the event has + * to provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this start time. + * @param endOfTracking + * if null, all stored data until the "end of time" will be loaded that the event has to + * provide, particularly for the mark positions which are stored per event, not per race; otherwise, + * particularly the mark position loading will be constrained to this end time. * @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. - * @param trackedEventRegistry used to create the {@link TrackedEvent} for the domain event + * @param trackedEventRegistry + * used to create the {@link TrackedEvent} for the domain event */ protected TracTracRaceTrackerImpl(DomainFactory domainFactory, URL paramURL, URI liveURI, URI storedURI, - WindStore windStore, TrackedEventRegistry trackedEventRegistry) throws URISyntaxException, - MalformedURLException, FileNotFoundException { + TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore, + TrackedEventRegistry trackedEventRegistry) throws URISyntaxException, MalformedURLException, + FileNotFoundException { super(); urls = new Triple(paramURL, liveURI, storedURI); this.races = new HashSet(); @@ -123,7 +135,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements setTrackedEvent(trackedEventRegistry.getOrCreateTrackedEvent(domainEvent)); receivers = new HashSet(); Set typeControllers = new HashSet(); - for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedEvent(), tractracEvent, windStore, this)) { + for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedEvent(), tractracEvent, startOfTracking, + endOfTracking, windStore, this)) { receivers.add(receiver); for (TypeController typeController : receiver.getTypeControllersAndStart()) { typeControllers.add(typeController); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 53eaac92452..da64b95ad1e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -315,5 +315,12 @@ public interface TrackedRace { Distance getWindwardDistanceToOverallLeader(Competitor competitor, TimePoint timePoint) throws NoWindException; - WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, Iterable windSourcesToExclude); + /** + * Loops over this tracked race's wind sources and from each asks its averaged wind for the position p + * and time point at, using the particular wind source's averaging interval. The confidences delivered + * by each wind source are used during computing the averaged result across the wind sources. The result has the averaged + * confidence attached. + */ + WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, + Iterable windSourcesToExclude); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CombinedWindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CombinedWindTrackImpl.java index f599ce4b983..58bc5ed4915 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CombinedWindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CombinedWindTrackImpl.java @@ -1,14 +1,12 @@ package com.sap.sailing.domain.tracking.impl; -import java.util.NavigableSet; - import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.Wind; +import com.sap.sailing.domain.tracking.impl.TrackBasedEstimationWindTrackImpl.EstimatedWindFixesAsNavigableSet; /** * A wind track that delivers the result of * {@link TrackedRace#getWind(com.sap.sailing.domain.common.Position, com.sap.sailing.domain.common.TimePoint)}, - * using a {@link CombinedWindAsNavigableSet} as its internal raw fixes collection. + * using a {@link CombinedWindAsNavigableSet} as its internal raw fixes collection. Resolution of raw fixes is set to 10s. * * @author Axel Uhl (d043530) * @@ -16,13 +14,25 @@ import com.sap.sailing.domain.tracking.Wind; public class CombinedWindTrackImpl extends VirtualWindTrackImpl { private CombinedWindAsNavigableSet virtualInternalRawFixes; - public CombinedWindTrackImpl(TrackedRace trackedRace, long millisecondsOverWhichToAverage) { - super(trackedRace, millisecondsOverWhichToAverage); - virtualInternalRawFixes = new CombinedWindAsNavigableSet(this, trackedRace, /* resolutionInMilliseconds */ 1000l); + public CombinedWindTrackImpl(TrackedRace trackedRace) { + super(trackedRace, /* millisecondsOverWhichToAverage not used, see overridden method */ -1); + virtualInternalRawFixes = new CombinedWindAsNavigableSet(this, trackedRace, /* resolutionInMilliseconds */ 10000l); } @Override - protected NavigableSet getInternalRawFixes() { + protected CombinedWindAsNavigableSet getInternalRawFixes() { return virtualInternalRawFixes; } + + /** + * The combined wind source already averages the wind from each wind source considered. There is no use in again + * averaging over a longer period of time. Therefore, we set the averaging interval to two times the resolution of + * the {@link EstimatedWindFixesAsNavigableSet virtual fixes collection} plus two milliseconds, so that at most one + * fix before and one fix after the time point requested will be used. + */ + @Override + public long getMillisecondsOverWhichToAverageWind() { + return 2*getInternalRawFixes().getResolutionInMilliseconds()+2; + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index 4f316885cb5..3336ec589b4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -134,9 +134,9 @@ public class GPSFixTrackImpl extends TrackImpl } private Pair getFixesForPositionEstimation(TimePoint timePoint, boolean inclusive) { - FixType lastFix = inclusive ? getLastFixAtOrBefore(timePoint) : getLastFixBefore(timePoint); - FixType firstFix = inclusive ? getFirstFixAtOrAfter(timePoint) : getFirstFixAfter(timePoint); - return new Pair(lastFix, firstFix); + FixType lastFixBefore = inclusive ? getLastFixAtOrBefore(timePoint) : getLastFixBefore(timePoint); + FixType firstFixAfter = inclusive ? getFirstFixAtOrAfter(timePoint) : getFirstFixAfter(timePoint); + return new Pair(lastFixBefore, firstFixAfter); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index d311813d7f2..54dc30d79ad 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -523,7 +523,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { public WindTrack getOrCreateWindTrack(WindSource windSource) { WindTrack result; if (windSource.getType() == WindSourceType.COMBINED) { - result = new CombinedWindTrackImpl(this, getMillisecondsOverWhichToAverageWind()); + result = new CombinedWindTrackImpl(this); } else { synchronized (windTracks) { result = windTracks.get(windSource); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/VirtualWindFixesAsNavigableSet.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/VirtualWindFixesAsNavigableSet.java index d16ab52ab0b..b97eea5b48b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/VirtualWindFixesAsNavigableSet.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/VirtualWindFixesAsNavigableSet.java @@ -77,13 +77,13 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl final TimePoint timePointOfLastEvent = trackedRace.getTimePointOfLastEvent(); if (timePointOfLastEvent == null) { // nothing received yet; "lowering" to end of time - result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / resolutionInMilliseconds - * resolutionInMilliseconds); + result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / getResolutionInMilliseconds() + * getResolutionInMilliseconds()); } else if (w.getTimePoint().compareTo(timePointOfLastEvent) > 0) { result = lowerToResolution(new DummyWind(timePointOfLastEvent)); } else { - result = new MillisecondsTimePoint((w.getTimePoint().asMillis() - 1) / resolutionInMilliseconds - * resolutionInMilliseconds); + result = new MillisecondsTimePoint((w.getTimePoint().asMillis() - 1) / getResolutionInMilliseconds() + * getResolutionInMilliseconds()); } return result; } @@ -93,13 +93,13 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl final TimePoint timePointOfLastEvent = trackedRace.getTimePointOfLastEvent(); if (timePointOfLastEvent == null) { // nothing received yet; "lowering" to end of time - result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / resolutionInMilliseconds - * resolutionInMilliseconds); + result = new MillisecondsTimePoint((Long.MAX_VALUE - 1) / getResolutionInMilliseconds() + * getResolutionInMilliseconds()); } else if (w.getTimePoint().compareTo(timePointOfLastEvent) > 0) { result = floorToResolution(new DummyWind(timePointOfLastEvent)); } else { - result = new MillisecondsTimePoint(w.getTimePoint().asMillis() / resolutionInMilliseconds - * resolutionInMilliseconds); + result = new MillisecondsTimePoint(w.getTimePoint().asMillis() / getResolutionInMilliseconds() + * getResolutionInMilliseconds()); } return result; } @@ -113,8 +113,8 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl } else if (w.getTimePoint().compareTo(startOfTracking) < 0) { result = ceilingToResolution(new DummyWind(startOfTracking)); } else { - result = new MillisecondsTimePoint(((w.getTimePoint().asMillis() - 1) / resolutionInMilliseconds + 1) - * resolutionInMilliseconds); + result = new MillisecondsTimePoint(((w.getTimePoint().asMillis() - 1) / getResolutionInMilliseconds() + 1) + * getResolutionInMilliseconds()); } return result; } @@ -128,8 +128,8 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl } else if (w.getTimePoint().compareTo(startOfTracking) < 0) { result = higherToResolution(new DummyWind(startOfTracking)); } else { - result = new MillisecondsTimePoint((w.getTimePoint().asMillis() / resolutionInMilliseconds + 1) - * resolutionInMilliseconds); + result = new MillisecondsTimePoint((w.getTimePoint().asMillis() / getResolutionInMilliseconds() + 1) + * getResolutionInMilliseconds()); } return result; } @@ -200,7 +200,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl @Override public Wind next() { Wind result = floor(new DummyWind(timePoint)); - timePoint = new MillisecondsTimePoint(timePoint.asMillis() + resolutionInMilliseconds); + timePoint = new MillisecondsTimePoint(timePoint.asMillis() + getResolutionInMilliseconds()); return result; } @@ -229,7 +229,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl @Override public Wind next() { Wind result = floor(new DummyWind(timePoint)); - timePoint = new MillisecondsTimePoint(timePoint.asMillis() - resolutionInMilliseconds); + timePoint = new MillisecondsTimePoint(timePoint.asMillis() - getResolutionInMilliseconds()); return result; } @@ -297,7 +297,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl @Override public int size() { - return (int) ((getTo().asMillis() - getFrom().asMillis()) / resolutionInMilliseconds); + return (int) ((getTo().asMillis() - getFrom().asMillis()) / getResolutionInMilliseconds()); } @Override @@ -305,7 +305,7 @@ public abstract class VirtualWindFixesAsNavigableSet extends AbstractUnmodifiabl boolean result = false; if (o instanceof Wind) { Wind wind = (Wind) o; - result = wind.getTimePoint().asMillis() % resolutionInMilliseconds == 0 + result = wind.getTimePoint().asMillis() % getResolutionInMilliseconds() == 0 && wind.getTimePoint().compareTo(getFrom()) >= 0 && wind.getTimePoint().compareTo(getTo()) < 0; } return result; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index d9bc29bdc87..6a373a54546 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -73,6 +73,7 @@ import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.Util.Triple; +import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard.Entry; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; @@ -443,6 +444,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS storedURI = rr.storedURI; } final RacesHandle raceHandle = getService().addTracTracRace(new URL(rr.paramURL), new URI(liveURI), new URI(storedURI), + new MillisecondsTimePoint(rr.trackingStartTime), new MillisecondsTimePoint(rr.trackingEndTime), MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory), TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS); if (trackWind) { new Thread("Wind tracking starter for race "+rr.eventName+"/"+rr.name) { @@ -550,7 +552,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS } else { Util.addAll(trackedRace.getWindSources(), windSourcesToDeliver); // TODO bug #375: add the combined wind; currently, CombinedWindTrackImpl just takes too long to return results... - // windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED)); + windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED)); } for (WindSource windSource : windSourcesToDeliver) { WindTrackInfoDTO windTrackInfoDTO = new WindTrackInfoDTO(); @@ -612,7 +614,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS List windSourcesToDeliver = new ArrayList(); Util.addAll(trackedRace.getWindSources(), windSourcesToDeliver); // TODO bug #375: add the combined wind; currently, CombinedWindTrackImpl just takes too long to return results... - // windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED)); + windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED)); for (WindSource windSource : windSourcesToDeliver) { if (windSourceTypeNames == null || windSourceTypeNames.contains(windSource.getType().name())) { TimePoint fromTimePoint = new MillisecondsTimePoint(from); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/components/CompositeSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/components/CompositeSettingsDialogComponent.java index 09243c3b785..9c17ea70d7b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/components/CompositeSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/components/CompositeSettingsDialogComponent.java @@ -32,13 +32,17 @@ public class CompositeSettingsDialogComponent implements SettingsDialogComponent @Override public Validator getValidator() { - // TODO Auto-generated method stub - return null; + return new CompositeValidator(components); } @Override public FocusWidget getFocusWidget() { - // TODO Auto-generated method stub + for (Component component : components) { + FocusWidget fw = component.getSettingsDialogComponent().getFocusWidget(); + if (fw != null) { + return fw; + } + } return null; } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java index ef56ce4b8a3..197bc960499 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingWindTracksTest.java @@ -73,7 +73,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive Event domainEvent = domainFactory.getOrCreateEvent(getEvent()); DynamicTrackedEvent trackedEvent = new RacingEventServiceImpl().getOrCreateTrackedEvent(domainEvent); Iterable typeControllers = domainFactory.getUpdateReceivers(trackedEvent, getEvent(), - EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() { + EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, new DynamicRaceDefinitionSet() { @Override public void addRaceDefinition(RaceDefinition race) { } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java index 01825af4792..807cfeeb583 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java @@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.common.EventIdentifier; import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -113,6 +114,15 @@ public interface RacingEventService extends TrackedEventRegistry { RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, long timeoutInMilliseconds) throws MalformedURLException, FileNotFoundException, URISyntaxException; + /** + * Same as {@link #addTracTracRace(URL, URI, URI, WindStore, long)}, only that start and end of tracking are + * specified which may help reducing the amount of stored data (particularly mark positions) that needs to be + * loaded. + */ + RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, TimePoint trackingStartTime, + TimePoint trackingEndTime, WindStore windStore, long timeoutForReceivingRaceDefinitionInMilliseconds) + throws MalformedURLException, FileNotFoundException, URISyntaxException; + /** * Stops tracking all races of the event specified. This will also stop tracking wind for all races of this event. * See {@link #stopTrackingWind(Event, RaceDefinition)}. If there were multiple calls to diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index dacf2dc0edd..35768804ee4 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -379,10 +379,18 @@ public class RacingEventServiceImpl implements RacingEventService, EventFetcher, @Override public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, WindStore windStore, long timeoutInMilliseconds) throws MalformedURLException, FileNotFoundException, URISyntaxException { + return addTracTracRace(paramURL, liveURI, storedURI, /* startOfTracking */ null, + /* endOfTracking */ null, windStore, timeoutInMilliseconds); + } + + @Override + public synchronized RacesHandle addTracTracRace(URL paramURL, URI liveURI, URI storedURI, + TimePoint startOfTracking, TimePoint endOfTracking, WindStore windStore, + long timeoutInMilliseconds) throws MalformedURLException, FileNotFoundException, URISyntaxException { Triple key = new Triple(paramURL, liveURI, storedURI); RaceTracker tracker = raceTrackersByID.get(key); if (tracker == null) { - tracker = getDomainFactory().createRaceTracker(paramURL, liveURI, storedURI, windStore, this); + tracker = getDomainFactory().createRaceTracker(paramURL, liveURI, storedURI, startOfTracking, endOfTracking, windStore, this); raceTrackersByID.put(tracker.getID(), tracker); Set trackers = raceTrackersByEvent.get(tracker.getEvent()); if (trackers == null) {