mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-22 20:13:52 +00:00
bug3964: computing avg SOG and ride height for entire race when race is finished
Change-Id: I982325e724f891e88ed1a6297c18d8a71f38d1b8
This commit is contained in:
1 parent
8a38e46f95
commit
e84394597f
10 files changed
+82
-15
No files matched your search
+8
@@ -78,6 +78,8 @@ public class LeaderboardEntryDTO implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public Duration averageSamplingInterval;
|
public Duration averageSamplingInterval;
|
||||||
|
|
||||||
|
public Double averageRideHeightInMeters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time gap to the competitor leading the race; for one-design races this is the time the competitor is expected
|
* The time gap to the competitor leading the race; for one-design races this is the time the competitor is expected
|
||||||
* to need to reach the leader's (windward) position (if in the same leg) or the difference between the time at
|
* to need to reach the leader's (windward) position (if in the same leg) or the difference between the time at
|
||||||
@@ -174,6 +176,7 @@ public class LeaderboardEntryDTO implements Serializable {
|
|||||||
result = prime * result
|
result = prime * result
|
||||||
+ ((speedOverGroundAtStartOfRaceInKnots == null) ? 0 : speedOverGroundAtStartOfRaceInKnots.hashCode());
|
+ ((speedOverGroundAtStartOfRaceInKnots == null) ? 0 : speedOverGroundAtStartOfRaceInKnots.hashCode());
|
||||||
result = prime * result + ((startTack == null) ? 0 : startTack.hashCode());
|
result = prime * result + ((startTack == null) ? 0 : startTack.hashCode());
|
||||||
|
result = prime * result + ((averageRideHeightInMeters == null) ? 0 : averageRideHeightInMeters.hashCode());
|
||||||
result = prime * result + ((averageSamplingInterval == null) ? 0 : averageSamplingInterval.hashCode());
|
result = prime * result + ((averageSamplingInterval == null) ? 0 : averageSamplingInterval.hashCode());
|
||||||
result = prime * result + ((timeSinceLastPositionFixInSeconds == null) ? 0 : timeSinceLastPositionFixInSeconds.hashCode());
|
result = prime * result + ((timeSinceLastPositionFixInSeconds == null) ? 0 : timeSinceLastPositionFixInSeconds.hashCode());
|
||||||
result = prime * result + ((netPoints == null) ? 0 : netPoints.hashCode());
|
result = prime * result + ((netPoints == null) ? 0 : netPoints.hashCode());
|
||||||
@@ -282,6 +285,11 @@ public class LeaderboardEntryDTO implements Serializable {
|
|||||||
return false;
|
return false;
|
||||||
if (startTack != other.startTack)
|
if (startTack != other.startTack)
|
||||||
return false;
|
return false;
|
||||||
|
if (averageRideHeightInMeters == null) {
|
||||||
|
if (other.averageRideHeightInMeters != null)
|
||||||
|
return false;
|
||||||
|
} else if (!averageRideHeightInMeters.equals(other.averageRideHeightInMeters))
|
||||||
|
return false;
|
||||||
if (averageSamplingInterval == null) {
|
if (averageSamplingInterval == null) {
|
||||||
if (other.averageSamplingInterval != null)
|
if (other.averageSamplingInterval != null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+5
-3
@@ -541,15 +541,12 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isControlTrackingFromStartAndFinishTimes() {
|
public boolean isControlTrackingFromStartAndFinishTimes() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setControlTrackingFromStartAndFinishTimes(
|
public void setControlTrackingFromStartAndFinishTimes(
|
||||||
boolean controlTrackingFromStartAndFinishTimes) {
|
boolean controlTrackingFromStartAndFinishTimes) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1130,4 +1127,9 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
|||||||
public Iterable<RaceLog> getAttachedRaceLogs() {
|
public Iterable<RaceLog> getAttachedRaceLogs() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
@@ -681,4 +681,9 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
|||||||
public Iterable<RaceLog> getAttachedRaceLogs() {
|
public Iterable<RaceLog> getAttachedRaceLogs() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
@@ -1437,6 +1437,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
|||||||
} else {
|
} else {
|
||||||
entryDTO.timeSinceLastPositionFixInSeconds = null;
|
entryDTO.timeSinceLastPositionFixInSeconds = null;
|
||||||
}
|
}
|
||||||
|
entryDTO.averageRideHeightInMeters = trackedRace.getAverageRideHeight(competitor, timePoint);
|
||||||
}
|
}
|
||||||
if (addLegDetails && trackedRace != null) {
|
if (addLegDetails && trackedRace != null) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
|||||||
import com.sap.sailing.domain.common.tracking.SensorFix;
|
import com.sap.sailing.domain.common.tracking.SensorFix;
|
||||||
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException;
|
||||||
import com.sap.sailing.domain.polars.PolarDataService;
|
import com.sap.sailing.domain.polars.PolarDataService;
|
||||||
|
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||||
import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache;
|
import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache;
|
||||||
@@ -685,6 +686,8 @@ public interface TrackedRace extends Serializable, IsManagedByCache<SharedDomain
|
|||||||
Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
|
Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
|
||||||
boolean waitForLatestAnalysis) throws NoWindException;
|
boolean waitForLatestAnalysis) throws NoWindException;
|
||||||
|
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
WindStore getWindStore();
|
WindStore getWindStore();
|
||||||
|
|
||||||
Competitor getOverallLeader(TimePoint timePoint);
|
Competitor getOverallLeader(TimePoint timePoint);
|
||||||
|
|||||||
+1
-2
@@ -174,8 +174,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
|||||||
}
|
}
|
||||||
if (timePointToUse != null) {
|
if (timePointToUse != null) {
|
||||||
Distance d = getDistanceTraveled(timePointToUse);
|
Distance d = getDistanceTraveled(timePointToUse);
|
||||||
long millis = timePointToUse.asMillis() - legStart.getTimePoint().asMillis();
|
result = d.inTime(legStart.getTimePoint().until(timePointToUse));
|
||||||
result = d.inTime(millis);
|
|
||||||
} else {
|
} else {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
|
|||||||
+16
@@ -1538,6 +1538,22 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
final Double result;
|
||||||
|
BravoFixTrack<Competitor> track = getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
||||||
|
final Leg firstLeg;
|
||||||
|
final TrackedLegOfCompetitor firstTrackedLeg;
|
||||||
|
if (track != null && (firstLeg = getRace().getCourse().getFirstLeg()) != null && (firstTrackedLeg = getTrackedLeg(competitor, firstLeg)).hasStartedLeg(timePoint)) {
|
||||||
|
final TrackedLegOfCompetitor lastTrackedLeg = getTrackedLegFinishingAt(getRace().getCourse().getLastWaypoint()).getTrackedLeg(competitor);
|
||||||
|
TimePoint endTimePoint = lastTrackedLeg.hasFinishedLeg(timePoint) ? lastTrackedLeg.getFinishTime() : timePoint;
|
||||||
|
result = track.getAverageRideHeight(firstTrackedLeg.getStartTime(), endTimePoint);
|
||||||
|
} else {
|
||||||
|
result = null;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint) {
|
public TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint) {
|
||||||
// If the mark passing that starts a leg happened exactly at timePoint, the MarkPassingByTimeComparator won't consider
|
// If the mark passing that starts a leg happened exactly at timePoint, the MarkPassingByTimeComparator won't consider
|
||||||
|
|||||||
+5
@@ -860,4 +860,9 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
|||||||
public Iterable<RaceLog> getAttachedRaceLogs() {
|
public Iterable<RaceLog> getAttachedRaceLogs() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+33
-10
@@ -76,6 +76,7 @@ import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
|
|||||||
import com.sap.sailing.domain.common.dto.LegEntryDTO;
|
import com.sap.sailing.domain.common.dto.LegEntryDTO;
|
||||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||||
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
|
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
|
||||||
|
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||||
import com.sap.sailing.gwt.ui.actions.GetLeaderboardByNameAction;
|
import com.sap.sailing.gwt.ui.actions.GetLeaderboardByNameAction;
|
||||||
import com.sap.sailing.gwt.ui.client.Collator;
|
import com.sap.sailing.gwt.ui.client.Collator;
|
||||||
import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
|
import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
|
||||||
@@ -102,6 +103,7 @@ import com.sap.sse.common.Util.Pair;
|
|||||||
import com.sap.sse.common.filter.BinaryOperator;
|
import com.sap.sse.common.filter.BinaryOperator;
|
||||||
import com.sap.sse.common.filter.Filter;
|
import com.sap.sse.common.filter.Filter;
|
||||||
import com.sap.sse.common.filter.FilterSet;
|
import com.sap.sse.common.filter.FilterSet;
|
||||||
|
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||||
import com.sap.sse.gwt.client.ErrorReporter;
|
import com.sap.sse.gwt.client.ErrorReporter;
|
||||||
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
||||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||||
@@ -972,10 +974,10 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
|||||||
new FormattedDoubleDetailTypeColumn(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS, new RaceGapToLeaderInSeconds(),
|
new FormattedDoubleDetailTypeColumn(DetailType.RACE_GAP_TO_LEADER_IN_SECONDS, new RaceGapToLeaderInSeconds(),
|
||||||
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
||||||
result.put(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS,
|
result.put(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS,
|
||||||
new FormattedDoubleDetailTypeColumn(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, new CurrentSpeedOverGroundInKnots(),
|
new FormattedDoubleDetailTypeColumn(DetailType.RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, new RaceCurrentSpeedOverGroundInKnots(),
|
||||||
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
||||||
result.put(DetailType.RACE_CURRENT_RIDE_HEIGHT_IN_METERS, new RideHeightColumn(DetailType.RACE_CURRENT_RIDE_HEIGHT_IN_METERS,
|
result.put(DetailType.RACE_CURRENT_RIDE_HEIGHT_IN_METERS, new RideHeightColumn(DetailType.RACE_CURRENT_RIDE_HEIGHT_IN_METERS,
|
||||||
new CurrentRideHeightInMeters(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
new RaceCurrentRideHeightInMeters(), LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
||||||
result.put(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS,
|
result.put(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS,
|
||||||
new FormattedDoubleDetailTypeColumn(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, new RaceDistanceToCompetitorFarthestAheadInMeters(),
|
new FormattedDoubleDetailTypeColumn(DetailType.RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, new RaceDistanceToCompetitorFarthestAheadInMeters(),
|
||||||
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
LEG_COLUMN_HEADER_STYLE, LEG_COLUMN_STYLE, LeaderboardPanel.this));
|
||||||
@@ -1446,27 +1448,48 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
|||||||
lastLegDetail = fieldsForRace.legDetails.get(--lastLegIndex);
|
lastLegDetail = fieldsForRace.legDetails.get(--lastLegIndex);
|
||||||
}
|
}
|
||||||
if (lastLegDetail != null) {
|
if (lastLegDetail != null) {
|
||||||
result = get(lastLegDetail);
|
if (lastLegDetail.finished) {
|
||||||
|
result = getAfterLastLegFinished(row);
|
||||||
|
} else {
|
||||||
|
result = getBeforeLastLegFinished(lastLegDetail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T get(LegEntryDTO lastLegDetail);
|
protected abstract T getBeforeLastLegFinished(LegEntryDTO currentLegDetail);
|
||||||
|
|
||||||
|
protected abstract T getAfterLastLegFinished(LeaderboardRowDTO row);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CurrentSpeedOverGroundInKnots extends AbstractLastLegDetailField<Double> {
|
private class RaceCurrentSpeedOverGroundInKnots extends AbstractLastLegDetailField<Double> {
|
||||||
@Override
|
@Override
|
||||||
protected Double get(LegEntryDTO lastLegDetail) {
|
protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) {
|
||||||
return lastLegDetail.currentSpeedOverGroundInKnots;
|
return currentLegDetail.currentSpeedOverGroundInKnots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Double getAfterLastLegFinished(LeaderboardRowDTO row) {
|
||||||
|
return new MeterDistance(row.totalDistanceTraveledInMeters).inTime(new MillisecondsDurationImpl((long) (1000.*row.totalTimeSailedInSeconds))).getKnots();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CurrentRideHeightInMeters extends AbstractLastLegDetailField<Double> {
|
private class RaceCurrentRideHeightInMeters extends AbstractLastLegDetailField<Double> {
|
||||||
@Override
|
@Override
|
||||||
protected Double get(LegEntryDTO lastLegDetail) {
|
protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) {
|
||||||
return lastLegDetail.currentRideHeightInMeters;
|
return currentLegDetail.currentRideHeightInMeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Double getAfterLastLegFinished(LeaderboardRowDTO row) {
|
||||||
|
Double result = null;
|
||||||
|
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName());
|
||||||
|
if (fieldsForRace != null) {
|
||||||
|
result = fieldsForRace.averageRideHeightInMeters;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -656,4 +656,9 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
|
|||||||
public Iterable<RaceLog> getAttachedRaceLogs() {
|
public Iterable<RaceLog> getAttachedRaceLogs() {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user