increased resolution for raw COMBINED fixes to 10s; constrain MarkPosition loading to tracked time

This commit is contained in:
Axel Uhl committed 2012-03-09 00:04:50 +01:00
1 parent 4898fc7194
commit 8fd3667793
19 files changed
+182 -80

No files matched your search

@@ -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());
@@ -90,7 +90,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
setStoredDataLoaded(false);
ArrayList<Receiver> receivers = new ArrayList<Receiver>();
for (Receiver r : domainFactory.getUpdateReceivers(trackedEvent, getEvent(), EmptyWindStore.INSTANCE,
new DynamicRaceDefinitionSet() {
/* startOfTracking */ null, /* endOfTracking */ null, new DynamicRaceDefinitionSet() {
@Override
public void addRaceDefinition(RaceDefinition race) {
}
@@ -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);
@@ -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) {
}
@@ -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<Competitor> competitors = fourtyninerYellow_2.getRacesHandle().getRaces().iterator().next().getCompetitors();
for (Competitor competitor : competitors) {
@@ -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.
* <p>
*
* @param startOfTracking
* if <code>null</code>, 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 <code>null</code>, 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 <code>null</code>, 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 <code>null</code>, 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<Receiver> getUpdateReceivers(DynamicTrackedEvent trackedEvent, Event tractracEvent, WindStore windStore,
DynamicRaceDefinitionSet raceDefinitionSetToUpdate);
Iterable<Receiver> 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<Receiver> 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,
@@ -269,8 +269,9 @@ public class DomainFactoryImpl implements DomainFactory {
}
@Override
public Iterable<Receiver> getUpdateReceivers(DynamicTrackedEvent trackedEvent, com.tractrac.clientmodule.Event tractracEvent,
WindStore windStore, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types) {
public Iterable<Receiver> getUpdateReceivers(DynamicTrackedEvent trackedEvent,
com.tractrac.clientmodule.Event tractracEvent, WindStore windStore, TimePoint startOfTracking,
TimePoint endOfTracking, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, ReceiverType... types) {
Collection<Receiver> result = new ArrayList<Receiver>();
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<Receiver> 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
@@ -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 AbstractReceiverWithQueue<ControlPoint
private static final Logger logger = Logger.getLogger(MarkPositionReceiver.class.getName());
private int received;
public MarkPositionReceiver(final DynamicTrackedEvent trackedEvent, com.tractrac.clientmodule.Event tractracEvent, final DomainFactory domainFactory) {
/**
* if <code>null</code>, 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 <code>null</code>, 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 <code>null</code>, 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 <code>null</code>, 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
public void gotData(ControlPoint controlPoint, ControlPointPositionData record, boolean isLiveData) {
enqueue(new Triple<ControlPoint, ControlPointPositionData, Boolean>(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;
@@ -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
* <p>
*
* A race tracker uses the <code>paramURL</code> 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}.
* <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#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.
* <p>
*
* @param startOfTracking
* if <code>null</code>, 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 <code>null</code>, 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<URL, URI, URI>(paramURL, liveURI, storedURI);
this.races = new HashSet<RaceDefinition>();
@@ -123,7 +135,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
setTrackedEvent(trackedEventRegistry.getOrCreateTrackedEvent(domainEvent));
receivers = new HashSet<Receiver>();
Set<TypeController> typeControllers = new HashSet<TypeController>();
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);
@@ -315,5 +315,12 @@ public interface TrackedRace {
Distance getWindwardDistanceToOverallLeader(Competitor competitor, TimePoint timePoint) throws NoWindException;
WindWithConfidence<Pair<Position, TimePoint>> getWindWithConfidence(Position p, TimePoint at, Iterable<WindSource> windSourcesToExclude);
/**
* Loops over this tracked race's wind sources and from each asks its averaged wind for the position <code>p</code>
* and time point <code>at</code>, 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<Pair<Position, TimePoint>> getWindWithConfidence(Position p, TimePoint at,
Iterable<WindSource> windSourcesToExclude);
}
@@ -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<Wind> 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;
}
}
@@ -134,9 +134,9 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
}
private Pair<FixType, FixType> getFixesForPositionEstimation(TimePoint timePoint, boolean inclusive) {
FixType lastFix = inclusive ? getLastFixAtOrBefore(timePoint) : getLastFixBefore(timePoint);
FixType firstFix = inclusive ? getFirstFixAtOrAfter(timePoint) : getFirstFixAfter(timePoint);
return new Pair<FixType, FixType>(lastFix, firstFix);
FixType lastFixBefore = inclusive ? getLastFixAtOrBefore(timePoint) : getLastFixBefore(timePoint);
FixType firstFixAfter = inclusive ? getFirstFixAtOrAfter(timePoint) : getFirstFixAfter(timePoint);
return new Pair<FixType, FixType>(lastFixBefore, firstFixAfter);
}
@Override
@@ -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);
@@ -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;
@@ -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<WindSource> windSourcesToDeliver = new ArrayList<WindSource>();
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);
@@ -32,13 +32,17 @@ public class CompositeSettingsDialogComponent implements SettingsDialogComponent
@Override
public Validator<CompositeSettings> 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;
}
@@ -73,7 +73,7 @@ public class TestStoringAndRetrievingWindTracksTest extends AbstractTracTracLive
Event domainEvent = domainFactory.getOrCreateEvent(getEvent());
DynamicTrackedEvent trackedEvent = new RacingEventServiceImpl().getOrCreateTrackedEvent(domainEvent);
Iterable<Receiver> typeControllers = domainFactory.getUpdateReceivers(trackedEvent, getEvent(),
EmptyWindStore.INSTANCE, new DynamicRaceDefinitionSet() {
EmptyWindStore.INSTANCE, /* startOfTracking */ null, /* endOfTracking */ null, new DynamicRaceDefinitionSet() {
@Override
public void addRaceDefinition(RaceDefinition race) {
}
@@ -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
@@ -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<URL, URI, URI> key = new Triple<URL, URI, URI>(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<RaceTracker> trackers = raceTrackersByEvent.get(tracker.getEvent());
if (trackers == null) {