mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-24 14:38:45 +00:00
bug5207: compilable version with average leg wind cache moved to right place
This commit is contained in:
+6
@@ -15,6 +15,12 @@ public interface ORCPerformanceCurveLeg extends Serializable {
|
||||
*/
|
||||
Bearing getTwa();
|
||||
|
||||
/**
|
||||
* Same as {@link #getTwa()}, but with the possibility to pass a cache that can remember the results
|
||||
* of computing the wind for a specific leg across a certain computing scope.
|
||||
*/
|
||||
Bearing getTwa(AverageWindOnLegCache cache);
|
||||
|
||||
String toString();
|
||||
|
||||
ORCPerformanceCurveLegTypes getType();
|
||||
|
||||
+6
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.domain.common.orc.impl;
|
||||
|
||||
import com.sap.sailing.domain.common.orc.AverageWindOnLegCache;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes;
|
||||
import com.sap.sse.common.Bearing;
|
||||
@@ -33,6 +34,11 @@ public class ORCPerformanceCurveLegImpl implements ORCPerformanceCurveLeg {
|
||||
return twa;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getTwa(AverageWindOnLegCache cache) {
|
||||
return twa;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ORCPerformanceCurveLeg scale(double share) {
|
||||
final Distance scaledLength = getLength().scale(share);
|
||||
|
||||
-7
@@ -8,7 +8,6 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
@@ -1292,10 +1291,4 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
public TrackingConnectorInfo getTrackingConnectorInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-6
@@ -8,7 +8,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
@@ -815,9 +814,4 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-9
@@ -2,7 +2,6 @@ package com.sap.sailing.domain.leaderboard.caching;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -32,6 +31,7 @@ import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveCourseImpl;
|
||||
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.AbstractSimpleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.orc.impl.AbstractORCPerformanceCurveTwaLegAdapter;
|
||||
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveByImpliedWindRankingMetric;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
@@ -83,6 +83,11 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea
|
||||
*/
|
||||
final ConcurrentHashMap<Triple<TrackedRace, Competitor, TimePoint>, Wind> windCache;
|
||||
|
||||
/**
|
||||
* The average wind in a leg as defined by {@link TrackedLeg#getAverageWind(int)}. See {@link #getWindForLeg(TrackedLeg, Function)}.
|
||||
*/
|
||||
private final ConcurrentHashMap<ORCPerformanceCurveLeg, Wind> trackedLegAverageWindCache;
|
||||
|
||||
private static final Wind NULL_WIND = new WindImpl(/* position */ new DegreePosition(0, 0),
|
||||
/* time point */ MillisecondsTimePoint.now(), /* windSpeedWithBearing */ new KnotSpeedWithBearingImpl(0, new DegreeBearingImpl(0)));
|
||||
|
||||
@@ -146,6 +151,7 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea
|
||||
windCache = new ConcurrentHashMap<>();
|
||||
scratchBoat = new ConcurrentHashMap<>();
|
||||
legBearingCache = new ConcurrentHashMap<>();
|
||||
trackedLegAverageWindCache = new ConcurrentHashMap<>();
|
||||
relativeCorrectedTimePerCompetitor = new ConcurrentHashMap<>();
|
||||
approximateWaypointPositions = new ConcurrentHashMap<>();
|
||||
this.performanceCurvesPerCompetitor = new ConcurrentHashMap<>();
|
||||
@@ -209,12 +215,12 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea
|
||||
@Override
|
||||
public ORCPerformanceCurveCourse getTotalCourse(TrackedRace raceContext, Supplier<ORCPerformanceCurveCourse> totalCourseSupplier) {
|
||||
if (totalCourse == null) {
|
||||
totalCourse = fixORCPerformanceCurveCourse(totalCourseSupplier.get());
|
||||
totalCourse = fixORCPerformanceCurveCourse(totalCourseSupplier.get(), /* cache */ this);
|
||||
}
|
||||
return totalCourse;
|
||||
}
|
||||
|
||||
private ORCPerformanceCurveCourse fixORCPerformanceCurveCourse(ORCPerformanceCurveCourse course) {
|
||||
private ORCPerformanceCurveCourse fixORCPerformanceCurveCourse(ORCPerformanceCurveCourse course, ORCPerformanceCurveCache cache) {
|
||||
final List<ORCPerformanceCurveLeg> legs = new ArrayList<>();
|
||||
boolean changed = false;
|
||||
for (final ORCPerformanceCurveLeg leg : course.getLegs()) {
|
||||
@@ -316,11 +322,13 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindForLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
Triple<TrackedRace, Competitor, TimePoint> cacheKey = new Triple<>(leg.getTrackedRace(), null, timePoint);
|
||||
return Optional.ofNullable(windCache.get(cacheKey)).orElseGet(() -> {
|
||||
windCache.put(cacheKey, value.get());
|
||||
return windCache.get(cacheKey);
|
||||
});
|
||||
public <L extends ORCPerformanceCurveLeg> Wind getAverageWind(L leg,
|
||||
Function<L, Wind> averageWindForLegSupplier) {
|
||||
Wind result = trackedLegAverageWindCache.get(leg);
|
||||
if (result == null) {
|
||||
result = averageWindForLegSupplier.apply(leg);
|
||||
trackedLegAverageWindCache.put(leg, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-9
@@ -5,7 +5,7 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.orc.AverageWindOnLegCache;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes;
|
||||
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
|
||||
@@ -15,7 +15,7 @@ import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public interface ORCPerformanceCurveCache {
|
||||
public interface ORCPerformanceCurveCache extends AverageWindOnLegCache {
|
||||
/**
|
||||
* If not yet computed, computes a copy of the total course supplied by the {@code totalCourseSupplier} where
|
||||
* any adapted leg that would query a live {@link TrackedLeg} for TWA and distance is replaced by a leg of
|
||||
@@ -60,10 +60,4 @@ public interface ORCPerformanceCurveCache {
|
||||
*/
|
||||
Duration getRelativeCorrectedTime(Competitor competitor, TrackedRace raceContext,
|
||||
TimePoint timePoint, BiFunction<Competitor, TimePoint, Duration> relativeCorrectedTimeSupplier);
|
||||
|
||||
/**
|
||||
* Determines the wind at the leg. The result is cached for subsequent calls with equal parameters.
|
||||
* @param value function for compute wind value if it's not preset in cache
|
||||
*/
|
||||
Wind getWindForLeg(TrackedLeg leg, Supplier<Wind> value);
|
||||
}
|
||||
}
|
||||
+8
-30
@@ -1,21 +1,16 @@
|
||||
package com.sap.sailing.domain.orc.impl;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.orc.AverageWindOnLegCache;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes;
|
||||
import com.sap.sailing.domain.confidence.ConfidenceBasedWindAverager;
|
||||
import com.sap.sailing.domain.confidence.ConfidenceFactory;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindWithConfidence;
|
||||
import com.sap.sailing.domain.tracking.impl.NoCachingWindLegTypeAndLegBearingCache;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
/**
|
||||
* Abstract base class for adapting a {@link TrackedLeg} to the {@link ORCPerformanceCurveLeg} interface. If wind
|
||||
@@ -47,31 +42,14 @@ public abstract class AbstractORCPerformanceCurveTwaLegAdapter implements ORCPer
|
||||
return trackedLeg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a {@link Wind} estimation based on {@link #numParts} x {@link #numParts} wind samples, taken for
|
||||
* {@link #numParts} time points spread equally across the time range between the first boat entering and the last
|
||||
* boat exiting the leg (defaulting to "now" if no boat has exited the leg yet) and across {@link #numParts}
|
||||
* positions along the great circle segment connecting the approximate start waypoint's position and the approximate
|
||||
* end waypoint's position at the respective time point. Those wind samples are averaged based on their original
|
||||
* confidences. The {@link #scale(double) scaling} of this leg does not affect the wind sampling; in all cases, wind
|
||||
* samples will always be taken along the full leg distance, making the result of this method the same for the same
|
||||
* boundary conditions (mark passings etc.) for all competitors.
|
||||
*/
|
||||
private Wind getWind() {
|
||||
ConfidenceBasedWindAverager<Util.Pair<Position, TimePoint>> timeWeigher =
|
||||
ConfidenceFactory.INSTANCE.createWindAverager(/* weigher==null means use 1.0 as base confidence */ null);
|
||||
final Iterable<TimePoint> referenceTimePoints = trackedLeg.getEquidistantReferenceTimePoints(numParts);
|
||||
Iterable<WindWithConfidence<Util.Pair<Position, TimePoint>>> winds =
|
||||
Util.stream(referenceTimePoints).flatMap(timepoint -> {
|
||||
return Util.stream(trackedLeg.getEquidistantSectionsOfLeg(timepoint, numParts))
|
||||
.map(p -> trackedLeg.getTrackedRace().getWindWithConfidence(p, timepoint));
|
||||
}).collect(Collectors.toList());
|
||||
return timeWeigher.getAverage(winds, null).getObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getTwa() {
|
||||
final Wind wind = getTrackedLeg().getTrackedRace().getWindByTrackedLeg(getTrackedLeg(), () -> getWind());
|
||||
return getTwa(new NoCachingWindLegTypeAndLegBearingCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bearing getTwa(AverageWindOnLegCache cache) {
|
||||
final Wind wind = cache.getAverageWind(this, legAdapter->legAdapter.getTrackedLeg().getAverageWind(/* numParts */ 10).getObject());
|
||||
final Bearing result;
|
||||
if (wind == null) {
|
||||
result = null;
|
||||
|
||||
+2
-2
@@ -485,7 +485,7 @@ implements com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric {
|
||||
} else {
|
||||
final ORCCertificate certificate = getCertificate(getTrackedRace().getBoatOfCompetitor(competitor));
|
||||
if (certificate != null) {
|
||||
performanceCurveForPartialCourse = new ORCPerformanceCurveImpl(certificate, competitorsPartialCourseAtTimePoint);
|
||||
performanceCurveForPartialCourse = new ORCPerformanceCurveImpl(certificate, competitorsPartialCourseAtTimePoint, cache);
|
||||
} else {
|
||||
performanceCurveForPartialCourse = null;
|
||||
}
|
||||
@@ -671,7 +671,7 @@ implements com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric {
|
||||
final ORCCertificate certificate = getCertificate(getTrackedRace().getBoatOfCompetitor(competitor));
|
||||
if (certificate != null) {
|
||||
performanceCurveForCompetitorToPositionOfCompetitorFarthestAhread = new ORCPerformanceCurveImpl(certificate,
|
||||
courseOfCompetitorFarthestAhead);
|
||||
courseOfCompetitorFarthestAhead, cache);
|
||||
final Speed competitorsCurrentImpliedWind = cache.getImpliedWind(timePoint, getTrackedRace(), competitorFarthestAhead, getImpliedWindSupplier(cache));
|
||||
if (competitorsCurrentImpliedWind != null) {
|
||||
final Duration allowanceToPositionOfBoatFarthestAhead = performanceCurveForCompetitorToPositionOfCompetitorFarthestAhread
|
||||
|
||||
+19
-4
@@ -27,6 +27,9 @@ import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.impl.NoCachingWindLegTypeAndLegBearingCache;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
@@ -88,10 +91,15 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
|
||||
* boat is assumed to need at that true wind speed/angle for one nautical mile.
|
||||
*/
|
||||
public ORCPerformanceCurveImpl(ORCCertificate certificate, ORCPerformanceCurveCourse course) throws FunctionEvaluationException {
|
||||
this(certificate, course, new NoCachingWindLegTypeAndLegBearingCache());
|
||||
}
|
||||
|
||||
public ORCPerformanceCurveImpl(ORCCertificate certificate, ORCPerformanceCurveCourse course,
|
||||
WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws FunctionEvaluationException {
|
||||
this.course = course;
|
||||
this.trueWindAngles = certificate.getTrueWindAngles();
|
||||
this.trueWindSpeeds = certificate.getTrueWindSpeeds();
|
||||
functionImpliedWindInKnotsToAverageSpeedInKnotsForCourse = createPerformanceCurve(certificate);
|
||||
functionImpliedWindInKnotsToAverageSpeedInKnotsForCourse = createPerformanceCurve(certificate, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,8 +118,9 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
|
||||
* assumed at 10000kts true wind speed is the same as for the highest wind speed from the original list.
|
||||
* <p>
|
||||
*/
|
||||
private UnivariateDifferentiableFunction createPerformanceCurve(ORCCertificate certificate) throws FunctionEvaluationException {
|
||||
final Map<Speed, Duration> allowancesForCoursePerTrueWindSpeed = createAllowancesPerCourse(certificate);
|
||||
private UnivariateDifferentiableFunction createPerformanceCurve(ORCCertificate certificate,
|
||||
ORCPerformanceCurveCache cache) throws FunctionEvaluationException {
|
||||
final Map<Speed, Duration> allowancesForCoursePerTrueWindSpeed = createAllowancesPerCourse(certificate, cache);
|
||||
double[] xs = new double[certificate.getTrueWindSpeeds().length+2];
|
||||
double[] ys = new double[certificate.getTrueWindSpeeds().length+2];
|
||||
int i = 0;
|
||||
@@ -148,7 +157,8 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
|
||||
* {@link #course}, keyed by the different true wind speeds. The resulting {@link LinkedHashMap}'s iteration
|
||||
* order is guaranteed to deliver the true wind speed keys in the order of ascending wind speeds.
|
||||
*/
|
||||
public LinkedHashMap<Speed, Duration> createAllowancesPerCourse(ORCCertificate certificate) throws FunctionEvaluationException {
|
||||
public LinkedHashMap<Speed, Duration> createAllowancesPerCourse(ORCCertificate certificate,
|
||||
ORCPerformanceCurveCache cache) throws FunctionEvaluationException {
|
||||
final LinkedHashMap<Speed, Duration> result = new LinkedHashMap<>();
|
||||
final Map<ORCPerformanceCurveLeg, Map<Speed, Duration>> allowancesPerLeg = new HashMap<>();
|
||||
for (final ORCPerformanceCurveLeg leg : course.getLegs()) {
|
||||
@@ -169,6 +179,11 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
|
||||
* considering the leg's {@link ORCPerformanceCurveLeg#getLength() length}.
|
||||
*/
|
||||
private Map<Speed, Duration> createAllowancePerLeg(ORCPerformanceCurveLeg leg, ORCCertificate certificate) throws FunctionEvaluationException {
|
||||
return createAllowancePerLeg(leg, certificate, new NoCachingWindLegTypeAndLegBearingCache());
|
||||
}
|
||||
|
||||
private Map<Speed, Duration> createAllowancePerLeg(ORCPerformanceCurveLeg leg, ORCCertificate certificate,
|
||||
ORCPerformanceCurveCache cache) throws FunctionEvaluationException {
|
||||
Map<Speed, Map<Bearing, Speed>> twaAllowances = certificate.getVelocityPredictionPerTrueWindSpeedAndAngle();
|
||||
Map<Speed, Bearing> beatAngles = certificate.getBeatAngles();
|
||||
Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed = certificate.getBeatVMGPredictions();
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
@@ -751,10 +750,4 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
||||
public TrackingConnectorInfo getTrackingConnectorInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ import com.sap.sailing.domain.common.LegType;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.TargetTimeInfo.LegTargetTimeInfo;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
public interface TrackedLeg extends Serializable {
|
||||
@@ -248,7 +250,24 @@ public interface TrackedLeg extends Serializable {
|
||||
* "now" is used.
|
||||
*/
|
||||
Iterable<TimePoint> getEquidistantReferenceTimePoints(int numberOfPoints);
|
||||
|
||||
|
||||
/**
|
||||
* Computes a {@link Wind} estimation based on {@link #numParts} x {@link #numParts} wind samples, taken for
|
||||
* {@link #numParts} time points spread equally across the time range between the first boat entering and the last
|
||||
* boat exiting the leg (defaulting to "now" if no boat has exited the leg yet) and across {@link #numParts}
|
||||
* positions along the great circle segment connecting the approximate start waypoint's position and the approximate
|
||||
* end waypoint's position at the respective time point. Those wind samples are averaged based on their original
|
||||
* confidences. The {@link #scale(double) scaling} of this leg does not affect the wind sampling; in all cases, wind
|
||||
* samples will always be taken along the full leg distance, making the result of this method the same for the same
|
||||
* boundary conditions (mark passings etc.) for all competitors.
|
||||
*
|
||||
* @param numParts
|
||||
* the number of positions and the number of time points to use for averaging the wind field; the result
|
||||
* will hence be computed as an average---weighted by the original confidence of each wind estimation at
|
||||
* any of these positions/time points---of these {@code numParts*numParts} wind estimations.
|
||||
*/
|
||||
WindWithConfidence<Util.Pair<Position, TimePoint>> getAverageWind(int numParts);
|
||||
|
||||
/**
|
||||
* The leader at the given <code>timePoint</code> in this leg, based on the {@link TrackedRace#getRankingMetric() ranking metric}
|
||||
* installed for the race.
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.orc.RaceLogORCImpliedWindSourceEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
@@ -1257,11 +1256,4 @@ public interface TrackedRace
|
||||
* may be {@code null}, particularly in test set-ups
|
||||
*/
|
||||
TrackingConnectorInfo getTrackingConnectorInfo();
|
||||
|
||||
/**
|
||||
* Obtains estimated interpolated wind information for a given tracked leg.
|
||||
* @param value
|
||||
* @return cached value or value computed by supplier function
|
||||
*/
|
||||
Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value);
|
||||
}
|
||||
|
||||
+3
-3
@@ -11,6 +11,7 @@ import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.Wind;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
|
||||
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
|
||||
import com.sap.sailing.domain.orc.ORCPerformanceCurve;
|
||||
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
@@ -83,8 +84,7 @@ public class NoCachingWindLegTypeAndLegBearingCache implements WindLegTypeAndLeg
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindForLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
return null;
|
||||
public <L extends ORCPerformanceCurveLeg> Wind getAverageWind(L leg, Function<L, Wind> averageWindForLegSupplier) {
|
||||
return averageWindForLegSupplier.apply(leg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
@@ -19,6 +19,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
@@ -36,6 +37,8 @@ import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.impl.TargetTimeInfoImpl;
|
||||
import com.sap.sailing.domain.confidence.ConfidenceBasedWindAverager;
|
||||
import com.sap.sailing.domain.confidence.ConfidenceFactory;
|
||||
import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache;
|
||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||
import com.sap.sailing.domain.polars.PolarDataService;
|
||||
@@ -297,6 +300,21 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindWithConfidence<Pair<Position, TimePoint>> getAverageWind(int numParts) {
|
||||
ConfidenceBasedWindAverager<Util.Pair<Position, TimePoint>> timeWeigher =
|
||||
ConfidenceFactory.INSTANCE.createWindAverager(/* weigher==null means use 1.0 as base confidence */ null);
|
||||
final Iterable<TimePoint> referenceTimePoints = getEquidistantReferenceTimePoints(numParts);
|
||||
Iterable<WindWithConfidence<Util.Pair<Position, TimePoint>>> winds =
|
||||
Util.stream(referenceTimePoints).flatMap(timepoint -> {
|
||||
return Util.stream(getEquidistantSectionsOfLeg(timepoint, numParts))
|
||||
.map(p -> getTrackedRace().getWindWithConfidence(p, timepoint));
|
||||
}).collect(Collectors.toList());
|
||||
return timeWeigher.getAverage(winds, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Position getEffectiveWindPosition(Callable<Position> exactPositionProvider, TimePoint at, WindPositionMode mode) {
|
||||
final Position effectivePosition;
|
||||
switch (mode) {
|
||||
|
||||
-10
@@ -33,7 +33,6 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -431,8 +430,6 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
private final NamedReentrantReadWriteLock sensorTracksLock;
|
||||
|
||||
private transient ConcurrentMap<TimePoint, LeaderboardDTOCalculationReuseCache> windLegByTimepointCache;
|
||||
|
||||
/**
|
||||
* Constructs the tracked race with one-design ranking.
|
||||
*/
|
||||
@@ -594,13 +591,6 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
logger.log(Level.SEVERE, "Waiting for loading from stores to finish was interrupted", e);
|
||||
}
|
||||
rankingMetric = rankingMetricConstructor.apply(this);
|
||||
windLegByTimepointCache = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
LeaderboardDTOCalculationReuseCache windByLeg = windLegByTimepointCache.computeIfAbsent(leg.getReferenceTimePoint(), LeaderboardDTOCalculationReuseCache::new);
|
||||
return windByLeg.getWindForLeg(leg, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-7
@@ -10,7 +10,6 @@ import java.util.NavigableSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
@@ -967,10 +966,4 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
public TrackingConnectorInfo getTrackingConnectorInfo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wind getWindByTrackedLeg(TrackedLeg leg, Supplier<Wind> value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user