mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 21:25:38 +00:00
bug6068: introduced four new @Statistic methods for wind axis-based XTE
This commit is contained in:
+4
@@ -253,6 +253,10 @@ XTE=Cross-Track Error, signed (- = left, + = right)
|
||||
AbsoluteXTE=Absolute Cross-Track Error, unsigned
|
||||
XTERelativeSigned=Relative Cross-Track Error, signed (-1 = 1/2 leg length left, 0 = middle, +1 = 1/2 leg length right)
|
||||
XTERelativeUnsigned=Relative Cross-Track Error, unsigned (0 = middle, 1 = 1/2 leg length out)
|
||||
XTEToWindAxisUnsigned=Cross-Track Error to Wind Axis, unsigned
|
||||
XTEToWindAxisSigned=Cross-Track Error to Wind Axis, signed (- = left, + = right)
|
||||
XTEToWindAxisRelativeUnsigned=Relative Cross-Track Error to Wind Axis, unsigned (0 = middle, 1 = 1/2 leg length out)
|
||||
XTEToWindAxisRelativeSigned=Relative Cross-Track Error to Wind Axis, signed (-1 = 1/2 leg length left, 0 = middle, +1 = 1/2 leg length right)
|
||||
Day=Day
|
||||
CompetitorDay=Competitor Day
|
||||
CompetitorDaySailingDomainRetrieverChain=Competitor-Day for race
|
||||
|
||||
+4
@@ -256,6 +256,10 @@ XTE=Absolute Querabweichung, vorzeichenbehaftet (- = links, + = rechts)
|
||||
AbsoluteXTE=Absolute Querabweichung, ohne Vorzeichen
|
||||
XTERelativeSigned=Relative Querabweichung, mit Vorzeichen (-1 = 1/2 Schenkellänge links, 0 = Mitte, +1 = 1/2 Schenkellänge rechts)
|
||||
XTERelativeUnsigned=Relative Querabweichung, ohne Vorzeichen (0 = Mitte, 1 = ganz aussen)
|
||||
XTEToWindAxisUnsigned=Querabweichung zur Windachse, ohne Vorzeichen
|
||||
XTEToWindAxisSigned=Querabweichung zur Windachse, vorzeichenbehaftet (- = links, + = rechts)
|
||||
XTEToWindAxisRelativeUnsigned=Relative Querabweichung zur Windachse, mit Vorzeichen (-1 = 1/2 Schenkellänge links, 0 = Mitte, +1 = 1/2 Schenkellänge rechts)
|
||||
XTEToWindAxisRelativeSigned=Relative Querabweichung zur Windachse, ohne Vorzeichen (0 = Mitte, 1 = ganz aussen)
|
||||
Day=Tag
|
||||
CompetitorDay=Teilnehmer-Tag
|
||||
CompetitorDaySailingDomainRetrieverChain=Teilnehmer-Tag für Wettfahrt
|
||||
|
||||
+30
@@ -42,6 +42,36 @@ public interface HasGPSFixContext {
|
||||
@Statistic(messageKey = "XTERelativeUnsigned", resultDecimals = 2)
|
||||
Double getRelativeXTEUnsigned();
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint.
|
||||
*/
|
||||
@Statistic(messageKey = "XTEToWindAxisUnsigned", resultDecimals = 2)
|
||||
Distance getXTEToWindAxisUnsigned();
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint.
|
||||
*/
|
||||
@Statistic(messageKey = "XTEToWindAxisSigned", resultDecimals = 2)
|
||||
Distance getXTEToWindAxisSigned();
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint. That distance is divided
|
||||
* by half the leg length.
|
||||
*/
|
||||
@Statistic(messageKey = "XTEToWindAxisRelativeUnsigned", resultDecimals = 2)
|
||||
Double getXTEToWindAxisRelativeUnsigned();
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint. That distance is divided
|
||||
* by half the leg length.
|
||||
*/
|
||||
@Statistic(messageKey = "XTEToWindAxisRelativeSigned", resultDecimals = 2)
|
||||
Double getXTEToWindAxisRelativeSigned();
|
||||
|
||||
@Statistic(messageKey = "SmoothedSpeed", resultDecimals = 2)
|
||||
Speed getSmoothedSpeed();
|
||||
|
||||
|
||||
+20
@@ -149,4 +149,24 @@ public class GPSFixWithContext implements HasGPSFixContext {
|
||||
final double fractionSailed = Math.max(0, legWindwardDistance.add(windwardDistanceToGo.scale(-1)).divide(legWindwardDistance));
|
||||
return (int) Math.min(10, 1+10*fractionSailed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getXTEToWindAxisUnsigned() {
|
||||
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getUnsignedCrossTrackErrorToWindAxis(getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getXTEToWindAxisSigned() {
|
||||
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getSignedCrossTrackErrorToWindAxis(getTimePoint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getXTEToWindAxisRelativeUnsigned() {
|
||||
return getRelativeXTE(TrackedLegOfCompetitor::getUnsignedCrossTrackErrorToWindAxis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getXTEToWindAxisRelativeSigned() {
|
||||
return getRelativeXTE(TrackedLegOfCompetitor::getSignedCrossTrackErrorToWindAxis);
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,19 @@ public interface TrackedLeg extends Serializable {
|
||||
*/
|
||||
Distance getSignedCrossTrackError(Position p, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Returns the (unsigned) distance of <code>p</code> to this leg's wind axis attached to the leg's end
|
||||
* waypoint at <code>timePoint</code>.
|
||||
*/
|
||||
Distance getUnsignedCrossTrackErrorToWindAxis(Position p, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Returns the (unsigned) distance of <code>p</code> to this leg's wind axis attached to the leg's end
|
||||
* waypoint at <code>timePoint</code>. Negative distances mean "left" of the
|
||||
* wind axis, looking in the direction of the leg, positive distances mean "right."
|
||||
*/
|
||||
Distance getSignedCrossTrackErrorToWindAxis(Position p, TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Must be called when the start and finish waypoint of this leg may have changed.
|
||||
*/
|
||||
|
||||
+12
@@ -325,6 +325,18 @@ public interface TrackedLegOfCompetitor extends Serializable {
|
||||
* @return {@code null} if the competitor has not started or already finished the leg
|
||||
*/
|
||||
Distance getSignedCrossTrackError(TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint.
|
||||
*/
|
||||
Distance getUnsignedCrossTrackErrorToWindAxis(TimePoint timePoint);
|
||||
|
||||
/**
|
||||
* Instead of projecting onto the course middle line connecting start and end of the leg,
|
||||
* projects onto the wind axis, attached to the leg's end waypoint.
|
||||
*/
|
||||
Distance getSignedCrossTrackErrorToWindAxis(TimePoint timePoint);
|
||||
|
||||
TrackedLeg getTrackedLeg();
|
||||
|
||||
|
||||
+18
-4
@@ -393,16 +393,30 @@ public class TrackedLegImpl implements TrackedLeg {
|
||||
|
||||
@Override
|
||||
public Distance getAbsoluteCrossTrackError(Position p, TimePoint timePoint) {
|
||||
final Position approximatePosition = getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint);
|
||||
final Position approximateLegFromPosition = getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint);
|
||||
final Bearing legBearing = getLegBearing(timePoint);
|
||||
return approximatePosition==null || legBearing==null ? null : p.absoluteCrossTrackError(approximatePosition, legBearing);
|
||||
return approximateLegFromPosition==null || legBearing==null ? null : p.absoluteCrossTrackError(approximateLegFromPosition, legBearing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getSignedCrossTrackError(Position p, TimePoint timePoint) {
|
||||
final Position approximatePosition = getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint);
|
||||
final Position approximateLegFromPosition = getTrackedRace().getApproximatePosition(getLeg().getFrom(), timePoint);
|
||||
final Bearing legBearing = getLegBearing(timePoint);
|
||||
return approximatePosition==null || legBearing==null ? null : p.crossTrackError(approximatePosition, legBearing);
|
||||
return approximateLegFromPosition==null || legBearing==null ? null : p.crossTrackError(approximateLegFromPosition, legBearing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getUnsignedCrossTrackErrorToWindAxis(Position p, TimePoint timePoint) {
|
||||
final Position approximateLegToPosition = getTrackedRace().getApproximatePosition(getLeg().getTo(), timePoint);
|
||||
final Bearing windAxis = getWind(p, timePoint, getTrackedRace().getWindSourcesToExclude()).getFrom(); // the "from" wind direction, not "to"
|
||||
return approximateLegToPosition==null || windAxis==null ? null : p.absoluteCrossTrackError(approximateLegToPosition, windAxis);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getSignedCrossTrackErrorToWindAxis(Position p, TimePoint timePoint) {
|
||||
final Position approximateLegToPosition = getTrackedRace().getApproximatePosition(getLeg().getTo(), timePoint);
|
||||
final Bearing windAxis = getWind(p, timePoint, getTrackedRace().getWindSourcesToExclude()).getFrom(); // the "from" wind direction, not "to"
|
||||
return approximateLegToPosition==null || windAxis==null ? null : p.crossTrackError(approximateLegToPosition, windAxis);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+21
-18
@@ -26,6 +26,7 @@ import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache;
|
||||
import com.sap.sailing.domain.tracking.WindPositionMode;
|
||||
@@ -543,7 +544,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
||||
@Override
|
||||
public Distance getAverageAbsoluteCrossTrackError(TimePoint timePoint, boolean waitForLatestAnalysis) {
|
||||
final Distance result;
|
||||
MarkPassing legStart = getMarkPassingForLegStart();
|
||||
final MarkPassing legStart = getMarkPassingForLegStart();
|
||||
if (legStart != null) {
|
||||
final TimePoint to = getTimePointNotAfterFinishingOfLeg(timePoint);
|
||||
if (to != null) {
|
||||
@@ -575,15 +576,14 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getAbsoluteCrossTrackError(TimePoint timePoint) {
|
||||
|
||||
private Distance getSomeCrossTrackError(TimePoint timePoint, BiFunction<TrackedLeg, Position, Distance> crossTrackCalculatorAtTimePoint) {
|
||||
final Distance result;
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> track = getTrackedRace().getTrack(getCompetitor());
|
||||
if (track != null) {
|
||||
final Position estimatedPosition = track.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
if (estimatedPosition != null) {
|
||||
result = getTrackedLeg().getAbsoluteCrossTrackError(estimatedPosition, timePoint);
|
||||
result = crossTrackCalculatorAtTimePoint.apply(getTrackedLeg(), estimatedPosition);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
@@ -593,21 +593,24 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getAbsoluteCrossTrackError(TimePoint timePoint) {
|
||||
return getSomeCrossTrackError(timePoint, (trackedLeg, estimatedPosition)->getTrackedLeg().getAbsoluteCrossTrackError(estimatedPosition, timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getSignedCrossTrackError(TimePoint timePoint) {
|
||||
final Distance result;
|
||||
final GPSFixTrack<Competitor, GPSFixMoving> track = getTrackedRace().getTrack(getCompetitor());
|
||||
if (track != null) {
|
||||
final Position estimatedPosition = track.getEstimatedPosition(timePoint, /* extrapolate */ true);
|
||||
if (estimatedPosition != null) {
|
||||
result = getTrackedLeg().getSignedCrossTrackError(estimatedPosition, timePoint);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
return getSomeCrossTrackError(timePoint, (trackedLeg, estimatedPosition)->getTrackedLeg().getSignedCrossTrackError(estimatedPosition, timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getUnsignedCrossTrackErrorToWindAxis(TimePoint timePoint) {
|
||||
return getSomeCrossTrackError(timePoint, (trackedLeg, estimatedPosition)->getTrackedLeg().getUnsignedCrossTrackErrorToWindAxis(estimatedPosition, timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getSignedCrossTrackErrorToWindAxis(TimePoint timePoint) {
|
||||
return getSomeCrossTrackError(timePoint, (trackedLeg, estimatedPosition)->getTrackedLeg().getSignedCrossTrackErrorToWindAxis(estimatedPosition, timePoint));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user