From e84394597f47dff1db90823b99c52535d3347538 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Oct 2016 13:11:12 +0200 Subject: [PATCH 1/4] bug3964: computing avg SOG and ride height for entire race when race is finished Change-Id: I982325e724f891e88ed1a6297c18d8a71f38d1b8 --- .../common/dto/LeaderboardEntryDTO.java | 8 ++++ .../domain/test/mock/MockedTrackedRace.java | 8 ++-- ...ockedTrackedRaceWithStartTimeAndRanks.java | 5 +++ .../impl/AbstractSimpleLeaderboardImpl.java | 1 + .../sailing/domain/tracking/TrackedRace.java | 3 ++ .../impl/TrackedLegOfCompetitorImpl.java | 3 +- .../domain/tracking/impl/TrackedRaceImpl.java | 16 +++++++ .../gwt/ui/test/MockedTrackedRace.java | 5 +++ .../gwt/ui/leaderboard/LeaderboardPanel.java | 43 ++++++++++++++----- .../server/masterdata/DummyTrackedRace.java | 5 +++ 10 files changed, 82 insertions(+), 15 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java index 1eab1c2ace2..390ec3246b1 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java @@ -78,6 +78,8 @@ public class LeaderboardEntryDTO implements Serializable { */ 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 * 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 + ((speedOverGroundAtStartOfRaceInKnots == null) ? 0 : speedOverGroundAtStartOfRaceInKnots.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 + ((timeSinceLastPositionFixInSeconds == null) ? 0 : timeSinceLastPositionFixInSeconds.hashCode()); result = prime * result + ((netPoints == null) ? 0 : netPoints.hashCode()); @@ -282,6 +285,11 @@ public class LeaderboardEntryDTO implements Serializable { return false; if (startTack != other.startTack) return false; + if (averageRideHeightInMeters == null) { + if (other.averageRideHeightInMeters != null) + return false; + } else if (!averageRideHeightInMeters.equals(other.averageRideHeightInMeters)) + return false; if (averageSamplingInterval == null) { if (other.averageSamplingInterval != null) return false; 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 e0119115587..d479e3bdacc 100644 --- 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 @@ -541,15 +541,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { @Override public boolean isControlTrackingFromStartAndFinishTimes() { - // TODO Auto-generated method stub return false; } @Override public void setControlTrackingFromStartAndFinishTimes( boolean controlTrackingFromStartAndFinishTimes) { - // TODO Auto-generated method stub - } }; } @@ -1130,4 +1127,9 @@ public class MockedTrackedRace implements DynamicTrackedRace { public Iterable getAttachedRaceLogs() { return Collections.emptySet(); } + + @Override + public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + 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 fefad810f2b..0d05f85c50f 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 @@ -681,4 +681,9 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { public Iterable getAttachedRaceLogs() { return Collections.emptySet(); } + + @Override + public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + return null; + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 083e5915d18..622447a5771 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -1437,6 +1437,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } else { entryDTO.timeSinceLastPositionFixInSeconds = null; } + entryDTO.averageRideHeightInMeters = trackedRace.getAverageRideHeight(competitor, timePoint); } if (addLegDetails && trackedRace != null) { try { 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 b9f36f9e1aa..9d40a0d9df5 100644 --- 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 @@ -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.polars.NotEnoughDataHasBeenAddedException; 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.RankingInfo; import com.sap.sailing.domain.tracking.impl.NonCachingMarkPositionAtTimePointCache; @@ -685,6 +686,8 @@ public interface TrackedRace extends Serializable, IsManagedByCache 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 public TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint) { // If the mark passing that starts a leg happened exactly at timePoint, the MarkPassingByTimeComparator won't consider 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 b58478a3a82..1a3e75ffd46 100644 --- 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 @@ -860,4 +860,9 @@ public class MockedTrackedRace implements DynamicTrackedRace { public Iterable getAttachedRaceLogs() { return Collections.emptySet(); } + + @Override + public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + return null; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index a6ab0f59476..5af89afdd88 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -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.RaceColumnDTO; 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.client.Collator; 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.Filter; 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.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -972,10 +974,10 @@ public class LeaderboardPanel extends SimplePanel implements Component { + private class RaceCurrentSpeedOverGroundInKnots extends AbstractLastLegDetailField { @Override - protected Double get(LegEntryDTO lastLegDetail) { - return lastLegDetail.currentSpeedOverGroundInKnots; + protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) { + 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 { + private class RaceCurrentRideHeightInMeters extends AbstractLastLegDetailField { @Override - protected Double get(LegEntryDTO lastLegDetail) { - return lastLegDetail.currentRideHeightInMeters; + protected Double getBeforeLastLegFinished(LegEntryDTO currentLegDetail) { + 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; } } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java index c5be8205189..1fa1fd0fb0a 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java @@ -656,4 +656,9 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { public Iterable getAttachedRaceLogs() { return Collections.emptySet(); } + + @Override + public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + return null; + } } From 02be736b122557eec1208dfff72e25e6fa9daa03 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 21 Oct 2016 14:36:04 +0200 Subject: [PATCH 2/4] fixed bug 3964 by calculating *race* average after last leg is finished Change-Id: Ib9852e87e473dbfae9c1a67407bb85338f8a979b --- .../common/dto/LeaderboardEntryDTO.java | 41 ++++++++++++++++ .../domain/common/dto/LeaderboardRowDTO.java | 25 ++++++++++ .../gwt/ui/leaderboard/LeaderboardPanel.java | 49 +++++-------------- 3 files changed, 77 insertions(+), 38 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java index 390ec3246b1..9d525058fea 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardEntryDTO.java @@ -3,10 +3,13 @@ package com.sap.sailing.domain.common.dto; import java.io.Serializable; import java.util.List; +import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.Tack; +import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sse.common.Duration; +import com.sap.sse.common.impl.MillisecondsDurationImpl; /** * Holds a single competitor's scoring details for a single race. It may optionally contain @@ -134,6 +137,44 @@ public class LeaderboardEntryDTO implements Serializable { public boolean hasScoreCorrection() { return totalPointsCorrected || (reasonForMaxPoints != null && reasonForMaxPoints != MaxPointsReason.NONE); } + + public Duration getTimeSailedInMillis() { + final Duration result; + if (legDetails != null) { + long timeInMilliseconds = 0; + for (LegEntryDTO legDetail : legDetails) { + if (legDetail != null) { + if (legDetail.distanceTraveledInMeters != null && legDetail.timeInMilliseconds != null) { + timeInMilliseconds += legDetail.timeInMilliseconds; + } else { + timeInMilliseconds = 0; + break; + } + } + } + result = new MillisecondsDurationImpl(timeInMilliseconds); + } else { + result = null; + } + return result; + } + + public Distance getDistanceTraveledInMeters() { + Distance result = null; + if (legDetails != null) { + for (LegEntryDTO legDetail : legDetails) { + if (legDetail != null) { + if (legDetail.distanceTraveledInMeters != null) { + if (result == null) { + result = Distance.NULL; + } + result = result.add(new MeterDistance(legDetail.distanceTraveledInMeters)); + } + } + } + } + return result; + } @Override public int hashCode() { diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java index 1f5036c8083..a5db8b41249 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/LeaderboardRowDTO.java @@ -4,6 +4,9 @@ import java.io.Serializable; import java.util.Date; import java.util.Map; +import com.sap.sailing.domain.common.Distance; +import com.sap.sse.common.Duration; + /** * Holds data about one competitor and all races represented by the owning {@link LeaderboardDTO leaderboard}. * @@ -117,6 +120,28 @@ public class LeaderboardRowDTO implements Serializable { return true; } + public Distance getDistanceTraveledInMeters(String raceColumnName) { + final Distance result; + LeaderboardEntryDTO fieldsForRace = fieldsByRaceColumnName.get(raceColumnName); + if (fieldsForRace != null) { + result = fieldsForRace.getDistanceTraveledInMeters(); + } else { + result = null; + } + return result; + } + + public Duration getTimeSailed(String raceColumnName) { + final Duration result; + LeaderboardEntryDTO fieldsForRace = fieldsByRaceColumnName.get(raceColumnName); + if (fieldsForRace != null) { + result = fieldsForRace.getTimeSailedInMillis(); + } else { + result = null; + } + return result; + } + @Override public String toString() { return "LeaderboardRowDTO for competitor "+competitor; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index 5af89afdd88..3d4056386e1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -58,6 +58,7 @@ import com.google.gwt.view.client.MultiSelectionModel; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.DetailType; +import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.InvertibleComparator; import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.MaxPointsReason; @@ -76,7 +77,6 @@ import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; import com.sap.sailing.domain.common.dto.LegEntryDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; 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.client.Collator; import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; @@ -98,12 +98,12 @@ import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.leaderboard.DetailTypeColumn.LegDetailField; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; +import com.sap.sse.common.Duration; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.filter.BinaryOperator; import com.sap.sse.common.filter.Filter; 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.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -1100,26 +1100,13 @@ public class LeaderboardPanel extends SimplePanel implements Component { @Override public Double get(LeaderboardRowDTO row) { - Double result = null; - LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName()); - if (fieldsForRace != null && fieldsForRace.legDetails != null) { - double distanceTraveledInMeters = 0; - long timeInMilliseconds = 0; - for (LegEntryDTO legDetail : fieldsForRace.legDetails) { - if (legDetail != null) { - if (legDetail.distanceTraveledInMeters != null && legDetail.timeInMilliseconds != null) { - distanceTraveledInMeters += legDetail.distanceTraveledInMeters; - timeInMilliseconds += legDetail.timeInMilliseconds; - } else { - distanceTraveledInMeters = 0; - timeInMilliseconds = 0; - break; - } - } - } - if (timeInMilliseconds != 0) { - result = distanceTraveledInMeters / (double) timeInMilliseconds * 1000 * 3600 / 1852; - } + final Distance distanceTraveledInMeters = row.getDistanceTraveledInMeters(getRaceColumnName()); + final Duration time = row.getTimeSailed(getRaceColumnName()); + final Double result; + if (distanceTraveledInMeters != null && time != null) { + result = distanceTraveledInMeters.inTime(time).getKnots(); + } else { + result = null; } return result; } @@ -1301,21 +1288,7 @@ public class LeaderboardPanel extends SimplePanel implements Component { @Override public Double get(LeaderboardRowDTO row) { - Double result = null; - LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName()); - if (fieldsForRace != null && fieldsForRace.legDetails != null) { - for (LegEntryDTO legDetail : fieldsForRace.legDetails) { - if (legDetail != null) { - if (legDetail.distanceTraveledInMeters != null) { - if (result == null) { - result = 0.0; - } - result += legDetail.distanceTraveledInMeters; - } - } - } - } - return result; + return row.getDistanceTraveledInMeters(getRaceColumnName()).getMeters(); } } @@ -1472,7 +1445,7 @@ public class LeaderboardPanel extends SimplePanel implements Component Date: Fri, 21 Oct 2016 14:49:43 +0200 Subject: [PATCH 3/4] migrated ride height from a double value to a Distance Change-Id: I15c18f90df384b0241f2ec5ef7e223ded96561d9 --- .../domain/common/tracking/BravoFix.java | 4 ++- .../common/tracking/impl/BravoFixImpl.java | 6 +++-- .../domain/test/mock/MockedTrackedRace.java | 2 +- ...ockedTrackedRaceWithStartTimeAndRanks.java | 2 +- .../impl/BravoFixTrackSerializationTest.java | 4 +-- .../impl/AbstractSimpleLeaderboardImpl.java | 9 ++++--- .../domain/tracking/BravoFixTrack.java | 5 ++-- .../tracking/TrackedLegOfCompetitor.java | 4 +-- .../sailing/domain/tracking/TrackedRace.java | 2 +- .../tracking/impl/BravoFixTrackImpl.java | 25 +++++++++++-------- .../impl/TrackedLegOfCompetitorImpl.java | 10 +++++--- .../domain/tracking/impl/TrackedRaceImpl.java | 4 +-- .../gwt/ui/test/MockedTrackedRace.java | 2 +- .../gwt/ui/server/SailingServiceImpl.java | 3 ++- .../trackfiles/test/BravoDataImportTest.java | 8 +++--- .../server/masterdata/DummyTrackedRace.java | 2 +- 16 files changed, 54 insertions(+), 38 deletions(-) diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoFix.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoFix.java index 73dd3504886..22564e68cc3 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoFix.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/BravoFix.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.common.tracking; +import com.sap.sailing.domain.common.Distance; + /** * Specific {@link SensorFix} for bravo devices (http://www.bravosystems.es/). * @@ -12,5 +14,5 @@ public interface BravoFix extends SensorFix { * * @return the ride height */ - double getRideHeight(); + Distance getRideHeight(); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java index 99ba3015f75..c83402e7545 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/BravoFixImpl.java @@ -1,5 +1,7 @@ package com.sap.sailing.domain.common.tracking.impl; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.BravoFix; import com.sap.sailing.domain.common.tracking.DoubleVectorFix; @@ -32,8 +34,8 @@ public class BravoFixImpl implements BravoFix { } @Override - public double getRideHeight() { - return fix.get(BravoSensorDataMetadata.INSTANCE.rideHeightColumn); + public Distance getRideHeight() { + return new MeterDistance(fix.get(BravoSensorDataMetadata.INSTANCE.rideHeightColumn)); } } 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 d479e3bdacc..ba165f37cc1 100644 --- 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 @@ -1129,7 +1129,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { 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 0d05f85c50f..30cdeb5e6ac 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 @@ -683,7 +683,7 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace { } @Override - public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { return null; } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java index 2a0f19e5877..0ab5678b885 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/tracking/impl/BravoFixTrackSerializationTest.java @@ -82,8 +82,8 @@ public class BravoFixTrackSerializationTest { assertRideHeight(track, testFixData.timePoint, testFixData.rideHeight); } - private void assertRideHeight(BravoFixTrack track, TimePoint timePoint, double expected) { - assertEquals(expected, track.getRideHeight(timePoint), 0.0); + private void assertRideHeight(BravoFixTrack track, TimePoint timePoint, double expectedRideHeightInMeters) { + assertEquals(expectedRideHeightInMeters, track.getRideHeight(timePoint).getMeters(), 0.0); } @SuppressWarnings("unchecked") diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 622447a5771..471d4f5ff89 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -1437,7 +1437,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } else { entryDTO.timeSinceLastPositionFixInSeconds = null; } - entryDTO.averageRideHeightInMeters = trackedRace.getAverageRideHeight(competitor, timePoint); + final Distance averageRideHeight = trackedRace.getAverageRideHeight(competitor, timePoint); + entryDTO.averageRideHeightInMeters = averageRideHeight == null ? null : averageRideHeight.getMeters(); } if (addLegDetails && trackedRace != null) { try { @@ -1722,11 +1723,13 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race Double speedOverGroundInKnots; if (trackedLeg.hasFinishedLeg(timePoint)) { speedOverGroundInKnots = averageSpeedOverGround == null ? null : averageSpeedOverGround.getKnots(); - result.currentRideHeightInMeters = trackedLeg.getAverageRideHeight(timePoint); + final Distance averageRideHeight = trackedLeg.getAverageRideHeight(timePoint); + result.currentRideHeightInMeters = averageRideHeight == null ? null : averageRideHeight.getMeters(); } else { final SpeedWithBearing speedOverGround = trackedLeg.getSpeedOverGround(timePoint); speedOverGroundInKnots = speedOverGround == null ? null : speedOverGround.getKnots(); - result.currentRideHeightInMeters = trackedLeg.getRideHeight(timePoint); + final Distance rideHeight = trackedLeg.getRideHeight(timePoint); + result.currentRideHeightInMeters = rideHeight == null ? null : rideHeight.getMeters(); } result.currentSpeedOverGroundInKnots = speedOverGroundInKnots == null ? null : speedOverGroundInKnots; Distance distanceTraveled = trackedLeg.getDistanceTraveled(timePoint); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java index fcd4163de00..c5b77ab96b1 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/BravoFixTrack.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking; import java.io.Serializable; +import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.tracking.BravoFix; import com.sap.sse.common.TimePoint; import com.sap.sse.common.WithID; @@ -22,7 +23,7 @@ public interface BravoFixTrack extends S * @return the ride height for the given {@link TimePoint} or null if the {@link TimePoint} is not in the range * where we have fixes for. */ - Double getRideHeight(TimePoint timePoint); + Distance getRideHeight(TimePoint timePoint); /** * Calculates the average ride height for the given time range. @@ -34,5 +35,5 @@ public interface BravoFixTrack extends S * @return the average ride height for the given time range or null if there are no fixes in the given * time range. */ - Double getAverageRideHeight(TimePoint from, TimePoint to); + Distance getAverageRideHeight(TimePoint from, TimePoint to); } 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 c4a8ab28c45..dc47af1cce1 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 @@ -97,7 +97,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * timePoint. If the competitor already completed the leg at timePoint and the respective * mark passing event was already received, the average ride height for the entire leg (and no further) is computed. */ - Double getAverageRideHeight(TimePoint timePoint); + Distance getAverageRideHeight(TimePoint timePoint); /** * @return null if the competitor hasn't started this leg yet, otherwise the fix where the maximum speed was @@ -237,7 +237,7 @@ public interface TrackedLegOfCompetitor extends Serializable { * timePoint, returns the current ride height for this time point. If the competitor has already * finished the leg, the ride height at the time the competitor finished the leg is returned. */ - Double getRideHeight(TimePoint at); + Distance getRideHeight(TimePoint at); /** * Computes the distance along the wind track to the wind-projected position of the race's overall leader. If leader 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 9d40a0d9df5..d864ae66e80 100644 --- 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 @@ -686,7 +686,7 @@ public interface TrackedRace extends Serializable, IsManagedByCache extends S } @Override - public Double getRideHeight(TimePoint timePoint) { + public Distance getRideHeight(TimePoint timePoint) { BravoFix fixAfter = getFirstFixAtOrAfter(timePoint); if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) { // exact match of timepoint -> no interpolation necessary @@ -54,17 +52,24 @@ public class BravoFixTrackImpl extends S } @Override - public Double getAverageRideHeight(TimePoint from, TimePoint to) { + public Distance getAverageRideHeight(TimePoint from, TimePoint to) { + final Distance result; lockForRead(); try { - Spliterator fixes = getFixes(from, true, to, true).spliterator(); - OptionalDouble average = StreamSupport.stream(fixes, false).mapToDouble(BravoFix::getRideHeight).average(); - if (average.isPresent()) { - return average.getAsDouble(); + Distance sum = Distance.NULL; + int count = 0; + for (final BravoFix fix : getFixes(from, true, to, true)) { + sum = sum.add(fix.getRideHeight()); + count++; + } + if (count > 0) { + result = sum.scale(1./count); + } else { + result = null; } } finally { unlockAfterRead(); } - return null; + return result; } } 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 538b24dd2e2..fba23c8af4a 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 @@ -183,7 +183,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Double getAverageRideHeight(TimePoint timePoint) { + public Distance getAverageRideHeight(TimePoint timePoint) { MarkPassing legStart = getMarkPassingForLegStart(); if (legStart != null) { BravoFixTrack track = getTrackedRace() @@ -676,15 +676,17 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { } @Override - public Double getRideHeight(TimePoint at) { + public Distance getRideHeight(TimePoint at) { + final Distance result; if (hasStartedLeg(at)) { TimePoint timePoint =hasFinishedLeg(at) ? getMarkPassingForLegEnd().getTimePoint() : at; BravoFixTrack track = getTrackedRace() .> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME); - return track == null ? null : track.getRideHeight(timePoint); + result = track == null ? null : track.getRideHeight(timePoint); } else { - return null; + result = null; } + return result; } @Override 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 a5857993e06..bcb33ab5215 100644 --- 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 @@ -1539,8 +1539,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl } @Override - public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { - final Double result; + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + final Distance result; BravoFixTrack track = getSensorTrack(competitor, BravoFixTrack.TRACK_NAME); final Leg firstLeg; final TrackedLegOfCompetitor firstTrackedLeg; 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 1a3e75ffd46..00050caffca 100644 --- 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 @@ -862,7 +862,7 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { 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 cdcc7d02788..ffcf6f905f3 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 @@ -2941,7 +2941,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S final BravoFixTrack bravoFixTrack = trackedRace .> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME); if (bravoFixTrack != null) { - result = bravoFixTrack.getRideHeight(timePoint); + final Distance rideHeight = bravoFixTrack.getRideHeight(timePoint); + result = rideHeight == null ? null : rideHeight.getMeters(); } break; default: diff --git a/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java b/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java index 5fe5f150b5f..df3e94c8a5d 100644 --- a/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java +++ b/java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/BravoDataImportTest.java @@ -19,12 +19,12 @@ public class BravoDataImportTest { private final DoubleVectorFixImporter bravoDataImporter = new BravoDataImporterImpl(); private int callbackCallCount = 0; - private double sumRideHeight = 0.0; + private double sumRideHeightInMeters = 0.0; @Before public void setUp() { this.callbackCallCount = 0; - this.sumRideHeight = 0.0; + this.sumRideHeightInMeters = 0.0; } @Test @@ -51,12 +51,12 @@ public class BravoDataImportTest { bravoDataImporter.importFixes(importData.getInputStream(), (fixes, device) -> { for (DoubleVectorFix fix : fixes) { callbackCallCount++; - sumRideHeight += new BravoFixImpl(fix).getRideHeight(); + sumRideHeightInMeters += new BravoFixImpl(fix).getRideHeight().getMeters(); } }, "filename", "source"); Assert.assertEquals(importData.expectedFixesCount, callbackCallCount); Assert.assertEquals(importData.expectedAverageRideHeight, - callbackCallCount == 0 ? sumRideHeight : sumRideHeight / callbackCallCount, 0.00001); + callbackCallCount == 0 ? sumRideHeightInMeters : sumRideHeightInMeters / callbackCallCount, 0.00001); } private enum ImportData { diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java index 1fa1fd0fb0a..f7c5d1462db 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/masterdata/DummyTrackedRace.java @@ -658,7 +658,7 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials { } @Override - public Double getAverageRideHeight(Competitor competitor, TimePoint timePoint) { + public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { return null; } } From 5923ac55b252ce73a0edaec4bf95e5ee5a452567 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Sat, 22 Oct 2016 14:29:54 +0200 Subject: [PATCH 4/4] fixed SensorFixStoreAndLoadTest after changing ride height type from double to Distance Change-Id: I1b4864c25732a0d9b5db9275c7e835890ada8f07 --- .../test/impl/SensorFixStoreAndLoadTest.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java index 0fe9590a085..0d5f03e9a81 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/SensorFixStoreAndLoadTest.java @@ -49,9 +49,11 @@ import com.sap.sailing.domain.base.impl.CourseImpl; import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; import com.sap.sailing.domain.base.impl.RegattaImpl; import com.sap.sailing.domain.base.impl.WaypointImpl; +import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.impl.DegreeBearingImpl; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata; import com.sap.sailing.domain.common.tracking.DoubleVectorFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; @@ -95,9 +97,9 @@ public class SensorFixStoreAndLoadTest { private static final long FIX_TIMESTAMP2 = 120; private static final long FIX_TIMESTAMP3 = 210; private static final long AFTER_LAST_FIX = FIX_TIMESTAMP3 + 1; - private static final double FIX_RIDE_HEIGHT = 1337.0; - private static final double FIX_RIDE_HEIGHT2 = 1338.0; - private static final double FIX_RIDE_HEIGHT3 = 1336.0; + private static final Distance FIX_RIDE_HEIGHT = new MeterDistance(1337.0); + private static final Distance FIX_RIDE_HEIGHT2 = new MeterDistance(1338.0); + private static final Distance FIX_RIDE_HEIGHT3 = new MeterDistance(1336.0); private static final double FIX_TEST_VALUE = 12.0; protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a"); @@ -384,20 +386,14 @@ public class SensorFixStoreAndLoadTest { public void testBravoFixIsCorrectlyWrapped() throws InterruptedException { regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp, device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING))); - addBravoFixes(); - FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker(); - trackedRace.attachRaceLog(raceLog); trackedRace.attachRegattaLog(regattaLog); - trackedRace.waitForLoadingToFinish(); - BravoFixTrack bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME); assertEquals(FIX_RIDE_HEIGHT, bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight()); - fixLoaderAndTracker.stop(true); } @@ -482,9 +478,9 @@ public class SensorFixStoreAndLoadTest { } private void addBravoFixes() { - store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT)); - store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2)); - store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP3, FIX_RIDE_HEIGHT3)); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT.getMeters())); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2.getMeters())); + store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP3, FIX_RIDE_HEIGHT3.getMeters())); } private FixLoaderAndTracker createFixLoaderAndTracker() {