mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-28 14:57:12 +00:00
added boolean takesWind(Wind wind) Method to TrackedRace and did some renaming
This commit is contained in:
1 parent
4abcc4f907
commit
cbaf85766d
9 files changed
+78
-59
No files matched your search
+24
-24
@@ -18,12 +18,12 @@ import com.sap.sse.util.SmartFutureCache.EmptyUpdateInterval;
|
||||
|
||||
public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutionOrderProvider, RaceColumnListenerWithDefaultAction {
|
||||
private static final long serialVersionUID = 4795731834688229568L;
|
||||
private transient SmartFutureCache<String, Map<TrackedRace, Set<TrackedRace>>, EmptyUpdateInterval> raceOrderCacheMappingRaceToItsPredecessor;
|
||||
private transient SmartFutureCache<String, Map<TrackedRace, Set<TrackedRace>>, EmptyUpdateInterval> previousRacesByRaceCache;
|
||||
private final String RACES_ORDER_LIST_CACHE_KEY = "racesOrderCacheKey";
|
||||
private final String RACES_ORDER_LIST_LOCKS_NAME = getClass().getName();
|
||||
|
||||
public AbstractRaceExecutionOrderProvider() {
|
||||
raceOrderCacheMappingRaceToItsPredecessor = createRacesOrderCache();
|
||||
previousRacesByRaceCache = createRacesOrderCache();
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
@@ -34,38 +34,38 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
|
||||
|
||||
@Override
|
||||
public void triggerUpdate() {
|
||||
raceOrderCacheMappingRaceToItsPredecessor.triggerUpdate(RACES_ORDER_LIST_CACHE_KEY, /* update interval */null);
|
||||
previousRacesByRaceCache.triggerUpdate(RACES_ORDER_LIST_CACHE_KEY, /* update interval */null);
|
||||
}
|
||||
|
||||
private Map<TrackedRace, Set<TrackedRace>> getPredecessorsMap() {
|
||||
return raceOrderCacheMappingRaceToItsPredecessor.get(RACES_ORDER_LIST_CACHE_KEY, /* waitForLatest */true);
|
||||
private Map<TrackedRace, Set<TrackedRace>> getPreviousRacesByRace() {
|
||||
return previousRacesByRaceCache.get(RACES_ORDER_LIST_CACHE_KEY, /* waitForLatest */true);
|
||||
}
|
||||
|
||||
protected abstract Map<Fleet, Iterable<? extends RaceColumn>> getRaceColumnsOfSeries();
|
||||
|
||||
private Map<TrackedRace, Set<TrackedRace>> reloadRacesInExecutionOrder() {
|
||||
final Map<TrackedRace, Set<TrackedRace>> raceIdListInExecutionOrder = new HashMap<>();
|
||||
private Map<TrackedRace, Set<TrackedRace>> reloadAndGetPreviousRacesByRace() {
|
||||
final Map<TrackedRace, Set<TrackedRace>> previousRacesByRace = new HashMap<>();
|
||||
for (Entry<Fleet, Iterable<? extends RaceColumn>> raceColumnsInSeries : getRaceColumnsOfSeries().entrySet()) {
|
||||
addPredecessors(raceIdListInExecutionOrder, raceColumnsInSeries.getKey(), raceColumnsInSeries.getValue());
|
||||
addPreviousRaces(previousRacesByRace, raceColumnsInSeries.getKey(), raceColumnsInSeries.getValue());
|
||||
}
|
||||
return raceIdListInExecutionOrder;
|
||||
return previousRacesByRace;
|
||||
}
|
||||
|
||||
private void addPredecessors(final Map<TrackedRace, Set<TrackedRace>> raceIdListInExecutionOrder, Fleet fleet,
|
||||
private void addPreviousRaces(final Map<TrackedRace, Set<TrackedRace>> previousRacesByRace, Fleet fleet,
|
||||
final Iterable<? extends RaceColumn> raceColumns) {
|
||||
TrackedRace predecessor = null;
|
||||
TrackedRace previousRace = null;
|
||||
for (RaceColumn currentRaceColumn : raceColumns) {
|
||||
final TrackedRace trackedRaceInColumnForFleet = currentRaceColumn.getTrackedRace(fleet);
|
||||
if (trackedRaceInColumnForFleet != null) {
|
||||
Set<TrackedRace> predecessors = raceIdListInExecutionOrder.get(trackedRaceInColumnForFleet);
|
||||
if (predecessors == null) {
|
||||
predecessors = new HashSet<>();
|
||||
raceIdListInExecutionOrder.put(trackedRaceInColumnForFleet, predecessors);
|
||||
Set<TrackedRace> previousRaces = previousRacesByRace.get(trackedRaceInColumnForFleet);
|
||||
if (previousRaces == null) {
|
||||
previousRaces = new HashSet<>();
|
||||
previousRacesByRace.put(trackedRaceInColumnForFleet, previousRaces);
|
||||
}
|
||||
if (predecessor != null) {
|
||||
predecessors.add(predecessor);
|
||||
if (previousRace != null) {
|
||||
previousRaces.add(previousRace);
|
||||
}
|
||||
predecessor = trackedRaceInColumnForFleet;
|
||||
previousRace = trackedRaceInColumnForFleet;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
|
||||
public Map<TrackedRace, Set<TrackedRace>> computeCacheUpdate(String key,
|
||||
EmptyUpdateInterval updateInterval) throws Exception {
|
||||
if (key.equals(RACES_ORDER_LIST_CACHE_KEY)) {
|
||||
return reloadRacesInExecutionOrder();
|
||||
return reloadAndGetPreviousRacesByRace();
|
||||
} else {
|
||||
final Map<TrackedRace, Set<TrackedRace>> emptyMap = Collections.emptyMap();
|
||||
return emptyMap;
|
||||
@@ -88,18 +88,18 @@ public abstract class AbstractRaceExecutionOrderProvider implements RaceExecutio
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||
ois.defaultReadObject();
|
||||
this.raceOrderCacheMappingRaceToItsPredecessor = createRacesOrderCache();
|
||||
this.previousRacesByRaceCache = createRacesOrderCache();
|
||||
// don't call triggerUpdate() as of now because the cache's owner may not yet be fully initialized,
|
||||
// so the getRaceColumnsOfSeries() method may not yet be able to do its work. The owner must call
|
||||
// triggerUpdate when fully initialized.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TrackedRace> getPreviousRaceInExecutionOrder(TrackedRace race) {
|
||||
public Set<TrackedRace> getPreviousRacesInExecutionOrder(TrackedRace race) {
|
||||
Set<TrackedRace> result = Collections.emptySet();
|
||||
final Map<TrackedRace, Set<TrackedRace>> predecessorMap = getPredecessorsMap();
|
||||
if (predecessorMap != null) {
|
||||
result = predecessorMap.get(race);
|
||||
final Map<TrackedRace, Set<TrackedRace>> previousRacesByRace = getPreviousRacesByRace();
|
||||
if (previousRacesByRace != null) {
|
||||
result = previousRacesByRace.get(race);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import java.util.Set;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
|
||||
/**
|
||||
* Sometimes {@link TrackedRace}s want to know which {@link TrackedRace} is in front of them in the execution order
|
||||
* Sometimes {@link TrackedRace}s want to know which {@link DynamicTrackedRace} is in front of them in the execution order
|
||||
* of a {@link Regatta}. This is i.e interesting to know in the {@link DynamicTrackedRace #recordWind(com.sap.sailing.domain.common.Wind, com.sap.sailing.domain.common.WindSource)}
|
||||
* method, when the race has to decide whether to record the wind. If a previous {@link TrackedRace}
|
||||
* is <code>null</code>, the current {@link TrackedRace} would save the wind fixes earlier.
|
||||
@@ -20,7 +20,7 @@ public interface RaceExecutionOrderProvider {
|
||||
* {@link TrackedRace}s in the execution order of a {@link Regatta}. This expresses the fact that the races returned
|
||||
* by this method must all have been finished before <code>race</code> can start.
|
||||
*/
|
||||
Set<TrackedRace> getPreviousRaceInExecutionOrder(TrackedRace race);
|
||||
Set<TrackedRace> getPreviousRacesInExecutionOrder(TrackedRace race);
|
||||
|
||||
/**
|
||||
* When the owner of this cache-like provider has initialized all its structures that this cache requires
|
||||
|
||||
@@ -275,6 +275,11 @@ public interface TrackedRace extends Serializable {
|
||||
* is returned. Otherwise, the center of gravity between the mark positions is computed and returned.
|
||||
*/
|
||||
Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Checks whether the {@link Wind#getTimePoint()} is in range of start and end {@link TimePoint}s plus extra time for wind recording.
|
||||
*/
|
||||
boolean takesWindFix(Wind wind);
|
||||
|
||||
/**
|
||||
* Same as {@link #getWind(Position, TimePoint, Set) getWind(p, at, Collections.emptyList())}
|
||||
|
||||
+1
-24
@@ -24,7 +24,6 @@ import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Sideline;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.TimingConstants;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
@@ -46,12 +45,10 @@ import com.sap.sailing.domain.tracking.RaceAbortedListener;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRaceStatus;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
@@ -660,18 +657,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
@Override
|
||||
public boolean recordWind(Wind wind, WindSource windSource) {
|
||||
final boolean result;
|
||||
// TODO check what a good filter is; remember that start/end of tracking may change over time; what if we have discarded valuable wind fixes?
|
||||
TimePoint startOfRace = getStartOfRace();
|
||||
TimePoint startOfTracking = getStartOfTracking();
|
||||
TimePoint endOfRace = getEndOfRace();
|
||||
TimePoint endOfTracking = getEndOfTracking();
|
||||
final Duration conditionalTimeBeforeStartToTrackWind = getConditionalTimeBeforeStartToTrackWind(wind.getTimePoint());
|
||||
if ((startOfTracking == null || !startOfTracking.minus(conditionalTimeBeforeStartToTrackWind).after(wind.getTimePoint()) ||
|
||||
(startOfRace != null && !startOfRace.minus(conditionalTimeBeforeStartToTrackWind).after(wind.getTimePoint())))
|
||||
&&
|
||||
// Caution: don't add to endOfTracking; it may be the end of time, leading to a wrap-around / overflow
|
||||
(endOfTracking == null || endOfTracking.after(wind.getTimePoint().minus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS)) ||
|
||||
(endOfRace != null && endOfRace.plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).after(wind.getTimePoint())))) {
|
||||
if(takesWindFix(wind)){
|
||||
result = getOrCreateWindTrack(windSource).add(wind);
|
||||
updated(/* time point */null); // wind events shouldn't advance race time
|
||||
triggerManeuverCacheRecalculationForAllCompetitors();
|
||||
@@ -681,15 +667,6 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Duration getConditionalTimeBeforeStartToTrackWind(TimePoint timePointOfWindFix) {
|
||||
Set<TrackedRace> previousRacesInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
|
||||
if (previousRacesInExecutionOrder == null || !previousRacesInExecutionOrder.stream().filter(tr->tr.getEndOfTracking() != null).findAny().isPresent()) {
|
||||
return EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS;
|
||||
} else {
|
||||
return TIME_BEFORE_START_TO_TRACK_WIND_MILLIS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeWind(Wind wind, WindSource windSource) {
|
||||
|
||||
+26
-8
@@ -286,7 +286,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
*/
|
||||
protected transient ConcurrentHashMap<Serializable, RegattaLog> attachedRegattaLogs;
|
||||
|
||||
private transient ConcurrentHashMap<RaceExecutionOrderProvider, RaceExecutionOrderProvider> attachedRaceExecutionOrderProvider;
|
||||
private transient ConcurrentHashMap<RaceExecutionOrderProvider, RaceExecutionOrderProvider> attachedRaceExecutionOrderProviders;
|
||||
|
||||
/**
|
||||
* The time delay to the current point in time in milliseconds.
|
||||
@@ -380,7 +380,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
locksForMarkPassings = new IdentityHashMap<>();
|
||||
attachedRaceLogs = new ConcurrentHashMap<>();
|
||||
attachedRegattaLogs = new ConcurrentHashMap<>();
|
||||
attachedRaceExecutionOrderProvider = new ConcurrentHashMap<>();
|
||||
attachedRaceExecutionOrderProviders = new ConcurrentHashMap<>();
|
||||
this.status = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.PREPARED, 0.0);
|
||||
this.statusNotifier = new Object[0];
|
||||
this.loadingFromWindStoreLock = new NamedReentrantReadWriteLock("Loading from wind store lock for tracked race "
|
||||
@@ -578,7 +578,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
ois.defaultReadObject();
|
||||
raceStates = new WeakHashMap<>();
|
||||
attachedRaceLogs = new ConcurrentHashMap<>();
|
||||
attachedRaceExecutionOrderProvider = new ConcurrentHashMap<>();
|
||||
attachedRaceExecutionOrderProviders = new ConcurrentHashMap<>();
|
||||
markPassingsTimes = new ArrayList<com.sap.sse.common.Util.Pair<Waypoint, com.sap.sse.common.Util.Pair<TimePoint, TimePoint>>>();
|
||||
// The short time wind cache needs to be there before operations such as maneuver recalculation try to access it
|
||||
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
|
||||
@@ -1495,6 +1495,24 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean takesWindFix(Wind wind) {
|
||||
boolean result = false;
|
||||
TimePoint earliestStartTimePoint = Util.getEarliestOfTimePoints(getStartOfRace(), getStartOfTracking());
|
||||
TimePoint latestEndTimePoint = Util.getLatestOfTimePoints(getStartOfRace(), getStartOfTracking());
|
||||
if (earliestStartTimePoint != null && latestEndTimePoint != null) {
|
||||
TimePoint earliestStartTimePointMinusExtra = earliestStartTimePoint.minus(EXTRA_LONG_TIME_BEFORE_START_TO_TRACK_WIND_MILLIS);
|
||||
TimePoint latestEndTimePointPlusExtra = latestEndTimePoint.plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS);
|
||||
if (Util.isTimePointInRangeOfTimePointsAandB(wind.getTimePoint(), /* a */earliestStartTimePointMinusExtra, /* b */latestEndTimePointPlusExtra)) {
|
||||
Set<TrackedRace> previousRacesInExecutionOrder = getPreviousRacesFromAttachedRaceExecutionOrderProviders();
|
||||
if(previousRacesInExecutionOrder == null || !previousRacesInExecutionOrder.stream().filter(tr->tr.takesWindFix(wind) == true).findAny().isPresent()){
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWind(Position p, TimePoint at) {
|
||||
@@ -3054,15 +3072,15 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
@Override
|
||||
public void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider) {
|
||||
if (raceExecutionOrderProvider != null && !attachedRaceExecutionOrderProvider.containsKey(raceExecutionOrderProvider)) {
|
||||
attachedRaceExecutionOrderProvider.put(raceExecutionOrderProvider, raceExecutionOrderProvider);
|
||||
if (raceExecutionOrderProvider != null && !attachedRaceExecutionOrderProviders.containsKey(raceExecutionOrderProvider)) {
|
||||
attachedRaceExecutionOrderProviders.put(raceExecutionOrderProvider, raceExecutionOrderProvider);
|
||||
}
|
||||
}
|
||||
|
||||
protected Set<TrackedRace> getPreviousRacesFromAttachedRaceExecutionOrderProviders() {
|
||||
final Set<TrackedRace> result;
|
||||
if (attachedRaceExecutionOrderProvider != null) {
|
||||
result = attachedRaceExecutionOrderProvider.values().stream().map(reop->reop.getPreviousRaceInExecutionOrder(this)).collect(HashSet::new, (r, e)->r.addAll(e), (r, e)->r.addAll(e));
|
||||
if (attachedRaceExecutionOrderProviders != null) {
|
||||
result = attachedRaceExecutionOrderProviders.values().stream().map(reop->reop.getPreviousRacesInExecutionOrder(this)).collect(HashSet::new, (r, e)->r.addAll(e), (r, e)->r.addAll(e));
|
||||
} else {
|
||||
result = Collections.emptySet();
|
||||
}
|
||||
@@ -3072,7 +3090,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
@Override
|
||||
public void detachRaceExecutionOrderProvider(RaceExecutionOrderProvider raceExecutionOrderProvider) {
|
||||
if (raceExecutionOrderProvider != null) {
|
||||
attachedRaceExecutionOrderProvider.remove(raceExecutionOrderProvider);
|
||||
attachedRaceExecutionOrderProviders.remove(raceExecutionOrderProvider);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user