mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 05:11:04 +00:00
started to introduce a flag on TrackedRace identifying whether the first leg is known to be upwind
This commit is contained in:
1 parent
c8f8262737
commit
82077866ce
19 files changed
+101
-30
No files matched your search
@@ -22,4 +22,17 @@ public interface BoatClass extends Named {
|
||||
double getMinimumAngleBetweenDifferentTacksDownwind();
|
||||
|
||||
double getMinimumAngleBetweenDifferentTacksUpwind();
|
||||
|
||||
/**
|
||||
* Most olympic boat classes start their race with an upwind leg. Some other classes such
|
||||
* as the Extreme Sailing Series / Extreme40 do not necessarily start with an upwind leg.
|
||||
* Knowing this is relevant for the wind estimation fallback strategy. If the first leg of
|
||||
* a boat class doesn't have to be an upwind leg it's not permissible to estimate the wind
|
||||
* based on the course layout.<p>
|
||||
*
|
||||
* The result of calling this method suggests a good default for this boat class. It is
|
||||
* <em>not</em> an authoritative, prescriptive value. Races with this boat class may still
|
||||
* start with a non-upwind leg even though this method returns <code>true</code>.
|
||||
*/
|
||||
boolean typicallyStartsUpwind();
|
||||
}
|
||||
@@ -20,5 +20,5 @@ public interface DomainFactory {
|
||||
|
||||
MarkPassing createMarkPassing(TimePoint timePoint, Waypoint waypoint, Competitor competitor);
|
||||
|
||||
BoatClass getOrCreateBoatClass(String name);
|
||||
BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind);
|
||||
}
|
||||
@@ -19,8 +19,11 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
|
||||
|
||||
private final long approximateManeuverDurationInMilliseconds;
|
||||
|
||||
public BoatClassImpl(String name) {
|
||||
private final boolean alwaysStartsUpwind;
|
||||
|
||||
public BoatClassImpl(String name, boolean alwaysStartsUpwind) {
|
||||
super(name);
|
||||
this.alwaysStartsUpwind = alwaysStartsUpwind;
|
||||
approximateManeuverDurationInMilliseconds = 8000; // as discussed with Dennis Gehrlein
|
||||
}
|
||||
|
||||
@@ -49,4 +52,9 @@ public class BoatClassImpl extends NamedImpl implements BoatClass {
|
||||
return MAXIMUM_DISTANCE_FOR_COURSE_APPROXIMATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean typicallyStartsUpwind() {
|
||||
return alwaysStartsUpwind;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -76,11 +76,11 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoatClass getOrCreateBoatClass(String name) {
|
||||
public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) {
|
||||
synchronized (boatClassCache) {
|
||||
BoatClass result = boatClassCache.get(name);
|
||||
if (result == null) {
|
||||
result = new BoatClassImpl(name);
|
||||
result = new BoatClassImpl(name, typicallyStartsUpwind);
|
||||
boatClassCache.put(name, result);
|
||||
}
|
||||
return result;
|
||||
|
||||
+6
@@ -45,4 +45,10 @@ public interface DynamicTrackedRace extends TrackedRace {
|
||||
void setMillisecondsOverWhichToAverageWind(long millisecondsOverWhichToAverageWind);
|
||||
|
||||
DynamicTrackedEvent getTrackedEvent();
|
||||
|
||||
/**
|
||||
* If and only if <code>raceIsKnownToStartUpwind</code> is <code>true</code>, this tracked race is allowed to use
|
||||
* the start leg's direction as a fallback for estimating the wind direction.
|
||||
*/
|
||||
void setRaceIsKnownToStartUpwind(boolean raceIsKnownToStartUpwind);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.sap.sailing.domain.base.Tack;
|
||||
import com.sap.sailing.domain.base.TimePoint;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.DouglasPeucker;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg.LegType;
|
||||
|
||||
/**
|
||||
* Live tracking data of a single race. The race follows a defined {@link Course} with a sequence of {@link Leg}s. The
|
||||
@@ -221,4 +222,12 @@ public interface TrackedRace {
|
||||
* this race between <code>from</code> and <code>to</code>.
|
||||
*/
|
||||
List<Maneuver> getManeuvers(Competitor competitor, TimePoint from, TimePoint to) throws NoWindException;
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if this race is known to start with an {@link LegType#UPWIND upwind} leg.
|
||||
* If this is the case, the wind estimation may default to using the first leg's direction at race start
|
||||
* time as the direction the wind comes from.
|
||||
*/
|
||||
boolean raceIsKnownToStartUpwind();
|
||||
|
||||
}
|
||||
+13
@@ -35,9 +35,12 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
|
||||
private Set<RaceChangeListener<Competitor>> listeners;
|
||||
|
||||
private boolean raceIsKnownToStartUpwind;
|
||||
|
||||
public DynamicTrackedRaceImpl(TrackedEvent trackedEvent, RaceDefinition race,
|
||||
WindStore windStore, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
|
||||
super(trackedEvent, race, windStore, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed);
|
||||
this.raceIsKnownToStartUpwind = race.getBoatClass().typicallyStartsUpwind();
|
||||
for (Competitor competitor : getRace().getCompetitors()) {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = getTrack(competitor);
|
||||
track.addListener(this);
|
||||
@@ -281,4 +284,14 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
return (DynamicTrackedEvent) super.getTrackedEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRaceIsKnownToStartUpwind(boolean raceIsKnownToStartUpwind) {
|
||||
this.raceIsKnownToStartUpwind = raceIsKnownToStartUpwind;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean raceIsKnownToStartUpwind() {
|
||||
return raceIsKnownToStartUpwind;
|
||||
}
|
||||
|
||||
}
|
||||
+6
-5
@@ -112,7 +112,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
private boolean warnedOfNoWindFromSelectedSource;
|
||||
|
||||
private boolean warnedOfUsingLegDirectionAsWindEstimation;
|
||||
|
||||
|
||||
public TrackedRaceImpl(TrackedEvent trackedEvent, RaceDefinition race, WindStore windStore,
|
||||
long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed) {
|
||||
super();
|
||||
@@ -419,13 +419,14 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
if (result == null && raceIsKnownToStartUpwind()) {
|
||||
if (!warnedOfUsingLegDirectionAsWindEstimation) {
|
||||
logger.warning("Found no other wind settings either; using starting leg direction as guess for wind direction. Force assumed as 1 knot."+
|
||||
" Future warnings of this type will be suppressed for this race.");
|
||||
logger.warning("Found no other wind settings either; using starting leg direction at start time as guess for wind direction. "
|
||||
+ "Force assumed as 1 knot. Future warnings of this type will be suppressed for this race.");
|
||||
warnedOfUsingLegDirectionAsWindEstimation = true;
|
||||
}
|
||||
result = getDirectionFromStartToNextMark(at);
|
||||
TimePoint starttime = getStart();
|
||||
result = getDirectionFromStartToNextMark(starttime == null ? at : starttime);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in new issue
Block a user