diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TWATest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TWATest.java index 644b6496bb2..71f2e94f235 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TWATest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TWATest.java @@ -23,7 +23,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.TrackedLegImpl; @@ -65,7 +65,7 @@ public class TWATest { when(competitorTrack.getEstimatedSpeed((TimePoint) anyObject())).thenReturn(new KnotSpeedWithBearingImpl(10, boatToBearing)); when(trackedRace.getTWA(Matchers.eq(competitor), (TimePoint) anyObject())).thenCallRealMethod(); - when(trackedRace.getTWA(Matchers.eq(competitor), (TimePoint) anyObject(), (WindLegTypeAndLegBearingCache) anyObject())).thenCallRealMethod(); + when(trackedRace.getTWA(Matchers.eq(competitor), (TimePoint) anyObject(), (WindLegTypeAndLegBearingAndORCPerformanceCurveCache) anyObject())).thenCallRealMethod(); } @Test diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index 63408730c96..2d653c2aad7 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -78,7 +78,7 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRaceStatus; import com.sap.sailing.domain.tracking.TrackingDataLoader; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindSummary; @@ -826,7 +826,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -1040,7 +1040,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -1126,17 +1126,17 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -1246,7 +1246,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java index 98ab8640dde..f90483424ac 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithStartTimeAndRanks.java @@ -58,7 +58,7 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; 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.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindSummary; @@ -429,7 +429,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -588,7 +588,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -652,17 +652,17 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -764,7 +764,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { @Override public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java index 46150dd8240..2bf251a4da1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/caching/LeaderboardDTOCalculationReuseCache.java @@ -1,7 +1,11 @@ package com.sap.sailing.domain.leaderboard.caching; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; +import java.util.function.Supplier; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; @@ -11,12 +15,20 @@ import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.impl.WindImpl; +import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse; +import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg; +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.impl.ORCPerformanceCurveByImpliedWindRankingMetric; +import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveLegAdapter; import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Bearing; +import com.sap.sse.common.Speed; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; @@ -39,7 +51,7 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; * @author Axel Uhl (D043530) * */ -public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBearingCache { +public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBearingAndORCPerformanceCurveCache { /** * The reference time point for all queries to which values will be cached here. Queries that don't match this time point are * neither cached nor looked up in the cache. @@ -63,6 +75,23 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea * the leg's bearing at timePoint; null values are represented by {@link #NULL_BEARING}. */ final ConcurrentHashMap legBearingCache; + + /** + * The course for a race ranked by an {@link ORCPerformanceCurveByImpliedWindRankingMetric} metric or subclasses + * thereof. This course will have any tracked leg adapters replaced by fixed leg descriptions with a fixed TWA and + * distance as obtained upon the first call for the {@link #timePoint} from the underlying {@link TrackedRace}. + */ + private ORCPerformanceCurveCourse totalCourse; + + /** + * The scratch boat at {@link #timePoint}, once it has been requested, computed by a supplier that has + * to be provided to {@link #getScratchBoat(Supplier)}. + */ + private Competitor scratchBoat; + + private final ConcurrentHashMap performanceCurvesPerCompetitor; + + private final ConcurrentHashMap impliedWindPerCompetitor; private static final Bearing NULL_BEARING = new DegreeBearingImpl(0); @@ -70,6 +99,8 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea legTypeCache = new ConcurrentHashMap<>(); windCache = new ConcurrentHashMap<>(); legBearingCache = new ConcurrentHashMap<>(); + this.performanceCurvesPerCompetitor = new ConcurrentHashMap<>(); + this.impliedWindPerCompetitor = new ConcurrentHashMap<>(); this.timePoint = timePoint; } @@ -118,4 +149,51 @@ public class LeaderboardDTOCalculationReuseCache implements WindLegTypeAndLegBea } return result; } + + @Override + public ORCPerformanceCurveCourse getTotalCourse(Supplier totalCourseSupplier) { + if (totalCourse == null) { + totalCourse = fixORCPerformanceCurveCourse(totalCourseSupplier.get()); + } + return totalCourse; + } + + private ORCPerformanceCurveCourse fixORCPerformanceCurveCourse(ORCPerformanceCurveCourse course) { + final List legs = new ArrayList<>(); + boolean changed = false; + for (final ORCPerformanceCurveLeg leg : course.getLegs()) { + if (leg instanceof ORCPerformanceCurveLegAdapter) { + legs.add(new ORCPerformanceCurveLegImpl(leg.getLength(), leg.getTwa())); + changed = true; + } else { + legs.add(leg); + } + } + final ORCPerformanceCurveCourse result; + if (changed) { + result = new ORCPerformanceCurveCourseImpl(legs); + } else { + result = course; + } + return result; + } + + @Override + public Competitor getScratchBoat(Supplier scratchBoatSupplier) { + if (scratchBoat == null) { + scratchBoat = scratchBoatSupplier.get(); + } + return scratchBoat; + } + + @Override + public ORCPerformanceCurve getPerformanceCurveForPartialCourse(Competitor competitor, + Function performanceCurveSupplier) { + return performanceCurvesPerCompetitor.computeIfAbsent(competitor, performanceCurveSupplier); + } + + @Override + public Speed getImpliedWind(Competitor competitor, Function impliedWindSupplier) { + return impliedWindPerCompetitor.computeIfAbsent(competitor, impliedWindSupplier); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java index a5eee239edd..395d1160fed 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java @@ -81,7 +81,7 @@ import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; import com.sap.sse.common.Bearing; @@ -483,6 +483,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { } } } + final Map, RankingInfo> rankingInfoCache = new HashMap<>(); for (final Competitor competitor : this.getCompetitorsFromBestToWorst(timePoint)) { CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitor); LeaderboardRowDTO row = new LeaderboardRowDTO(); @@ -497,14 +498,20 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { Map> futuresForColumnName = new HashMap>(); final Set discardedRaceColumns = getResultDiscardingRule().getDiscardedRaceColumns(competitor, this, getRaceColumns(), timePoint); for (final RaceColumn raceColumn : this.getRaceColumns()) { + final boolean computeLegDetails = namesOfRaceColumnsForWhichToLoadLegDetails != null && + namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName()); + // if leg details are to be requested, the ranking info needs to be provided: + final RankingInfo rankingInfo = computeLegDetails ? rankingInfoCache.computeIfAbsent(new Pair<>(raceColumn, competitor), + raceColumnAndCompetitor->{ + final TrackedRace trackedRace = raceColumnAndCompetitor.getA().getTrackedRace(raceColumnAndCompetitor.getB()); + return trackedRace==null?null:trackedRace.getRankingMetric().getRankingInfo(timePoint, cache); + }) : null; Future future = executor.submit(() -> { - Entry entry = AbstractLeaderboardWithCache.this.getEntry(competitor, raceColumn, timePoint, discardedRaceColumns); - return getLeaderboardEntryDTO(entry, raceColumn, competitor, timePoint, - namesOfRaceColumnsForWhichToLoadLegDetails != null - && namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn - .getName()), waitForLatestAnalyses, legRanksCache, baseDomainFactory, - fillTotalPointsUncorrected, cache); - }); + Entry entry = AbstractLeaderboardWithCache.this.getEntry(competitor, raceColumn, timePoint, discardedRaceColumns); + return getLeaderboardEntryDTO(entry, raceColumn, competitor, timePoint, computeLegDetails, + rankingInfo, waitForLatestAnalyses, legRanksCache, baseDomainFactory, + fillTotalPointsUncorrected, cache); + }); futuresForColumnName.put(raceColumn.getName(), future); } for (Map.Entry> raceColumnNameAndFuture : futuresForColumnName.entrySet()) { @@ -609,6 +616,11 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { } /** + * @param rankingInfo + * must be provided when {@code addLegDetails} is {@code true}; it may, however, be the case that there + * is no {@link TrackedRace} for the {@code competitor} for which this entry shall be computed; in such + * cases it is permissible to pass {@code null} for this parameter despite {@code addLegDetails} being + * set. * @param waitForLatestAnalyses * if false, this method is allowed to read the maneuver analysis results from a cache that * may not reflect all data already received; otherwise, the method will always block for the latest @@ -621,9 +633,9 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { * the correction was removed. */ private LeaderboardEntryDTO getLeaderboardEntryDTO(Entry entry, RaceColumn raceColumn, Competitor competitor, - TimePoint timePoint, boolean addLegDetails, boolean waitForLatestAnalyses, - Map> legRanksCache, DomainFactory baseDomainFactory, - boolean fillTotalPointsUncorrected, WindLegTypeAndLegBearingCache cache) { + TimePoint timePoint, boolean addLegDetails, RankingInfo rankingInfo, + boolean waitForLatestAnalyses, Map> legRanksCache, + DomainFactory baseDomainFactory, boolean fillTotalPointsUncorrected, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { LeaderboardEntryDTO entryDTO = new LeaderboardEntryDTO(); TrackedRace trackedRace = raceColumn.getTrackedRace(competitor); entryDTO.race = trackedRace == null ? null : trackedRace.getRaceIdentifier(); @@ -670,7 +682,6 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { } if (addLegDetails && trackedRace != null) { try { - final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache); RaceDetails raceDetails = getRaceDetails(trackedRace, competitor, timePoint, waitForLatestAnalyses, legRanksCache, rankingInfo, cache); entryDTO.legDetails = raceDetails.getLegDetails(); @@ -848,7 +859,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { */ private RaceDetails getRaceDetails(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, Map> legRanksCache, - RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) throws InterruptedException, ExecutionException { + RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws InterruptedException, ExecutionException { final RaceDetails raceDetails; if (trackedRace.getEndOfTracking() != null && trackedRace.getEndOfTracking().compareTo(timePoint) < 0) { raceDetails = getRaceDetailsForEndOfTrackingFromCacheOrCalculateAndCache(trackedRace, competitor, legRanksCache, rankingInfo, cache); @@ -860,7 +871,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { private RaceDetails getRaceDetailsForEndOfTrackingFromCacheOrCalculateAndCache(final TrackedRace trackedRace, final Competitor competitor, final Map> legRanksCache, - RankingInfo rankingInfo, final WindLegTypeAndLegBearingCache cache) throws InterruptedException, ExecutionException { + RankingInfo rankingInfo, final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws InterruptedException, ExecutionException { final com.sap.sse.common.Util.Pair key = new com.sap.sse.common.Util.Pair(trackedRace, competitor); RunnableFuture raceDetails; final boolean needToRunRaceDetails; // when found in cache, another call to this method is already running it; else, it needs to be run here @@ -899,7 +910,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { private RaceDetails calculateRaceDetails(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, Map> legRanksCache, - WindLegTypeAndLegBearingCache cache, final RankingInfo rankingInfo) { + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache, final RankingInfo rankingInfo) { final List legDetails = new ArrayList(); final Course course = trackedRace.getRace().getCourse(); course.lockForRead(); // hold back any course re-configurations while looping over the legs @@ -939,7 +950,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { return new RaceDetails(legDetails, windwardDistanceToCompetitorFarthestAhead, averageAbsoluteCrossTrackError, averageSignedCrossTrackError, trackedRace.getRankingMetric().getGapToLeaderInOwnTime(rankingInfo, competitor, cache), trackedRace.getTimeSailedSinceRaceStart(competitor, timePoint), - trackedRace.getRankingMetric().getCorrectedTime(competitor, timePoint), + competitorRankingInfo == null ? null : competitorRankingInfo.getCorrectedTime(), competitorRankingInfo == null ? null : competitorRankingInfo.getCorrectedTimeAtEstimatedArrivalAtCompetitorFarthestAhead()); } finally { course.unlockAfterRead(); @@ -948,7 +959,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { private LegEntryDTO createLegEntry(TrackedLegOfCompetitor trackedLeg, TimePoint timePoint, boolean waitForLatestAnalyses, Map> legRanksCache, - RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { LegEntryDTO result; final Duration time = trackedLeg.getTime(timePoint); if (trackedLeg == null || time == null) { @@ -1147,7 +1158,7 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { return result; } - private Duration getGapAtEndOfPreviousLeg(TrackedLegOfCompetitor trackedLeg, final RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + private Duration getGapAtEndOfPreviousLeg(TrackedLegOfCompetitor trackedLeg, final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration result; final Course course = trackedLeg.getTrackedLeg().getTrackedRace().getRace().getCourse(); // if trackedLeg is the first leg, compute the gap at the start of this leg; otherwise, compute gap diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/ORCPerformanceCurveCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/ORCPerformanceCurveCache.java new file mode 100755 index 00000000000..d91f2cac8b0 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/ORCPerformanceCurveCache.java @@ -0,0 +1,29 @@ +package com.sap.sailing.domain.orc; + +import java.util.function.Function; +import java.util.function.Supplier; + +import com.sap.sailing.domain.base.Competitor; +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; +import com.sap.sailing.domain.tracking.TrackedLeg; +import com.sap.sse.common.Speed; + +public interface ORCPerformanceCurveCache { + /** + * 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 + * type {@link ORCPerformanceCurveLegImpl} of type {@link ORCPerformanceCurveLegTypes#TWA} with its TWA and + * distance set to the values obtained for this cache's time point, computed once when this call is made + * and no total course has been cached in this object yet. + */ + ORCPerformanceCurveCourse getTotalCourse(Supplier totalCourseSupplier); + + Competitor getScratchBoat(Supplier scratchBoatSupplier); + + ORCPerformanceCurve getPerformanceCurveForPartialCourse(Competitor competitor, Function performanceCurveSupplier); + + Speed getImpliedWind(Competitor competitor, Function impliedWindSupplier); + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveByImpliedWindRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveByImpliedWindRankingMetric.java index 1ae9cc8c5c7..f349bcb689b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveByImpliedWindRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveByImpliedWindRankingMetric.java @@ -6,6 +6,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; @@ -45,7 +46,7 @@ import com.sap.sailing.domain.ranking.AbstractRankingMetric; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; import com.sap.sse.common.Distance; @@ -96,7 +97,7 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki * Uses the {@link ORCPerformanceCurveRankingMetric#getScratchBoat(TimePoint) scratch boat} as the "boat * farthest ahead." The default scratch boat is defined as such but may be overridden explicitly. */ - public ORCPerformanceCurveRankingInfo(TimePoint timePoint, Map competitorRankingInfo, WindLegTypeAndLegBearingCache cache) { + public ORCPerformanceCurveRankingInfo(TimePoint timePoint, Map competitorRankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { super(timePoint, competitorRankingInfo, getScratchBoat(timePoint, cache)); } } @@ -105,8 +106,6 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki super(trackedRace); boatsById = initBoatsById(); competitorsById = initCompetitorsById(); - updateCertificatesFromLogs(); - updateCourseFromRaceLogs(); certificatesFromRaceLogUpdater = createCertificatesFromRaceLogAndCourseUpdater(); certificatesFromRegattaLogUpdater = createCertificatesFromRegattaLogUpdater(); if (trackedRace != null) { @@ -143,6 +142,8 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki } }); } + updateCertificatesFromLogs(); + updateCourseFromRaceLogs(); } public ORCCertificate getCertificate(Boat boat) { @@ -260,14 +261,14 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki return totalCourse; } - private ORCPerformanceCurveCourse getPartialCourse(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private ORCPerformanceCurveCourse getPartialCourse(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final ORCPerformanceCurveCourse result; final Leg firstLeg = getTrackedRace().getRace().getCourse().getFirstLeg(); final TrackedLegOfCompetitor trackedLegOfCompetitor = getTrackedRace().getTrackedLeg(competitor, timePoint); if (trackedLegOfCompetitor == null) { if (getTrackedRace().getTrackedLeg(competitor, firstLeg).hasStartedLeg(timePoint)) { // then we know the competitor has finished the race at timePoint - result = getTotalCourse(); + result = cache.getTotalCourse(()->getTotalCourse()); } else { // not started the race yet; return empty course result = getTotalCourse().subcourse(0, 0); @@ -294,9 +295,9 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki * {@link RaceLogORCScratchBoatEvent} in the {@link RaceLog}. The last unrevoked event in the first {@link RaceLog} * in which one is found is used. Only if none of the attached {@link RaceLog}s contains any unrevoked such event, * the scratch boat is selected implicitly to be the boat farthest ahead (see - * {@link #getCompetitorFarthestAhead(TimePoint, WindLegTypeAndLegBearingCache)}). + * {@link #getCompetitorFarthestAhead(TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache)}). */ - private Competitor getScratchBoat(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private Competitor getScratchBoat(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Competitor result; if (explicitScratchBoat != null) { result = explicitScratchBoat; @@ -311,28 +312,21 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki * on those values. */ @Override - public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map impliedWindByCompetitor = getImpliedWindByCompetitor(timePoint, cache); return (c1, c2)->Comparator.nullsLast((Speed impliedWindSpeed1, Speed impliedWindSpeed2)->impliedWindSpeed2.compareTo(impliedWindSpeed1)). compare(impliedWindByCompetitor.get(c1), impliedWindByCompetitor.get(c2)); } - private Map getImpliedWindByCompetitor(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private Map getImpliedWindByCompetitor(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map impliedWindByCompetitor = new HashMap<>(); for (final Competitor competitor : getTrackedRace().getRace().getCompetitors()) { - try { - impliedWindByCompetitor.put(competitor, getImpliedWind(competitor, timePoint, cache)); - } catch (MaxIterationsExceededException | FunctionEvaluationException e) { - // log and leave entry for competitor empty; this, together with a nullsLast comparator - // will sort such competitors towards "worse" ranks - logger.log(Level.WARNING, "Problem trying to determine ORC PCS implied wind for competitor " - + competitor + " for time point " + timePoint, e); - } + impliedWindByCompetitor.put(competitor, cache.getImpliedWind(competitor, getImpliedWindSupplier(timePoint, cache))); } return impliedWindByCompetitor; } - protected ORCPerformanceCurve getPerformanceCurveForPartialCourse(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) throws FunctionEvaluationException { + protected ORCPerformanceCurve getPerformanceCurveForPartialCourse(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws FunctionEvaluationException { final ORCPerformanceCurveCourse competitorsPartialCourseAtTimePoint = getPartialCourse(competitor, timePoint, cache); final ORCPerformanceCurve performanceCurveForPartialCourse; if (competitorsPartialCourseAtTimePoint.getTotalLength().equals(Distance.NULL)) { @@ -349,9 +343,9 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki return performanceCurveForPartialCourse; } - protected Speed getImpliedWind(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) throws FunctionEvaluationException, MaxIterationsExceededException { + protected Speed getImpliedWind(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws FunctionEvaluationException, MaxIterationsExceededException { final Speed result; - final ORCPerformanceCurve performanceCurveForPartialCourse = getPerformanceCurveForPartialCourse(competitor, timePoint, cache); + final ORCPerformanceCurve performanceCurveForPartialCourse = cache.getPerformanceCurveForPartialCourse(competitor, getPerformanceCurveSupplier(timePoint, cache)); if (performanceCurveForPartialCourse != null) { final Duration timeSailedSinceRaceStart = getTrackedRace().getTimeSailedSinceRaceStart(competitor, timePoint); if (timeSailedSinceRaceStart != null) { @@ -379,23 +373,26 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki */ @Override public Comparator getLegRankingComparator(TrackedLeg trackedLeg, TimePoint timePoint, - WindLegTypeAndLegBearingCache cache) { + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map impliedWindByCompetitor = new HashMap<>(); for (final Competitor competitor : getTrackedRace().getRace().getCompetitors()) { - final TimePoint timePointForImpliedWind; + Speed impliedWind; if (trackedLeg.getTrackedLeg(competitor).hasFinishedLeg(timePoint)) { - timePointForImpliedWind = trackedLeg.getTrackedLeg(competitor).getFinishTime(); + // dedicated time point at leg end; cannot use implied wind from cache + try { + impliedWind = getImpliedWind(competitor, trackedLeg.getTrackedLeg(competitor).getFinishTime(), cache); + } catch (MaxIterationsExceededException | FunctionEvaluationException e) { + // log and leave entry for competitor empty; this, together with a nullsLast comparator + // will sort such competitors towards "worse" ranks + logger.log(Level.WARNING, "Problem trying to determine ORC PCS implied wind for competitor " + + competitor + " for time point " + timePoint, e); + impliedWind = null; + } } else { - timePointForImpliedWind = timePoint; - } - try { - impliedWindByCompetitor.put(competitor, getImpliedWind(competitor, timePointForImpliedWind, cache)); - } catch (MaxIterationsExceededException | FunctionEvaluationException e) { - // log and leave entry for competitor empty; this, together with a nullsLast comparator - // will sort such competitors towards "worse" ranks - logger.log(Level.WARNING, "Problem trying to determine ORC PCS implied wind for competitor " - + competitor + " for time point " + timePoint, e); + // can use cache; we shall compute for the cache's timePoint: + impliedWind = cache.getImpliedWind(competitor, getImpliedWindSupplier(timePoint, cache)); } + impliedWindByCompetitor.put(competitor, impliedWind); } return (tloc1, tloc2)->{ final int result; @@ -428,37 +425,25 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki } @Override - public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Duration result = null; - final Competitor scratchBoat = getScratchBoat(timePoint, cache); + final Competitor scratchBoat = cache.getScratchBoat(()->getScratchBoat(timePoint, cache)); if (competitor == scratchBoat) { // the scratch boat's corrected time is its own time sailed result = getTrackedRace().getTimeSailedSinceRaceStart(competitor, timePoint); } else { + final Function performanceCurveSupplier = getPerformanceCurveSupplier(timePoint, cache); ORCPerformanceCurve scratchBoatPerformanceCurve; - // these try-catch clauses seem a bit clumsy, but we'd like to log differently, depending on - // where the FunctionEvaluationException is thrown - try { - scratchBoatPerformanceCurve = getPerformanceCurveForPartialCourse(scratchBoat, timePoint, cache); - } catch (FunctionEvaluationException e) { - logger.log(Level.WARNING, "Problem evaluating performance curve function for scratch boat "+scratchBoat, e); - scratchBoatPerformanceCurve = null; - } + scratchBoatPerformanceCurve = cache.getPerformanceCurveForPartialCourse(scratchBoat, performanceCurveSupplier); if (scratchBoatPerformanceCurve != null) { - ORCPerformanceCurve competitorPerformanceCurve; - try { - competitorPerformanceCurve = getPerformanceCurveForPartialCourse(competitor, timePoint, cache); - } catch (FunctionEvaluationException e) { - logger.log(Level.WARNING, "Problem evaluating performance curve function for competitor "+competitor, e); - competitorPerformanceCurve = null; - } - final Duration competitorTimeSinceRaceStart = getTrackedRace().getTimeSailedSinceRaceStart(competitor, timePoint); + ORCPerformanceCurve competitorPerformanceCurve = cache.getPerformanceCurveForPartialCourse(competitor, performanceCurveSupplier); + final Duration competitorElapsedTimeSinceRaceStart = getTrackedRace().getTimeSailedSinceRaceStart(competitor, timePoint); Speed competitorImpliedWind; try { - competitorImpliedWind = competitorPerformanceCurve.getImpliedWind(competitorTimeSinceRaceStart); + competitorImpliedWind = competitorPerformanceCurve.getImpliedWind(competitorElapsedTimeSinceRaceStart); } catch (MaxIterationsExceededException | FunctionEvaluationException e) { logger.log(Level.WARNING, "Problem evaluating performance curve function for competitor " + competitor - + " for duration " + competitorTimeSinceRaceStart, e); + + " for duration " + competitorElapsedTimeSinceRaceStart, e); logger.fine("The performance curve was: "+competitorPerformanceCurve); competitorImpliedWind = null; } @@ -476,6 +461,30 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki return result; } + protected Function getImpliedWindSupplier(TimePoint timePoint, + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { + return c->{ + try { + return getImpliedWind(c, timePoint, cache); + } catch (MaxIterationsExceededException | FunctionEvaluationException e) { + logger.log(Level.WARNING, "Problem evaluating performance curve", e); + return null; + } + }; + } + + protected Function getPerformanceCurveSupplier(TimePoint timePoint, + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { + return theCompetitor->{ + try { + return getPerformanceCurveForPartialCourse(theCompetitor, timePoint, cache); + } catch (FunctionEvaluationException e) { + logger.log(Level.WARNING, "Problem evaluating performance curve function for "+theCompetitor, e); + return null; + } + }; + } + @Override protected Duration getCalculatedTime(Competitor who, Supplier leg, Supplier estimatedPosition, Duration totalDurationSinceRaceStart, Distance totalWindwardDistanceTraveled) { @@ -490,7 +499,7 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki } @Override - public ORCPerformanceCurveRankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public ORCPerformanceCurveRankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map competitorRankingInfo = new HashMap<>(); final TimePoint startOfRace = getTrackedRace().getStartOfRace(); if (startOfRace != null) { @@ -513,7 +522,7 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki * the time difference is to the boat leading in the race by implied wind. */ @Override - public Duration getGapToLeaderInOwnTime(RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingCache cache) { + public Duration getGapToLeaderInOwnTime(RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { assert rankingInfo instanceof ORCPerformanceCurveRankingInfo; Duration result; final TimePoint startOfRace = getTrackedRace().getStartOfRace(); @@ -521,15 +530,15 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki final Duration actualRaceDuration = startOfRace.until(rankingInfo.getTimePoint()); final Competitor leader = rankingInfo.getLeaderByCorrectedEstimatedTimeToCompetitorFarthestAhead(); try { - final ORCPerformanceCurve competitorPerformanceCurve = getPerformanceCurveForPartialCourse(competitor, rankingInfo.getTimePoint(), cache); + final ORCPerformanceCurve competitorPerformanceCurve = cache.getPerformanceCurveForPartialCourse(competitor, getPerformanceCurveSupplier(rankingInfo.getTimePoint(), cache)); if (competitorPerformanceCurve == null) { result = null; } else { - final Speed impliedWindOfLeader = getImpliedWind(leader, rankingInfo.getTimePoint(), cache); + final Speed impliedWindOfLeader = cache.getImpliedWind(leader, getImpliedWindSupplier(rankingInfo.getTimePoint(), cache)); final Duration allowanceForLeaderInCompetitorsPerformanceCurve = competitorPerformanceCurve.getAllowancePerCourse(impliedWindOfLeader); result = actualRaceDuration.minus(allowanceForLeaderInCompetitorsPerformanceCurve); } - } catch (FunctionEvaluationException | MaxIterationsExceededException e) { + } catch (FunctionEvaluationException e) { logger.log(Level.WARNING, "Problem evaluating performance curve for competitor "+competitor+" for time point "+rankingInfo.getTimePoint(), e); result = null; } @@ -541,7 +550,7 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki @Override public Duration getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint, - RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { assert rankingInfo instanceof ORCPerformanceCurveRankingInfo; Duration result; final TimePoint startOfRace = getTrackedRace().getStartOfRace(); @@ -582,7 +591,7 @@ public class ORCPerformanceCurveByImpliedWindRankingMetric extends AbstractRanki } private TimePoint nowOrLegFinishTimeIfFinishedAtTimePoint(TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint, - WindLegTypeAndLegBearingCache cache) throws FunctionEvaluationException { + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws FunctionEvaluationException { final TimePoint timeForImpliedWindCalculation; if (trackedLegOfCompetitor.hasFinishedLeg(timePoint)) { timeForImpliedWindCalculation = trackedLegOfCompetitor.getFinishTime(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveRankingMetric.java index 5147d1aae08..4b51b85bc2b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCPerformanceCurveRankingMetric.java @@ -6,16 +6,16 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.math.FunctionEvaluationException; -import org.apache.commons.math.MaxIterationsExceededException; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.orc.ORCPerformanceCurve; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Duration; import com.sap.sse.common.Speed; import com.sap.sse.common.TimePoint; @@ -47,13 +47,13 @@ public class ORCPerformanceCurveRankingMetric extends ORCPerformanceCurveByImpli * time. */ @Override - public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map correctedTimesByCompetitor = getCorrectedTimesByCompetitor(timePoint, cache); return (c1, c2)->Comparator.nullsLast((Duration correctedTime1, Duration correctedTime2)->correctedTime1.compareTo(correctedTime2)). compare(correctedTimesByCompetitor.get(c1), correctedTimesByCompetitor.get(c2)); } - private Map getCorrectedTimesByCompetitor(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private Map getCorrectedTimesByCompetitor(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map correctedTimesByCompetitor = new HashMap<>(); for (final Competitor competitor : getTrackedRace().getRace().getCompetitors()) { correctedTimesByCompetitor.put(competitor, getCorrectedTime(competitor, timePoint, cache)); @@ -71,7 +71,7 @@ public class ORCPerformanceCurveRankingMetric extends ORCPerformanceCurveByImpli * racing at {@code timePoint}. */ @Override - public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Duration result; final Comparator comparatorByImpliedWind = super.getRaceRankingComparator(timePoint, cache); final Set competitors = new HashSet<>(); @@ -79,9 +79,10 @@ public class ORCPerformanceCurveRankingMetric extends ORCPerformanceCurveByImpli final Competitor leader = Collections.min(competitors, comparatorByImpliedWind); // use minimum because the comparator sorts "better" first if (leader != null) { try { - final ORCPerformanceCurve competitorPerformanceCurve = getPerformanceCurveForPartialCourse(competitor, timePoint, cache); - final Speed leaderImpliedWind = getImpliedWind(leader, timePoint, cache); - if (leaderImpliedWind != null) { + final Function performanceCurveSupplier = getPerformanceCurveSupplier(timePoint, cache); + final ORCPerformanceCurve competitorPerformanceCurve = cache.getPerformanceCurveForPartialCourse(competitor, performanceCurveSupplier); + final Speed leaderImpliedWind = cache.getImpliedWind(leader, getImpliedWindSupplier(timePoint, cache)); + if (leaderImpliedWind != null && competitorPerformanceCurve != null) { final Duration competitorAllowance = competitorPerformanceCurve.getAllowancePerCourse(leaderImpliedWind); final Duration competitorElapsedTime = getTrackedRace().getTimeSailedSinceRaceStart(competitor, timePoint); final Duration leaderElapsedTime = getTrackedRace().getTimeSailedSinceRaceStart(leader, timePoint); @@ -94,7 +95,7 @@ public class ORCPerformanceCurveRankingMetric extends ORCPerformanceCurveByImpli } else { result = null; } - } catch (FunctionEvaluationException | MaxIterationsExceededException e) { + } catch (FunctionEvaluationException e) { logger.log(Level.WARNING, "Problem evaluating performance curve", e); result = null; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java index d1809cd4384..cefe99dcfb6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/AbstractRankingMetric.java @@ -23,7 +23,7 @@ import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.impl.AbstractRaceRankComparator; import com.sap.sse.common.Distance; @@ -145,7 +145,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { private final TimePoint timePoint; /** - * Caches, on demand, the results of calls to {@link #getCompetitorFarthestAheadInLeg(Leg, TimePoint, WindLegTypeAndLegBearingCache)}. + * Caches, on demand, the results of calls to {@link #getCompetitorFarthestAheadInLeg(Leg, TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache)}. * null values are encoded as the {@link #NULL_COMPETITOR} and must be translated back to null before returning * to a caller outside of this class. */ @@ -162,7 +162,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { } @Override - public Competitor getCompetitorFarthestAheadInLeg(Leg leg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getCompetitorFarthestAheadInLeg(Leg leg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Competitor result = competitorFarthestAheadInLeg.get(leg); if (result == NULL_COMPETITOR) { result = null; @@ -220,7 +220,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { } @Override - public Competitor getLeaderInLegByCalculatedTime(Leg leg, WindLegTypeAndLegBearingCache cache) { + public Competitor getLeaderInLegByCalculatedTime(Leg leg, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TrackedLeg trackedLeg = getTrackedRace().getTrackedLeg(leg); return trackedLeg.getLeader(getTimePoint(), cache); } @@ -236,7 +236,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { return trackedRace; } - protected Competitor getCompetitorFarthestAhead(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + protected Competitor getCompetitorFarthestAhead(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Comparator oneDesignComparator = getWindwardDistanceTraveledComparator(timePoint, cache); Competitor competitorFarthestAhead = StreamSupport .stream(getCompetitors().spliterator(), /* parallel */true). @@ -339,7 +339,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * result is undefined. */ protected Duration getPredictedDurationToEndOfLegOrTo(TimePoint timePoint, final TrackedLegOfCompetitor legWho, final TrackedLegOfCompetitor legTo, - WindLegTypeAndLegBearingCache cache) { + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { assert isAssumedToHaveStartedLeg(timePoint, legWho) || isAssumedToHaveFinishedLeg(timePoint, legWho); assert isAssumedToHaveStartedLeg(timePoint, legTo) || isAssumedToHaveFinishedLeg(timePoint, legTo); final Duration toEndOfLegOrTo; @@ -364,7 +364,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { } private Duration getDurationToReach(final Position windwardPositionToReachInWhosCurrentLeg, TimePoint timePoint, - final TrackedLegOfCompetitor whosLeg, WindLegTypeAndLegBearingCache cache) { + final TrackedLegOfCompetitor whosLeg, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration toEndOfLegOrTo; final Speed averageVMG = whosLeg.getAverageVelocityMadeGood(timePoint, cache); final Speed vmg = averageVMG == null || Double.isNaN(averageVMG.getKnots()) ? @@ -398,17 +398,17 @@ public abstract class AbstractRankingMetric implements RankingMetric { * time point for wind approximation is taken to be a reference time point selected based on the mark passings * for the respective leg's from/to waypoints. */ - protected Distance getWindwardDistanceTraveled(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + protected Distance getWindwardDistanceTraveled(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getWindwardDistanceTraveled(competitor, getTrackedRace().getRace().getCourse().getFirstWaypoint(), timePoint, cache); } /** * Constructs a comparator based on the results of - * {@link #getWindwardDistanceTraveled(Competitor, TimePoint, WindLegTypeAndLegBearingCache)} where competitors are + * {@link #getWindwardDistanceTraveled(Competitor, TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache)} where competitors are * "less" than other competitors ("better") if they are in a later leg or, if in the same leg, have a greater * windward distance traveled. If both competitors have already finished the race, the finishing time is compared. */ - private Comparator getWindwardDistanceTraveledComparator(final TimePoint timePoint, final WindLegTypeAndLegBearingCache cache) { + private Comparator getWindwardDistanceTraveledComparator(final TimePoint timePoint, final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Map windwardDistanceTraveledPerCompetitor = new HashMap<>(); for (final Competitor competitor : getCompetitors()) { windwardDistanceTraveledPerCompetitor.put(competitor, getWindwardDistanceTraveled(competitor, timePoint, cache)); @@ -434,7 +434,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * time point for wind approximation is taken to be a reference time point selected based on the mark passings * for the respective leg's from/to waypoints. */ - protected Distance getWindwardDistanceTraveled(Competitor competitor, Waypoint from, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + protected Distance getWindwardDistanceTraveled(Competitor competitor, Waypoint from, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Distance result; if (from == null) { result = null; @@ -545,7 +545,7 @@ public abstract class AbstractRankingMetric implements RankingMetric { * has already finished the leg at timePoint; or the competitor with the greatest windward * distance traveled in the leg at timePoint otherwise */ - protected Competitor getCompetitorFarthestAheadInLeg(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + protected Competitor getCompetitorFarthestAheadInLeg(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Competitor firstAroundMark = getFirstLegFinisherBefore(trackedLeg, timePoint); final Competitor result; if (firstAroundMark != null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/NonPerformanceCurveRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/NonPerformanceCurveRankingMetric.java index 7ff1242d5c2..f99ad4018c4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/NonPerformanceCurveRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/NonPerformanceCurveRankingMetric.java @@ -11,7 +11,7 @@ import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -20,7 +20,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe private static final long serialVersionUID = 2647817114244817444L; public interface NonPerformanceCurveRankingInfo extends RankingInfoWithLegLeader { - Duration getActualTimeFromRaceStartToReachFarthestAheadInLeg(Competitor competitor, Leg leg, WindLegTypeAndLegBearingCache cache); + Duration getActualTimeFromRaceStartToReachFarthestAheadInLeg(Competitor competitor, Leg leg, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } public class NonPerformanceCurveRankingInfoImpl extends AbstractRankingInfoWithCompetitorRankingInfoCache implements NonPerformanceCurveRankingInfo { @@ -31,7 +31,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe } @Override - public Duration getActualTimeFromRaceStartToReachFarthestAheadInLeg(Competitor competitor, Leg leg, WindLegTypeAndLegBearingCache cache) { + public Duration getActualTimeFromRaceStartToReachFarthestAheadInLeg(Competitor competitor, Leg leg, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration result; final TrackedLegOfCompetitor tloc = getTrackedRace().getTrackedLeg(competitor, getTimePoint()); final Duration raceDurationAtTimePoint = getTrackedRace().getStartOfRace().until(getTimePoint()); @@ -57,7 +57,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe super(trackedRace); } - public RankingMetric.RankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public RankingMetric.RankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Map result = new HashMap<>(); Competitor competitorFarthestAhead = getCompetitorFarthestAhead(timePoint, cache); final Distance totalWindwardDistanceTraveled = getWindwardDistanceTraveled(competitorFarthestAhead, timePoint, cache); @@ -124,7 +124,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe * * @return null, if either of the two competitors' current legs is null */ - protected Duration getPredictedDurationToReachWindwardPositionOf(Competitor who, Competitor to, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + protected Duration getPredictedDurationToReachWindwardPositionOf(Competitor who, Competitor to, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TrackedLegOfCompetitor currentLegWho = getCurrentLegOrLastLegIfAlreadyFinished(who, timePoint); final TrackedLegOfCompetitor currentLegTo = getCurrentLegOrLastLegIfAlreadyFinished(to, timePoint); final Duration result = getPredictedDurationToReachWindwardPositionOf(currentLegWho, currentLegTo, timePoint, cache); @@ -133,7 +133,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe /** * Similar to - * {@link #getPredictedDurationToReachWindwardPositionOf(Competitor, Competitor, TimePoint, WindLegTypeAndLegBearingCache)}, + * {@link #getPredictedDurationToReachWindwardPositionOf(Competitor, Competitor, TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache)}, * allowing the caller to specify the legs to consider for the two competitors. This way, the "to" competitor's * leg may be set to one that is not necessarily the current leg at timePoint, enabling a comparison * for a specific leg. @@ -146,7 +146,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe * Precondition: legWho's leg is the same as or an earlier leg than legTo's leg. */ protected Duration getPredictedDurationToReachWindwardPositionOf(final TrackedLegOfCompetitor legWho, final TrackedLegOfCompetitor legTo, - TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { assert legWho == null || legTo == null || getTrackedRace().getRace().getCourse().getIndexOfWaypoint(legWho.getTrackedLeg().getLeg().getFrom()) <= getTrackedRace().getRace().getCourse().getIndexOfWaypoint(legTo.getTrackedLeg().getLeg().getFrom()); @@ -202,7 +202,7 @@ public abstract class NonPerformanceCurveRankingMetric extends AbstractRankingMe * {@link #validateGetDurationToReachAtEqualPerformanceParameters(Competitor, Waypoint, TimePoint, MarkPassing)}. */ protected abstract Duration getDurationToReachAtEqualPerformance(Competitor who, Competitor to, Waypoint fromWaypoint, - TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingCache cache); + TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); protected Comparator getComparatorByEstimatedCorrectedTimeWhenReachingCompetitorFarthestAhead( final Function rankingInfos) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/OneDesignRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/OneDesignRankingMetric.java index f10edf2418b..dfccf8cbe48 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/OneDesignRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/OneDesignRankingMetric.java @@ -12,7 +12,7 @@ import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.impl.RaceRankComparator; import com.sap.sailing.domain.tracking.impl.WindwardToGoComparator; @@ -28,18 +28,18 @@ public class OneDesignRankingMetric extends NonPerformanceCurveRankingMetric { } @Override - public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return new RaceRankComparator(getTrackedRace(), timePoint, cache); } @Override public Comparator getLegRankingComparator(TrackedLeg trackedLeg, - TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return new WindwardToGoComparator(trackedLeg, timePoint, cache); } @Override - public Duration getGapToLeaderInOwnTime(RankingMetric.RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingCache cache) { + public Duration getGapToLeaderInOwnTime(RankingMetric.RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { // When the competitor is in the same leg as the leader (which in this ranking metric is always the boat // farthest ahead) then the competitor's duration to reach the current leader's position is estimated based on the // competitor's average VMG on the current leg. @@ -107,7 +107,7 @@ public class OneDesignRankingMetric extends NonPerformanceCurveRankingMetric { } @Override - public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getActualTimeSinceStartOfRace(competitor, timePoint); } @@ -116,7 +116,7 @@ public class OneDesignRankingMetric extends NonPerformanceCurveRankingMetric { * reach her current position since passing fromWaypoint. */ @Override - protected Duration getDurationToReachAtEqualPerformance(Competitor who, Competitor to, Waypoint fromWaypoint, TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingCache cache) { + protected Duration getDurationToReachAtEqualPerformance(Competitor who, Competitor to, Waypoint fromWaypoint, TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final MarkPassing whenToPassedFromWaypoint = getTrackedRace().getMarkPassing(to, fromWaypoint); validateGetDurationToReachAtEqualPerformanceParameters(to, fromWaypoint, timePointOfTosPosition, whenToPassedFromWaypoint); return whenToPassedFromWaypoint.getTimePoint().until(timePointOfTosPosition); @@ -130,12 +130,12 @@ public class OneDesignRankingMetric extends NonPerformanceCurveRankingMetric { @Override public Duration getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint, - final RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return trackedLegOfCompetitor.getGapToLeader(timePoint, WindPositionMode.LEG_MIDDLE, rankingInfo, cache); } @Override - public RankingInfo getRankingInfo(final TimePoint timePoint, final WindLegTypeAndLegBearingCache cache) { + public RankingInfo getRankingInfo(final TimePoint timePoint, final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return new AbstractRankingInfo(timePoint) { private static final long serialVersionUID = 25689357311324825L; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/RankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/RankingMetric.java index c62b8a0a380..dba383cadc8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/RankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/RankingMetric.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuse import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -114,7 +114,7 @@ public interface RankingMetric extends Serializable { */ Competitor getLeaderByCorrectedEstimatedTimeToCompetitorFarthestAhead(); - Competitor getCompetitorFarthestAheadInLeg(Leg leg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Competitor getCompetitorFarthestAheadInLeg(Leg leg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } public interface RankingInfoWithLegLeader extends RankingInfo { @@ -126,7 +126,7 @@ public interface RankingMetric extends Serializable { * is normalized to the {@link TrackedLeg#getWindwardDistance() windward distance of the leg} at the * {@link TrackedLeg#getReferenceTimePoint() reference time point}. */ - Competitor getLeaderInLegByCalculatedTime(Leg leg, WindLegTypeAndLegBearingCache cache); + Competitor getLeaderInLegByCalculatedTime(Leg leg, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } public interface LegRankingInfo extends Timed, Serializable { @@ -146,9 +146,9 @@ public interface RankingMetric extends Serializable { return getRaceRankingComparator(timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); } - Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); - Comparator getLegRankingComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Comparator getLegRankingComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Determine the time sailed for the {@code competitor} at {@code timePoint} in this race. This ignores whether or not @@ -182,7 +182,7 @@ public interface RankingMetric extends Serializable { * Same as {@link #getCorrectedTime(Competitor, TimePoint)}, but allowing the caller to pass a cache that * accelerates some calculations. */ - Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Determines in competitor's own time how much time earlier she would have had to be where she is at @@ -193,17 +193,17 @@ public interface RankingMetric extends Serializable { * * @param rankingInfo * the pre-calculated ranking info for all competitors for a certain time point, as returned by - * {@link AbstractRankingMetric#getRankingInfo(TimePoint, WindLegTypeAndLegBearingCache)} + * {@link AbstractRankingMetric#getRankingInfo(TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache)} * @param competitor * the competitor for which to tell the gap to the leader in competitor's own time * - * @see #getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor, TimePoint, com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo.RankingInfo, WindLegTypeAndLegBearingCache) + * @see #getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor, TimePoint, com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo.RankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache) */ default Duration getGapToLeaderInOwnTime(RankingInfo rankingInfo, Competitor competitor) { return getGapToLeaderInOwnTime(rankingInfo, competitor, new LeaderboardDTOCalculationReuseCache(rankingInfo.getTimePoint())); } - default Duration getGapToLeaderInOwnTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + default Duration getGapToLeaderInOwnTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getGapToLeaderInOwnTime(getRankingInfo(timePoint, cache), competitor, cache); } @@ -215,9 +215,9 @@ public interface RankingMetric extends Serializable { return getRankingInfo(timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); } - RankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + RankingInfo getRankingInfo(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); - Duration getGapToLeaderInOwnTime(RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingCache cache); + Duration getGapToLeaderInOwnTime(RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Computes the competitor's gap in own time to the leader (or best leg finisher, in corrected time if @@ -229,5 +229,5 @@ public interface RankingMetric extends Serializable { * tells about leader (by calculated time) and boat farthest ahead */ Duration getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint, - RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java index 2e6a99796a9..386baa3c062 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java @@ -15,7 +15,7 @@ import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -89,7 +89,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki * along-course distance of the {@link #getTrackedRace() race's} course. */ @Override - public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Comparator getRaceRankingComparator(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final RankingMetric.RankingInfo rankingInfo = getRankingInfo(timePoint, cache); final Comparator durationComparatorNullsLast = Comparator.nullsLast(Comparator.naturalOrder()); return (c1, c2) -> { @@ -103,7 +103,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki } @Override - public Comparator getLegRankingComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Comparator getLegRankingComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { // competitors that have not yet started the leg will get a duration based on Long.MAX_VALUE final Map correctedTimesToReachFastestBoatsPositionAtTimePointOrEndOfLegMeasuredFromStartOfRace = new HashMap<>(); final Competitor fastestCompetitorInLeg = getCompetitorFarthestAheadInLeg(trackedLeg, timePoint, cache); @@ -170,7 +170,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki } @Override - public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Duration getCorrectedTime(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration timeActuallySpent = getActualTimeSinceStartOfRace(competitor, timePoint); final Distance windwardDistanceSailed = getWindwardDistanceTraveled(competitor, timePoint, cache); return getCalculatedTime(competitor, ()->getTrackedRace().getCurrentLeg(competitor, timePoint).getLeg(), @@ -205,7 +205,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki * that of to. */ @Override - protected Duration getDurationToReachAtEqualPerformance(Competitor who, Competitor to, Waypoint fromWaypoint, TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingCache cache) { + protected Duration getDurationToReachAtEqualPerformance(Competitor who, Competitor to, Waypoint fromWaypoint, TimePoint timePointOfTosPosition, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final MarkPassing whenToPassedFromWaypoint = getTrackedRace().getMarkPassing(to, fromWaypoint); final Duration t_who; if (whenToPassedFromWaypoint == null) { @@ -266,7 +266,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki * */ @Override - public Duration getGapToLeaderInOwnTime(RankingMetric.RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingCache cache) { + public Duration getGapToLeaderInOwnTime(RankingMetric.RankingInfo rankingInfo, Competitor competitor, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration result; // actual times and common distance: final Competitor leaderByCorrectedEstimatedTimeToCompetitorFarthestAhead = rankingInfo.getLeaderByCorrectedEstimatedTimeToCompetitorFarthestAhead(); @@ -339,7 +339,7 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki @Override public Duration getLegGapToLegLeaderInOwnTime(TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint, - RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { assert rankingInfo instanceof NonPerformanceCurveRankingInfo; final NonPerformanceCurveRankingInfo npcRankingInfo = (NonPerformanceCurveRankingInfo) rankingInfo; final Duration result; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DummyTrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DummyTrackedRace.java index fa9214b9e98..5f275c63cf9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DummyTrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/DummyTrackedRace.java @@ -395,7 +395,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { @Override public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -407,7 +407,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { @Override public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -607,17 +607,17 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -702,7 +702,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { @Override public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java index 380767c32f4..2c88ccd538b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java @@ -51,7 +51,7 @@ public interface TrackedLeg extends Serializable { * and bearing data can be passed to avoid redundant calculations during a single * round trip. */ - LinkedHashMap getRanks(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + LinkedHashMap getRanks(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); Bearing getLegBearing(TimePoint at); @@ -115,14 +115,14 @@ public interface TrackedLeg extends Serializable { * for leg types, wind data and leg bearings can be passed to save the effort of redundant calculations of these * values. */ - Distance getAbsoluteWindwardDistance(Position pos1, Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache); + Distance getAbsoluteWindwardDistance(Position pos1, Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Same as {@link #getWindwardDistance(Position, Position, TimePoint, WindPositionMode)}, only that a cache * for leg types, wind data and leg bearings can be passed to save the effort of redundant calculations of these * values. */ - Distance getWindwardDistance(final Position pos1, final Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistance(final Position pos1, final Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Same as {@link #getAbsoluteWindwardDistance(Position, Position, TimePoint, WindPositionMode)}, but this method considers the leg's @@ -136,9 +136,9 @@ public interface TrackedLeg extends Serializable { * that competitors need to travel in this leg. Due to the dynamics of the wind direction and the mark positions, * the result is time dependent. The wind direction is determined at the leg's middle at the time point at. */ - Distance getWindwardDistance(TimePoint at, WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistance(TimePoint at, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); - Distance getAbsoluteWindwardDistance(TimePoint at, WindLegTypeAndLegBearingCache cache); + Distance getAbsoluteWindwardDistance(TimePoint at, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Computes the windward distance for upwind/downwind legs or the great circle distance between this leg's waypoints @@ -146,16 +146,16 @@ public interface TrackedLeg extends Serializable { * the result is time dependent. As time point, the middle of the interval defined by the first mark passing starting the * leg and the last mark passing finishing the leg is used, where both time points default to "now." * - * @see #getWindwardDistance(TimePoint, WindLegTypeAndLegBearingCache) + * @see #getWindwardDistance(TimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache) */ Distance getWindwardDistance(); /** * Same as {@link #getWindwardDistance()}, but offering the client to use a cache */ - Distance getWindwardDistance(WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistance(WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); - Distance getAbsoluteWindwardDistance(WindLegTypeAndLegBearingCache cache); + Distance getAbsoluteWindwardDistance(WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * The middle (traveling half the length) of the course middle line, connecting the center of gravity of the leg's start @@ -183,9 +183,9 @@ public interface TrackedLeg extends Serializable { /** * Same as {@link #getAbsoluteWindwardDistanceFromLegStart(Position)}, offering the caller to pass in a cache */ - Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingCache cache); + Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); - Distance getWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Determines an average true wind direction for this leg; it does so by querying the tracked race for @@ -208,5 +208,5 @@ public interface TrackedLeg extends Serializable { */ Competitor getLeader(TimePoint timePoint); - Competitor getLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Competitor getLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java index e14cfdf5320..53640915a54 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java @@ -72,7 +72,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * Same as {@link #getWindwardDistanceToGo(TimePoint, WindPositionMode)}, only that a cache for wind and leg * type / bearing can be passed. */ - Distance getWindwardDistanceToGo(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistanceToGo(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Computes an approximation for the average velocity made good (windward / leeward speed) of this leg's competitor at @@ -154,7 +154,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * Same as {@link #getRank(TimePoint)} with the additional option to provide a cache * that can help avoid redundant calculations of wind and leg data. */ - int getRank(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + int getRank(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Computes the gap in seconds to the leader / winner of this leg. Returns null in case this leg's @@ -165,7 +165,7 @@ public interface TrackedLegOfCompetitor extends Serializable { /** * Same as {@link #getGapToLeader(TimePoint, RankingInfo, WindPositionMode)}, only that a cache for wind and leg type data is used. */ - Duration getGapToLeader(TimePoint timePoint, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + Duration getGapToLeader(TimePoint timePoint, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * If a caller already went through the effort of computing the leg's leader at timePoint, it @@ -179,7 +179,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * all can use the same basic information. */ Duration getGapToLeader(TimePoint timePoint, Competitor leaderInLegAtTimePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); boolean hasStartedLeg(TimePoint timePoint); @@ -208,7 +208,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * Same as {@link #getVelocityMadeGood(TimePoint, WindPositionMode)}, only that a cache for wind data and leg type and bearing * is passed. */ - SpeedWithBearing getVelocityMadeGood(TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache); + SpeedWithBearing getVelocityMadeGood(TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** @@ -219,7 +219,7 @@ public interface TrackedLegOfCompetitor extends Serializable { /** * Same as {@link #getEstimatedTimeToNextMark(TimePoint, WindPositionMode)}, only that a cache for leg type calculation is passed. */ - Duration getEstimatedTimeToNextMark(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache); + Duration getEstimatedTimeToNextMark(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Returns null in case this leg's competitor hasn't started the leg yet. If in the leg at @@ -264,7 +264,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * Same as {@link #getWindwardDistanceToCompetitorFarthestAhead(TimePoint, WindPositionMode, RankingInfo)}, only that a cache for leg type * calculation is passed. */ - Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Computes the average absolute cross track error for this leg. The cross track error for each fix is taken to be a @@ -289,7 +289,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * Like {@link #getAverageVelocityMadeGood(TimePoint)}, only with an additional cache argument that allows the method to * use already computed values for wind and leg type, potentially also updating the cache as it goes. */ - Speed getAverageVelocityMadeGood(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Speed getAverageVelocityMadeGood(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * If the {@link #getCompetitor() competitor} hasn't started the {@link #getTrackedLeg() leg} yet at 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 298e6f85772..579c3420269 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 @@ -683,7 +683,7 @@ public interface TrackedRace * materialized ranking information that is expensive to calculate, avoiding redundant calculations */ Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache); + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * Calls {@link #getWindWithConfidence(Position, TimePoint, Iterable)} and excludes those wind sources listed in @@ -734,7 +734,7 @@ public interface TrackedRace * wind on leg and leg bearing is provided. */ Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, - WindLegTypeAndLegBearingCache cache) throws NoWindException; + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException; Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, boolean waitForLatestAnalyses) throws NoWindException; @@ -747,7 +747,7 @@ public interface TrackedRace * wind direction and leg bearing is provided. */ Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalyses, - WindLegTypeAndLegBearingCache cache) throws NoWindException; + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException; Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, boolean waitForLatestAnalysis) throws NoWindException; @@ -758,7 +758,7 @@ public interface TrackedRace Competitor getOverallLeader(TimePoint timePoint); - Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); Boat getBoatOfCompetitor(Competitor competitor); @@ -774,7 +774,7 @@ public interface TrackedRace * Same as {@link #getCompetitorsFromBestToWorst(TimePoint)}, using a cache for wind, leg type and leg * bearing values. */ - List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache); + List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); /** * When provided with a {@link WindStore} during construction, the tracked race will @@ -1111,7 +1111,7 @@ public interface TrackedRace * it can be added to the boat's course over ground to arrive at the wind's {@link Wind#getFrom() "from"} direction. Example: wind * from the north (0deg), boat's course over ground 90deg (moving east), then the bearing returned is -90deg. */ - default Bearing getTWA(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + default Bearing getTWA(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Bearing twa = null; final GPSFixTrack sogTrack = this.getTrack(competitor); if (sogTrack != null) { @@ -1137,7 +1137,7 @@ public interface TrackedRace * Like {@link #getVelocityMadeGood(Competitor, TimePoint)}, but allowing callers to specify a cache that can * accelerate requests for wind directions, the leg type and the competitor's current leg's bearing. */ - default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + default SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getVelocityMadeGood(competitor, timePoint, WindPositionMode.EXACT, cache); } @@ -1149,7 +1149,7 @@ public interface TrackedRace * or has already finished), {@code null} is returned. */ SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode, - WindLegTypeAndLegBearingCache cache); + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache); boolean recordWind(Wind wind, WindSource windSource, boolean applyFilter); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingAndORCPerformanceCurveCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingAndORCPerformanceCurveCache.java new file mode 100755 index 00000000000..ce09a99cd74 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingAndORCPerformanceCurveCache.java @@ -0,0 +1,7 @@ +package com.sap.sailing.domain.tracking; + +import com.sap.sailing.domain.orc.ORCPerformanceCurveCache; + +public interface WindLegTypeAndLegBearingAndORCPerformanceCurveCache extends WindCache, LegTypeCache, LegBearingCache, ORCPerformanceCurveCache { + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingCache.java deleted file mode 100755 index f19a874f5d2..00000000000 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindLegTypeAndLegBearingCache.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.sap.sailing.domain.tracking; - -public interface WindLegTypeAndLegBearingCache extends WindCache, LegTypeCache, LegBearingCache { -} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/NoCachingWindLegTypeAndLegBearingCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/NoCachingWindLegTypeAndLegBearingCache.java index 72e2f506e25..b4078d3efca 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/NoCachingWindLegTypeAndLegBearingCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/NoCachingWindLegTypeAndLegBearingCache.java @@ -1,13 +1,19 @@ package com.sap.sailing.domain.tracking.impl; +import java.util.function.Function; +import java.util.function.Supplier; + import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse; +import com.sap.sailing.domain.orc.ORCPerformanceCurve; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sse.common.Bearing; +import com.sap.sse.common.Speed; import com.sap.sse.common.TimePoint; /** @@ -18,7 +24,7 @@ import com.sap.sse.common.TimePoint; * @author Axel Uhl (D043530) * */ -public class NoCachingWindLegTypeAndLegBearingCache implements WindLegTypeAndLegBearingCache { +public class NoCachingWindLegTypeAndLegBearingCache implements WindLegTypeAndLegBearingAndORCPerformanceCurveCache { @Override public Wind getWind(TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return trackedRace.getWind(trackedRace.getTrack(competitor).getEstimatedPosition(timePoint, false), timePoint); @@ -33,4 +39,25 @@ public class NoCachingWindLegTypeAndLegBearingCache implements WindLegTypeAndLeg public Bearing getLegBearing(TrackedLeg trackedLeg, TimePoint timePoint) { return trackedLeg.getLegBearing(timePoint); } + + @Override + public ORCPerformanceCurveCourse getTotalCourse(Supplier totalCourseSupplier) { + return totalCourseSupplier.get(); + } + + @Override + public Competitor getScratchBoat(Supplier scratchBoatSupplier) { + return scratchBoatSupplier.get(); + } + + @Override + public ORCPerformanceCurve getPerformanceCurveForPartialCourse(Competitor competitor, + Function performanceCurveSupplier) { + return performanceCurveSupplier.apply(competitor); + } + + @Override + public Speed getImpliedWind(Competitor competitor, Function impliedWindSupplier) { + return impliedWindSupplier.apply(competitor); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/RaceRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/RaceRankComparator.java index 219b3b0bf2d..63b2e3e1d32 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/RaceRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/RaceRankComparator.java @@ -10,7 +10,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sse.common.Distance; import com.sap.sse.common.TimePoint; @@ -39,9 +39,9 @@ import com.sap.sse.common.TimePoint; */ public class RaceRankComparator extends AbstractRaceRankComparator { private final Map windwardDistanceToGoInLegCache; - private final WindLegTypeAndLegBearingCache cache; + private final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache; - public RaceRankComparator(TrackedRace trackedRace, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public RaceRankComparator(TrackedRace trackedRace, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { super(trackedRace, timePoint, /* lessIsBetter */ true); this.cache = cache; this.windwardDistanceToGoInLegCache = new HashMap(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java index e9d2eb1f279..381a9092ac5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java @@ -42,7 +42,7 @@ import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRaceStatus; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindWithConfidence; import com.sap.sse.common.Bearing; @@ -118,7 +118,7 @@ public class TrackedLegImpl implements TrackedLeg { } @Override - public Competitor getLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { List byRank = getCompetitorTracksOrderedByRank(timePoint, cache); return byRank.get(0).getCompetitor(); } @@ -137,7 +137,7 @@ public class TrackedLegImpl implements TrackedLeg { return getCompetitorTracksOrderedByRank(timePoint, new LeaderboardDTOCalculationReuseCache(timePoint)); } - List getCompetitorTracksOrderedByRank(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + List getCompetitorTracksOrderedByRank(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { List rankedCompetitorList; rankedCompetitorList = competitorTracksOrderedByRank.get(timePoint); if (rankedCompetitorList != null) { @@ -169,7 +169,7 @@ public class TrackedLegImpl implements TrackedLeg { } @Override - public LinkedHashMap getRanks(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public LinkedHashMap getRanks(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { List orderedTrackedLegsOfCompetitors = getCompetitorTracksOrderedByRank(timePoint, cache); LinkedHashMap result = new LinkedHashMap(); int i=1; @@ -372,7 +372,7 @@ public class TrackedLegImpl implements TrackedLeg { @Override public Distance getAbsoluteWindwardDistance(Position pos1, Position pos2, TimePoint at, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Distance preResult = getWindwardDistance(pos1, pos2, at, windPositionMode, cache); final Distance result; if (preResult == null || preResult.getMeters() >= 0) { @@ -390,23 +390,23 @@ public class TrackedLegImpl implements TrackedLeg { } @Override - public Distance getWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TimePoint referenceTimePoint = getReferenceTimePoint(); return getWindwardDistanceFromLegStart(pos, referenceTimePoint, cache); } - private Distance getWindwardDistanceFromLegStart(Position pos, final TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private Distance getWindwardDistanceFromLegStart(Position pos, final TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getWindwardDistance(getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint), pos, timePoint, WindPositionMode.LEG_MIDDLE, cache); } @Override - public Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingCache cache) { + public Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TimePoint referenceTimePoint = getReferenceTimePoint(); return getAbsoluteWindwardDistanceFromLegStart(pos, referenceTimePoint, cache); } - private Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, final TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + private Distance getAbsoluteWindwardDistanceFromLegStart(Position pos, final TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getAbsoluteWindwardDistance(getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint), pos, timePoint, WindPositionMode.LEG_MIDDLE, cache); } @@ -426,13 +426,13 @@ public class TrackedLegImpl implements TrackedLeg { } @Override - public Distance getWindwardDistance(WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistance(WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TimePoint middle = getReferenceTimePoint(); return getWindwardDistance(middle, cache); } @Override - public Distance getAbsoluteWindwardDistance(WindLegTypeAndLegBearingCache cache) { + public Distance getAbsoluteWindwardDistance(WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TimePoint middle = getReferenceTimePoint(); return getAbsoluteWindwardDistance(middle, cache); } @@ -470,21 +470,21 @@ public class TrackedLegImpl implements TrackedLeg { } @Override - public Distance getWindwardDistance(final TimePoint middle, WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistance(final TimePoint middle, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Position fromPos = getTrackedRace().getApproximatePosition(getLeg().getFrom(), middle); final Position toPos = getTrackedRace().getApproximatePosition(getLeg().getTo(), middle); return getWindwardDistance(fromPos, toPos, middle, WindPositionMode.LEG_MIDDLE, cache); } @Override - public Distance getAbsoluteWindwardDistance(final TimePoint middle, WindLegTypeAndLegBearingCache cache) { + public Distance getAbsoluteWindwardDistance(final TimePoint middle, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Position fromPos = getTrackedRace().getApproximatePosition(getLeg().getFrom(), middle); final Position toPos = getTrackedRace().getApproximatePosition(getLeg().getTo(), middle); return getAbsoluteWindwardDistance(fromPos, toPos, middle, WindPositionMode.LEG_MIDDLE, cache); } @Override - public Distance getWindwardDistance(final Position pos1, final Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistance(final Position pos1, final Position pos2, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Distance result; if (pos1 == null || pos2 == null) { result = null; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java index 0acfc6d5cb8..55f57490bfb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java @@ -27,7 +27,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sse.common.Bearing; import com.sap.sse.common.Distance; @@ -219,7 +219,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { @Override - public Distance getWindwardDistanceToGo(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistanceToGo(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Distance result; if (hasFinishedLeg(timePoint)) { result = Distance.NULL; @@ -253,7 +253,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { * The distance returned may turn negative if the competitor sailed past the approximate windward position of the * leg's {@link Leg#getTo() end waypoint} but hasn't finished the leg yet. */ - private Distance getWindwardDistanceTo(Waypoint waypoint, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + private Distance getWindwardDistanceTo(Waypoint waypoint, TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Position estimatedPosition = getTrackedRace().getTrack(getCompetitor()).getEstimatedPosition(at, false); if (!hasStartedLeg(at) || estimatedPosition == null) { // covers the case with no fixes for this leg yet, also if the mark passing has already been received @@ -284,7 +284,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { * in case the wind direction is not known */ private SpeedWithBearing getWindwardSpeed(SpeedWithBearing speed, final TimePoint at, WindPositionMode windPositionMode, - WindLegTypeAndLegBearingCache cache) { + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final SpeedWithBearing result; if (speed != null) { Bearing projectToBearing; @@ -329,7 +329,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public int getRank(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public int getRank(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { int result = 0; if (hasStartedLeg(timePoint)) { List competitorTracksByRank = getTrackedLeg().getCompetitorTracksOrderedByRank(timePoint, cache); @@ -344,7 +344,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Speed getAverageVelocityMadeGood(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Speed getAverageVelocityMadeGood(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Speed result = null; MarkPassing start = getMarkPassingForLegStart(); if (start != null && start.getTimePoint().compareTo(timePoint) <= 0) { @@ -440,7 +440,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + public Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { // FIXME bug 607 it seems the following fetches the leader of this leg, not the overall leader; validate!!! Use getTrackedRace().getRanks() instead Competitor competitorFarthestAhead = rankingInfo.getCompetitorFarthestAhead(); TrackedLegOfCompetitor leaderLeg = getTrackedRace().getCurrentLeg(competitorFarthestAhead, timePoint); @@ -535,7 +535,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { @Override public Duration getGapToLeader(TimePoint timePoint, final Competitor leaderInLegAtTimePoint, - WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getGapToLeader(timePoint, ()->leaderInLegAtTimePoint, windPositionMode, rankingInfo, cache); } @@ -550,12 +550,12 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Duration getGapToLeader(final TimePoint timePoint, WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + public Duration getGapToLeader(final TimePoint timePoint, WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return getGapToLeader(timePoint, ()->getTrackedLeg().getLeader(hasFinishedLeg(timePoint) ? getFinishTime() : timePoint), windPositionMode, rankingInfo, new LeaderboardDTOCalculationReuseCache(timePoint)); } - private Duration getGapToLeader(TimePoint timePoint, LeaderGetter leaderGetter, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + private Duration getGapToLeader(TimePoint timePoint, LeaderGetter leaderGetter, WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { // If a competitor already completed this leg, compute the estimated arrival time at the // end of this leg and compare to the first mark passing for the end of this leg; if this leg's competitor also already // finished the leg, return the difference between this competitor's leg completion time point and the leader's completion @@ -659,7 +659,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public SpeedWithBearing getVelocityMadeGood(TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + public SpeedWithBearing getVelocityMadeGood(TimePoint at, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { if (hasStartedLeg(at)) { TimePoint timePoint; if (hasFinishedLeg(at)) { @@ -722,7 +722,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Duration getEstimatedTimeToNextMark(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + public Duration getEstimatedTimeToNextMark(TimePoint timePoint, WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Duration result; if (hasFinishedLeg(timePoint)) { result = Duration.NULL; 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 162f8cb20fd..36c65a17799 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 @@ -142,7 +142,7 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRaceStatus; import com.sap.sailing.domain.tracking.TrackedRaceWithWindEssentials; import com.sap.sailing.domain.tracking.TrackedRegatta; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindSummary; @@ -1489,7 +1489,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { Competitor result = null; List ranks = getCompetitorsFromBestToWorst(timePoint, cache); if (ranks != null && !ranks.isEmpty()) { @@ -1546,7 +1546,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } @Override - public List getCompetitorsFromBestToWorst(TimePoint unadjustedTimePoint, WindLegTypeAndLegBearingCache cache) { + public List getCompetitorsFromBestToWorst(TimePoint unadjustedTimePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TimePoint timePoint; // normalize the time point to get cache hits when asking for time points that are later than // the last time point affected by any event received for this tracked race @@ -1607,7 +1607,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis, - WindLegTypeAndLegBearingCache cache) + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException { NavigableSet markPassings = getMarkPassings(competitor); TimePoint from = null; @@ -1636,7 +1636,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) throws NoWindException { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException { NavigableSet markPassings = getMarkPassings(competitor); TimePoint from = null; lockForRead(markPassings); @@ -2865,7 +2865,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final TrackedLegOfCompetitor trackedLeg = getTrackedLeg(competitor, timePoint); return trackedLeg == null ? null : trackedLeg.getWindwardDistanceToCompetitorFarthestAhead(timePoint, windPositionMode, rankingInfo, cache); } @@ -3825,7 +3825,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { TrackedLegOfCompetitor trackedLeg = getTrackedLeg(competitor, timePoint); final SpeedWithBearing result; if (trackedLeg != null) { @@ -3864,7 +3864,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl * position, defaulting to the "COMBINED" wind source at the middle of the course. In particular, it then * obviously makes no real sense to request {@link WindPositionMode#LEG_MIDDLE} because no leg is known. */ - Wind getWind(WindPositionMode windPositionMode, TrackedLegImpl trackedLeg, Competitor competitor, TimePoint at, WindLegTypeAndLegBearingCache cache) { + Wind getWind(WindPositionMode windPositionMode, TrackedLegImpl trackedLeg, Competitor competitor, TimePoint at, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final Wind wind; if (windPositionMode == WindPositionMode.EXACT) { wind = cache.getWind(this, competitor, at); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindwardToGoComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindwardToGoComparator.java index 031ffff2ffa..7ab24cd60e7 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindwardToGoComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindwardToGoComparator.java @@ -11,7 +11,7 @@ import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sse.common.Distance; import com.sap.sse.common.TimePoint; @@ -27,9 +27,9 @@ public class WindwardToGoComparator implements Comparator wwdtgCache; - private final WindLegTypeAndLegBearingCache windAndLegTypeCache; + private final WindLegTypeAndLegBearingAndORCPerformanceCurveCache windAndLegTypeCache; - public WindwardToGoComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public WindwardToGoComparator(TrackedLeg trackedLeg, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { this.trackedLeg = trackedLeg; this.timePoint = timePoint; wwdtgCache = new HashMap(); diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index 4dcc57b33c3..03c7dab74df 100755 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -65,7 +65,7 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRaceStatus; import com.sap.sailing.domain.tracking.TrackingDataLoader; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindSummary; @@ -503,7 +503,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -716,7 +716,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingCache cache) { + boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -795,17 +795,17 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingCache cache) { + public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } @@ -923,7 +923,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingCache cache) { + WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { return null; } 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 c7816425d81..05c5287baaf 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 @@ -366,7 +366,7 @@ import com.sap.sailing.domain.tracking.Track; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingCache; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.WindWithConfidence; @@ -2110,7 +2110,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet throws NoWindException { Map, LegType> legTypeCache = new HashMap<>(); Map> result = new HashMap<>(); - final ConcurrentHashMap cachesByTimePoint = new ConcurrentHashMap<>(); + final ConcurrentHashMap cachesByTimePoint = new ConcurrentHashMap<>(); TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); getSecurityService().checkCurrentUserReadPermission(trackedRace); if (trackedRace != null) { @@ -2192,7 +2192,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet Double detailValue = null; if (detailType != null) { MillisecondsTimePoint time = new MillisecondsTimePoint(fix.getTimePoint().asMillis()); - WindLegTypeAndLegBearingCache cache = cachesByTimePoint.get(time); + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = cachesByTimePoint.get(time); if (cache == null) { cache = new LeaderboardDTOCalculationReuseCache(time); cachesByTimePoint.put(time, cache); @@ -3436,7 +3436,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } private Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor, - TimePoint timePoint, String leaderboardGroupName, String leaderboardName, WindLegTypeAndLegBearingCache cache) throws NoWindException { + TimePoint timePoint, String leaderboardGroupName, String leaderboardName, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException { Double result = null; Course course = trackedRace.getRace().getCourse(); course.lockForRead(); // make sure the tracked leg survives this call even if a course update is pending @@ -3826,7 +3826,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet final long adjustedStepSizeInMillis = (long) Math.max((double) stepSizeInMillis, startTime.until(endTime).divide(SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY).asMillis()); result = new CompetitorsRaceDataDTO(detailType, startTime==null?null:startTime.asDate(), endTime==null?null:endTime.asDate()); final int MAX_CACHE_SIZE = SailingServiceConstants.MAX_NUMBER_OF_FIXES_TO_QUERY; - final ConcurrentHashMap cachesByTimePoint = new ConcurrentHashMap<>(); + final ConcurrentHashMap cachesByTimePoint = new ConcurrentHashMap<>(); Map> resultFutures = new HashMap<>(); for (final CompetitorDTO competitorDTO : competitors) { FutureTask future = new FutureTask(new Callable() { @@ -3843,7 +3843,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet try { for (MarkPassing markPassing : competitorMarkPassings) { MillisecondsTimePoint time = new MillisecondsTimePoint(markPassing.getTimePoint().asMillis()); - WindLegTypeAndLegBearingCache cache = cachesByTimePoint.get(time); + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = cachesByTimePoint.get(time); if (cache == null) { cache = new LeaderboardDTOCalculationReuseCache(time); cachesByTimePoint.put(time, cache); @@ -3862,11 +3862,11 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet if (startTime != null && endTime != null) { for (long i = startTime.asMillis(); i <= endTime.asMillis(); i += adjustedStepSizeInMillis) { MillisecondsTimePoint time = new MillisecondsTimePoint(i); - WindLegTypeAndLegBearingCache cache = cachesByTimePoint.get(time); + WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = cachesByTimePoint.get(time); if (cache == null) { cache = new LeaderboardDTOCalculationReuseCache(time); if (cachesByTimePoint.size() >= MAX_CACHE_SIZE) { - final Iterator> iterator = cachesByTimePoint.entrySet().iterator(); + final Iterator> iterator = cachesByTimePoint.entrySet().iterator(); while (cachesByTimePoint.size() >= MAX_CACHE_SIZE && iterator.hasNext()) { iterator.next(); iterator.remove();