added failing test case for averaging a single wind fix with useSpeed=false

This commit is contained in:
Axel Uhl
2012-03-12 17:59:46 +01:00
parent 5791700bdd
commit 0ba0dc0212
4 changed files with 47 additions and 7 deletions
@@ -162,6 +162,22 @@ public class ConfidenceTest {
assertEquals(135, average.getObject().getBearing().getDegrees(), 0.00000001);
}
@Test
public void testAveragingOneWindWithUseSpeedFalse() {
WindWithConfidence<TimePoint> d1 = new WindWithConfidenceImpl<TimePoint>(new WindImpl(new DegreePosition(1, 0),
new MillisecondsTimePoint(20), new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(180))), /* confidence */
0.5, /* relativeTo */new MillisecondsTimePoint(20), /* useSpeed */ false);
ConfidenceBasedAverager<ScalableWind, Wind, TimePoint> averager = ConfidenceFactory.INSTANCE
.createAverager(ConfidenceFactory.INSTANCE.createHyperbolicTimeDifferenceWeigher(1000));
List<WindWithConfidence<TimePoint>> list = Arrays.asList(d1);
HasConfidence<ScalableWind, Wind, TimePoint> average = averager.getAverage(list, new MillisecondsTimePoint(20));
assertEquals(1.0, average.getObject().getPosition().getLatDeg(), 0.00000001);
assertEquals(0.0, average.getObject().getPosition().getLngDeg(), 0.00000001);
assertEquals(20, average.getObject().getTimePoint().asMillis());
assertEquals(10, average.getObject().getKnots(), 0.00000001);
assertEquals(180, average.getObject().getBearing().getDegrees(), 0.00000001);
}
@Test
public void testAveragingWithFourWindsTwoOfWhichHaveUseSpeedFalse() {
WindWithConfidence<TimePoint> d1 = new WindWithConfidenceImpl<TimePoint>(new WindImpl(new DegreePosition(1, 0),
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.base.impl.ScalablePosition;
import com.sap.sailing.domain.base.impl.ScalableSpeedWithBearing;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.confidence.ScalableValue;
import com.sap.sailing.domain.tracking.Wind;
@@ -19,32 +20,50 @@ public class ScalableWind implements ScalableValue<ScalableWind, Wind> {
private final double scaledTimePointSumInMilliseconds;
private final ScalableSpeedWithBearing scalableSpeedWithBearing;
/**
* Speeds are combined separately from the other values. A {@link ScalableWind} may use its {@link #useSpeed} flag
* to keep its speed value from being considered during addition with other values that do use their speed. For this
* case, the confidence sum for the speed needs to be passed along so that during {@link #divide(double)} the speed
* can be divided by a different divisor. Must be 0.0 in case {@link #useSpeed} is <code>false</code>.
*/
private final double speedConfidenceSum;
/**
* if <code>false</code>, the {@link ScalableSpeedWithBearing}'s speed is ignored during an {@link #add(ScalableValue)} operation
* with another {@link ScalableWind} object for which {@link #useSpeed} is <code>true</code>.
*/
private final boolean useSpeed;
public ScalableWind(Wind wind, boolean useSpeed) {
/**
* @param speedConfidenceSum must be <code>0.0</code> if <code>useSpeed==false</code>
*/
public ScalableWind(Wind wind, boolean useSpeed, double speedConfidenceSum) {
assert useSpeed || speedConfidenceSum==0.0;
this.scalablePosition = wind.getPosition() == null ? null : new ScalablePosition(wind.getPosition());
this.scaledTimePointSumInMilliseconds = wind.getTimePoint().asMillis();
this.scalableSpeedWithBearing = new ScalableSpeedWithBearing(wind);
this.useSpeed = useSpeed;
this.speedConfidenceSum = speedConfidenceSum;
}
/**
* @param speedConfidenceSum must be <code>0.0</code> if <code>useSpeed==false</code>
*/
private ScalableWind(ScalablePosition scalablePosition, double scaledTimePointSumInMilliseconds,
ScalableSpeedWithBearing scalableSpeedWithBearing, boolean useSpeed) {
ScalableSpeedWithBearing scalableSpeedWithBearing, boolean useSpeed, double speedConfidenceSum) {
super();
assert useSpeed || speedConfidenceSum==0.0;
this.scalablePosition = scalablePosition;
this.scaledTimePointSumInMilliseconds = scaledTimePointSumInMilliseconds;
this.scalableSpeedWithBearing = scalableSpeedWithBearing;
this.useSpeed = useSpeed;
this.speedConfidenceSum = speedConfidenceSum;
}
@Override
public ScalableWind multiply(double factor) {
return new ScalableWind(scalablePosition == null ? null : scalablePosition.multiply(factor),
factor * scaledTimePointSumInMilliseconds, scalableSpeedWithBearing.multiply(factor), useSpeed);
factor * scaledTimePointSumInMilliseconds, scalableSpeedWithBearing.multiply(factor), useSpeed, factor*speedConfidenceSum);
}
/**
@@ -57,6 +76,7 @@ public class ScalableWind implements ScalableValue<ScalableWind, Wind> {
public ScalableWind add(ScalableValue<ScalableWind, Wind> t) {
ScalableSpeedWithBearing thisSSWB;
ScalableSpeedWithBearing tSSWB;
double newSpeedConfidenceSum = useSpeed ? speedConfidenceSum : 0.0;
if (this.useSpeed || (t instanceof ScalableWind && !((ScalableWind) t).useSpeed)) {
thisSSWB = this.scalableSpeedWithBearing;
} else {
@@ -64,6 +84,7 @@ public class ScalableWind implements ScalableValue<ScalableWind, Wind> {
thisSSWB = new ScalableSpeedWithBearing(new KnotSpeedWithBearingImpl(/* wind "is a" speed */ t.getValue().divide(1.0).getKnots(),
this.scalableSpeedWithBearing.divide(1.0).getBearing()));
}
newSpeedConfidenceSum += (t instanceof ScalableWind && ((ScalableWind) t).useSpeed) ? ((ScalableWind) t).speedConfidenceSum : 0.0;
if (t instanceof ScalableWind && ((ScalableWind) t).useSpeed || !this.useSpeed) {
tSSWB = ((ScalableWind) t).scalableSpeedWithBearing;
} else {
@@ -73,13 +94,17 @@ public class ScalableWind implements ScalableValue<ScalableWind, Wind> {
}
return new ScalableWind(scalablePosition == null ? t.getValue().scalablePosition : scalablePosition.add(t.getValue().scalablePosition),
scaledTimePointSumInMilliseconds+t.getValue().scaledTimePointSumInMilliseconds,
thisSSWB.add(tSSWB), useSpeed || (t instanceof ScalableWind) && ((ScalableWind) t).useSpeed);
thisSSWB.add(tSSWB), useSpeed || (t instanceof ScalableWind) && ((ScalableWind) t).useSpeed, newSpeedConfidenceSum);
}
@Override
public Wind divide(double divisor) {
// TODO this is ugly; if we need to keep the confidence sum for speed in the scalable object, we should also keep the confidence sum for all other values in the scalable value
Bearing resultBearing = scalableSpeedWithBearing.divide(divisor).getBearing();
double resultSpeedInKnots = scalableSpeedWithBearing.divide(1.0).getKnots() / speedConfidenceSum;
return new WindImpl(scalablePosition == null ? null : scalablePosition.divide(divisor), new MillisecondsTimePoint(
(long) (scaledTimePointSumInMilliseconds / divisor)), scalableSpeedWithBearing.divide(divisor));
(long) (scaledTimePointSumInMilliseconds / divisor)),
new KnotSpeedWithBearingImpl(resultSpeedInKnots, resultBearing));
}
@Override
@@ -14,7 +14,7 @@ public class WindWithConfidenceImpl<RelativeTo> extends HasConfidenceImpl<Scalab
@Override
public ScalableWind getScalableValue() {
return new ScalableWind(getObject(), useSpeed);
return new ScalableWind(getObject(), useSpeed, /* speedConfidenceSum */ useSpeed?1.0:0.0);
}
@Override
@@ -917,7 +917,6 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
*/
protected GPSFixDTO getBoatFix(CompetitorDTO competitorDTO) {
return fixes.containsKey(competitorDTO) ? fixes.get(competitorDTO).get(lastShownFix.get(competitorDTO)) : null;
return competitorFixes == null ? null : competitorFixes.get(lastShownFix.get(competitorDTO));
}
/**