bug3964: computing avg SOG and ride height for entire race when race is finished

Change-Id: I982325e724f891e88ed1a6297c18d8a71f38d1b8
This commit is contained in:
Axel Uhl committed 2016-10-21 13:11:12 +02:00
1 parent 8a38e46f95
commit e84394597f
10 files changed
+82 -15

No files matched your search

@@ -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;
@@ -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;
}
} }
@@ -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;
}
} }
@@ -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);
@@ -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;
} }
@@ -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
@@ -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;
}
} }
@@ -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;
} }
} }
} }
@@ -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;
}
} }