mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-22 20:13:52 +00:00
Merge remote-tracking branch 'origin/bug3964'
This commit is contained in:
commit
5b67f0b9b9
20 files changed
+210
-92
No files matched your search
+49
@@ -3,10 +3,13 @@ package com.sap.sailing.domain.common.dto;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.common.Distance;
|
||||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||||
import com.sap.sailing.domain.common.Tack;
|
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.Duration;
|
||||||
|
import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds a single competitor's scoring details for a single race. It may optionally contain
|
* Holds a single competitor's scoring details for a single race. It may optionally contain
|
||||||
@@ -78,6 +81,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
|
||||||
@@ -132,6 +137,44 @@ public class LeaderboardEntryDTO implements Serializable {
|
|||||||
public boolean hasScoreCorrection() {
|
public boolean hasScoreCorrection() {
|
||||||
return totalPointsCorrected || (reasonForMaxPoints != null && reasonForMaxPoints != MaxPointsReason.NONE);
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
@@ -174,6 +217,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 +326,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;
|
||||||
|
|||||||
+25
@@ -4,6 +4,9 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
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}.
|
* 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;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "LeaderboardRowDTO for competitor "+competitor;
|
return "LeaderboardRowDTO for competitor "+competitor;
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
package com.sap.sailing.domain.common.tracking;
|
package com.sap.sailing.domain.common.tracking;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.common.Distance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific {@link SensorFix} for bravo devices (http://www.bravosystems.es/).
|
* Specific {@link SensorFix} for bravo devices (http://www.bravosystems.es/).
|
||||||
*
|
*
|
||||||
@@ -12,5 +14,5 @@ public interface BravoFix extends SensorFix {
|
|||||||
*
|
*
|
||||||
* @return the ride height
|
* @return the ride height
|
||||||
*/
|
*/
|
||||||
double getRideHeight();
|
Distance getRideHeight();
|
||||||
}
|
}
|
||||||
+4
-2
@@ -1,5 +1,7 @@
|
|||||||
package com.sap.sailing.domain.common.tracking.impl;
|
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.sensordata.BravoSensorDataMetadata;
|
||||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||||
@@ -32,8 +34,8 @@ public class BravoFixImpl implements BravoFix {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getRideHeight() {
|
public Distance getRideHeight() {
|
||||||
return fix.get(BravoSensorDataMetadata.INSTANCE.rideHeightColumn);
|
return new MeterDistance(fix.get(BravoSensorDataMetadata.INSTANCE.rideHeightColumn));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
-12
@@ -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.RaceDefinitionImpl;
|
||||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||||
import com.sap.sailing.domain.base.impl.WaypointImpl;
|
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.DegreeBearingImpl;
|
||||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||||
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
|
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.sensordata.BravoSensorDataMetadata;
|
||||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||||
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
|
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_TIMESTAMP2 = 120;
|
||||||
private static final long FIX_TIMESTAMP3 = 210;
|
private static final long FIX_TIMESTAMP3 = 210;
|
||||||
private static final long AFTER_LAST_FIX = FIX_TIMESTAMP3 + 1;
|
private static final long AFTER_LAST_FIX = FIX_TIMESTAMP3 + 1;
|
||||||
private static final double FIX_RIDE_HEIGHT = 1337.0;
|
private static final Distance FIX_RIDE_HEIGHT = new MeterDistance(1337.0);
|
||||||
private static final double FIX_RIDE_HEIGHT2 = 1338.0;
|
private static final Distance FIX_RIDE_HEIGHT2 = new MeterDistance(1338.0);
|
||||||
private static final double FIX_RIDE_HEIGHT3 = 1336.0;
|
private static final Distance FIX_RIDE_HEIGHT3 = new MeterDistance(1336.0);
|
||||||
private static final double FIX_TEST_VALUE = 12.0;
|
private static final double FIX_TEST_VALUE = 12.0;
|
||||||
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
|
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
|
||||||
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||||
@@ -384,20 +386,14 @@ public class SensorFixStoreAndLoadTest {
|
|||||||
public void testBravoFixIsCorrectlyWrapped() throws InterruptedException {
|
public void testBravoFixIsCorrectlyWrapped() throws InterruptedException {
|
||||||
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
regattaLog.add(new RegattaLogDeviceCompetitorBravoMappingEventImpl(new MillisecondsTimePoint(3), author, comp,
|
||||||
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
device, new MillisecondsTimePoint(START_OF_TRACKING), new MillisecondsTimePoint(MID_OF_TRACKING)));
|
||||||
|
|
||||||
addBravoFixes();
|
addBravoFixes();
|
||||||
|
|
||||||
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
FixLoaderAndTracker fixLoaderAndTracker = createFixLoaderAndTracker();
|
||||||
|
|
||||||
trackedRace.attachRaceLog(raceLog);
|
trackedRace.attachRaceLog(raceLog);
|
||||||
trackedRace.attachRegattaLog(regattaLog);
|
trackedRace.attachRegattaLog(regattaLog);
|
||||||
|
|
||||||
trackedRace.waitForLoadingToFinish();
|
trackedRace.waitForLoadingToFinish();
|
||||||
|
|
||||||
BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME);
|
BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(comp, BravoFixTrack.TRACK_NAME);
|
||||||
assertEquals(FIX_RIDE_HEIGHT,
|
assertEquals(FIX_RIDE_HEIGHT,
|
||||||
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight());
|
bravoFixTrack.getFirstFixAtOrAfter(new MillisecondsTimePoint(FIX_TIMESTAMP)).getRideHeight());
|
||||||
|
|
||||||
fixLoaderAndTracker.stop(true);
|
fixLoaderAndTracker.stop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +478,9 @@ public class SensorFixStoreAndLoadTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addBravoFixes() {
|
private void addBravoFixes() {
|
||||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT));
|
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP, FIX_RIDE_HEIGHT.getMeters()));
|
||||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2));
|
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2.getMeters()));
|
||||||
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP3, FIX_RIDE_HEIGHT3));
|
store.storeFix(device, createBravoDoubleVectorFixWithRideHeight(FIX_TIMESTAMP3, FIX_RIDE_HEIGHT3.getMeters()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private FixLoaderAndTracker createFixLoaderAndTracker() {
|
private FixLoaderAndTracker createFixLoaderAndTracker() {
|
||||||
|
|||||||
+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 Distance 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 Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -82,8 +82,8 @@ public class BravoFixTrackSerializationTest {
|
|||||||
assertRideHeight(track, testFixData.timePoint, testFixData.rideHeight);
|
assertRideHeight(track, testFixData.timePoint, testFixData.rideHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRideHeight(BravoFixTrack<Competitor> track, TimePoint timePoint, double expected) {
|
private void assertRideHeight(BravoFixTrack<Competitor> track, TimePoint timePoint, double expectedRideHeightInMeters) {
|
||||||
assertEquals(expected, track.getRideHeight(timePoint), 0.0);
|
assertEquals(expectedRideHeightInMeters, track.getRideHeight(timePoint).getMeters(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|||||||
+6
-2
@@ -1437,6 +1437,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
|||||||
} else {
|
} else {
|
||||||
entryDTO.timeSinceLastPositionFixInSeconds = null;
|
entryDTO.timeSinceLastPositionFixInSeconds = null;
|
||||||
}
|
}
|
||||||
|
final Distance averageRideHeight = trackedRace.getAverageRideHeight(competitor, timePoint);
|
||||||
|
entryDTO.averageRideHeightInMeters = averageRideHeight == null ? null : averageRideHeight.getMeters();
|
||||||
}
|
}
|
||||||
if (addLegDetails && trackedRace != null) {
|
if (addLegDetails && trackedRace != null) {
|
||||||
try {
|
try {
|
||||||
@@ -1721,11 +1723,13 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
|||||||
Double speedOverGroundInKnots;
|
Double speedOverGroundInKnots;
|
||||||
if (trackedLeg.hasFinishedLeg(timePoint)) {
|
if (trackedLeg.hasFinishedLeg(timePoint)) {
|
||||||
speedOverGroundInKnots = averageSpeedOverGround == null ? null : averageSpeedOverGround.getKnots();
|
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 {
|
} else {
|
||||||
final SpeedWithBearing speedOverGround = trackedLeg.getSpeedOverGround(timePoint);
|
final SpeedWithBearing speedOverGround = trackedLeg.getSpeedOverGround(timePoint);
|
||||||
speedOverGroundInKnots = speedOverGround == null ? null : speedOverGround.getKnots();
|
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;
|
result.currentSpeedOverGroundInKnots = speedOverGroundInKnots == null ? null : speedOverGroundInKnots;
|
||||||
Distance distanceTraveled = trackedLeg.getDistanceTraveled(timePoint);
|
Distance distanceTraveled = trackedLeg.getDistanceTraveled(timePoint);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.common.Distance;
|
||||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||||
import com.sap.sse.common.TimePoint;
|
import com.sap.sse.common.TimePoint;
|
||||||
import com.sap.sse.common.WithID;
|
import com.sap.sse.common.WithID;
|
||||||
@@ -22,7 +23,7 @@ public interface BravoFixTrack<ItemType extends WithID & Serializable> extends S
|
|||||||
* @return the ride height for the given {@link TimePoint} or <code>null</code> if the {@link TimePoint} is not in the range
|
* @return the ride height for the given {@link TimePoint} or <code>null</code> if the {@link TimePoint} is not in the range
|
||||||
* where we have fixes for.
|
* where we have fixes for.
|
||||||
*/
|
*/
|
||||||
Double getRideHeight(TimePoint timePoint);
|
Distance getRideHeight(TimePoint timePoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the average ride height for the given time range.
|
* Calculates the average ride height for the given time range.
|
||||||
@@ -34,5 +35,5 @@ public interface BravoFixTrack<ItemType extends WithID & Serializable> extends S
|
|||||||
* @return the average ride height for the given time range or <code>null</code> if there are no fixes in the given
|
* @return the average ride height for the given time range or <code>null</code> if there are no fixes in the given
|
||||||
* time range.
|
* time range.
|
||||||
*/
|
*/
|
||||||
Double getAverageRideHeight(TimePoint from, TimePoint to);
|
Distance getAverageRideHeight(TimePoint from, TimePoint to);
|
||||||
}
|
}
|
||||||
+2
-2
@@ -97,7 +97,7 @@ public interface TrackedLegOfCompetitor extends Serializable {
|
|||||||
* <code>timePoint</code>. If the competitor already completed the leg at <code>timePoint</code> and the respective
|
* <code>timePoint</code>. If the competitor already completed the leg at <code>timePoint</code> and the respective
|
||||||
* mark passing event was already received, the average ride height for the entire leg (and no further) is computed.
|
* 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 <code>null</code> if the competitor hasn't started this leg yet, otherwise the fix where the maximum speed was
|
* @return <code>null</code> 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 {
|
|||||||
* <code>timePoint</code>, returns the current ride height for this time point. If the competitor has already
|
* <code>timePoint</code>, 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.
|
* 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
|
* Computes the distance along the wind track to the wind-projected position of the race's overall leader. If leader
|
||||||
|
|||||||
@@ -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 Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint);
|
||||||
|
|
||||||
WindStore getWindStore();
|
WindStore getWindStore();
|
||||||
|
|
||||||
Competitor getOverallLeader(TimePoint timePoint);
|
Competitor getOverallLeader(TimePoint timePoint);
|
||||||
|
|||||||
+15
-10
@@ -1,10 +1,8 @@
|
|||||||
package com.sap.sailing.domain.tracking.impl;
|
package com.sap.sailing.domain.tracking.impl;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.OptionalDouble;
|
|
||||||
import java.util.Spliterator;
|
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
|
import com.sap.sailing.domain.common.Distance;
|
||||||
import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata;
|
import com.sap.sailing.domain.common.sensordata.BravoSensorDataMetadata;
|
||||||
import com.sap.sailing.domain.common.tracking.BravoFix;
|
import com.sap.sailing.domain.common.tracking.BravoFix;
|
||||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||||
@@ -34,7 +32,7 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getRideHeight(TimePoint timePoint) {
|
public Distance getRideHeight(TimePoint timePoint) {
|
||||||
BravoFix fixAfter = getFirstFixAtOrAfter(timePoint);
|
BravoFix fixAfter = getFirstFixAtOrAfter(timePoint);
|
||||||
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
if (fixAfter != null && fixAfter.getTimePoint().compareTo(timePoint) == 0) {
|
||||||
// exact match of timepoint -> no interpolation necessary
|
// exact match of timepoint -> no interpolation necessary
|
||||||
@@ -54,17 +52,24 @@ public class BravoFixTrackImpl<ItemType extends WithID & Serializable> extends S
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getAverageRideHeight(TimePoint from, TimePoint to) {
|
public Distance getAverageRideHeight(TimePoint from, TimePoint to) {
|
||||||
|
final Distance result;
|
||||||
lockForRead();
|
lockForRead();
|
||||||
try {
|
try {
|
||||||
Spliterator<BravoFix> fixes = getFixes(from, true, to, true).spliterator();
|
Distance sum = Distance.NULL;
|
||||||
OptionalDouble average = StreamSupport.stream(fixes, false).mapToDouble(BravoFix::getRideHeight).average();
|
int count = 0;
|
||||||
if (average.isPresent()) {
|
for (final BravoFix fix : getFixes(from, true, to, true)) {
|
||||||
return average.getAsDouble();
|
sum = sum.add(fix.getRideHeight());
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count > 0) {
|
||||||
|
result = sum.scale(1./count);
|
||||||
|
} else {
|
||||||
|
result = null;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
unlockAfterRead();
|
unlockAfterRead();
|
||||||
}
|
}
|
||||||
return null;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-6
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -184,7 +183,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getAverageRideHeight(TimePoint timePoint) {
|
public Distance getAverageRideHeight(TimePoint timePoint) {
|
||||||
MarkPassing legStart = getMarkPassingForLegStart();
|
MarkPassing legStart = getMarkPassingForLegStart();
|
||||||
if (legStart != null) {
|
if (legStart != null) {
|
||||||
BravoFixTrack<Competitor> track = getTrackedRace()
|
BravoFixTrack<Competitor> track = getTrackedRace()
|
||||||
@@ -677,15 +676,17 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getRideHeight(TimePoint at) {
|
public Distance getRideHeight(TimePoint at) {
|
||||||
|
final Distance result;
|
||||||
if (hasStartedLeg(at)) {
|
if (hasStartedLeg(at)) {
|
||||||
TimePoint timePoint =hasFinishedLeg(at) ? getMarkPassingForLegEnd().getTimePoint() : at;
|
TimePoint timePoint =hasFinishedLeg(at) ? getMarkPassingForLegEnd().getTimePoint() : at;
|
||||||
BravoFixTrack<Competitor> track = getTrackedRace()
|
BravoFixTrack<Competitor> track = getTrackedRace()
|
||||||
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
||||||
return track == null ? null : track.getRideHeight(timePoint);
|
result = track == null ? null : track.getRideHeight(timePoint);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
result = null;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+16
@@ -1538,6 +1538,22 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
final Distance 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 Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+41
-45
@@ -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;
|
||||||
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
|
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
|
||||||
import com.sap.sailing.domain.common.DetailType;
|
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.InvertibleComparator;
|
||||||
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
||||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||||
@@ -97,6 +98,7 @@ 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.DetailTypeColumn.LegDetailField;
|
||||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
|
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies;
|
||||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
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;
|
||||||
import com.sap.sse.common.Util.Pair;
|
import com.sap.sse.common.Util.Pair;
|
||||||
import com.sap.sse.common.filter.BinaryOperator;
|
import com.sap.sse.common.filter.BinaryOperator;
|
||||||
@@ -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));
|
||||||
@@ -1098,26 +1100,13 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
|||||||
private class RaceAverageSpeedInKnots implements LegDetailField<Double> {
|
private class RaceAverageSpeedInKnots implements LegDetailField<Double> {
|
||||||
@Override
|
@Override
|
||||||
public Double get(LeaderboardRowDTO row) {
|
public Double get(LeaderboardRowDTO row) {
|
||||||
Double result = null;
|
final Distance distanceTraveledInMeters = row.getDistanceTraveledInMeters(getRaceColumnName());
|
||||||
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceColumnName());
|
final Duration time = row.getTimeSailed(getRaceColumnName());
|
||||||
if (fieldsForRace != null && fieldsForRace.legDetails != null) {
|
final Double result;
|
||||||
double distanceTraveledInMeters = 0;
|
if (distanceTraveledInMeters != null && time != null) {
|
||||||
long timeInMilliseconds = 0;
|
result = distanceTraveledInMeters.inTime(time).getKnots();
|
||||||
for (LegEntryDTO legDetail : fieldsForRace.legDetails) {
|
} else {
|
||||||
if (legDetail != null) {
|
result = 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1299,21 +1288,7 @@ public class LeaderboardPanel extends SimplePanel implements Component<Leaderboa
|
|||||||
private class RaceDistanceTraveledInMeters implements LegDetailField<Double> {
|
private class RaceDistanceTraveledInMeters implements LegDetailField<Double> {
|
||||||
@Override
|
@Override
|
||||||
public Double get(LeaderboardRowDTO row) {
|
public Double get(LeaderboardRowDTO row) {
|
||||||
Double result = null;
|
return row.getDistanceTraveledInMeters(getRaceColumnName()).getMeters();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,27 +1421,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 RaceAverageSpeedInKnots().get(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -2941,7 +2941,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
|||||||
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace
|
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace
|
||||||
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
.<BravoFix, BravoFixTrack<Competitor>> getSensorTrack(competitor, BravoFixTrack.TRACK_NAME);
|
||||||
if (bravoFixTrack != null) {
|
if (bravoFixTrack != null) {
|
||||||
result = bravoFixTrack.getRideHeight(timePoint);
|
final Distance rideHeight = bravoFixTrack.getRideHeight(timePoint);
|
||||||
|
result = rideHeight == null ? null : rideHeight.getMeters();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+4
-4
@@ -19,12 +19,12 @@ public class BravoDataImportTest {
|
|||||||
|
|
||||||
private final DoubleVectorFixImporter bravoDataImporter = new BravoDataImporterImpl();
|
private final DoubleVectorFixImporter bravoDataImporter = new BravoDataImporterImpl();
|
||||||
private int callbackCallCount = 0;
|
private int callbackCallCount = 0;
|
||||||
private double sumRideHeight = 0.0;
|
private double sumRideHeightInMeters = 0.0;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.callbackCallCount = 0;
|
this.callbackCallCount = 0;
|
||||||
this.sumRideHeight = 0.0;
|
this.sumRideHeightInMeters = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -51,12 +51,12 @@ public class BravoDataImportTest {
|
|||||||
bravoDataImporter.importFixes(importData.getInputStream(), (fixes, device) -> {
|
bravoDataImporter.importFixes(importData.getInputStream(), (fixes, device) -> {
|
||||||
for (DoubleVectorFix fix : fixes) {
|
for (DoubleVectorFix fix : fixes) {
|
||||||
callbackCallCount++;
|
callbackCallCount++;
|
||||||
sumRideHeight += new BravoFixImpl(fix).getRideHeight();
|
sumRideHeightInMeters += new BravoFixImpl(fix).getRideHeight().getMeters();
|
||||||
}
|
}
|
||||||
}, "filename", "source");
|
}, "filename", "source");
|
||||||
Assert.assertEquals(importData.expectedFixesCount, callbackCallCount);
|
Assert.assertEquals(importData.expectedFixesCount, callbackCallCount);
|
||||||
Assert.assertEquals(importData.expectedAverageRideHeight,
|
Assert.assertEquals(importData.expectedAverageRideHeight,
|
||||||
callbackCallCount == 0 ? sumRideHeight : sumRideHeight / callbackCallCount, 0.00001);
|
callbackCallCount == 0 ? sumRideHeightInMeters : sumRideHeightInMeters / callbackCallCount, 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum ImportData {
|
private enum ImportData {
|
||||||
|
|||||||
+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 Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user