Merge branch 'master' into mark-rounding-inference

This commit is contained in:
Axel Uhl committed 2015-03-29 17:37:34 +02:00
commit 297f91a098
5 files changed
+64 -11

No files matched your search

@@ -47,10 +47,18 @@ public interface ReadonlyRaceState extends RaceStateEventProcessor {
RaceLog getRaceLog();
/**
* Gets the currently attached {@link ReadonlyRacingProcedure}.
* Gets the currently attached {@link ReadonlyRacingProcedure}, providing a default in case there is none provided
* in the race log nor the regatta configuration.
*/
ReadonlyRacingProcedure getRacingProcedure();
/**
* If no racing procedure is defined in the underlying race log, <code>null</code> is returned; otherwise
* the racing procedure as it would be returned by {@link #getRacingProcedure()}.
* @return
*/
ReadonlyRacingProcedure getRacingProcedureNoFallback();
/**
* Gets the currently attached {@link ReadonlyRacingProcedure}. Use this method to avoid casting in cases you are
* sure about the {@link ReadonlyRacingProcedure}'s type.
@@ -92,7 +92,18 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
private final LastPublishedCourseDesignFinder courseDesignerAnalyzer;
private final LastWindFixFinder lastWindFixAnalyzer;
/**
* The cached racing procedure type. If no racing procedure type specification is found in the underlying race log,
* a default is taken from {@link #fallbackInitialProcedureType}.
*/
private RacingProcedureType cachedRacingProcedureType;
/**
* The result of {@link #determineInitialProcedureType()}; may be {@link RacingProcedureType#UNKNOWN} in case no
* specification is found in the underlying race log.
*/
private RacingProcedureType cachedRacingProcedureTypeNoFallback;
private RaceLogRaceStatus cachedRaceStatus;
private int cachedPassId;
private TimePoint cachedStartTime;
@@ -130,7 +141,12 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
this.courseDesignerAnalyzer = new LastPublishedCourseDesignFinder(raceLog);
this.lastWindFixAnalyzer = new LastWindFixFinder(raceLog);
this.cachedRacingProcedureType = determineInitialProcedureType();
this.cachedRacingProcedureTypeNoFallback = determineInitialProcedureType();
if (this.cachedRacingProcedureTypeNoFallback == null || this.cachedRacingProcedureTypeNoFallback == RacingProcedureType.UNKNOWN) {
this.cachedRacingProcedureType = fallbackInitialProcedureType;
} else {
cachedRacingProcedureType = cachedRacingProcedureTypeNoFallback;
}
this.cachedRaceStatus = RaceLogRaceStatus.UNKNOWN;
this.cachedPassId = raceLog.getCurrentPassId();
// see resolved bug 2083: make sure the listener registration is "weak" in the sense that it is removed when
@@ -148,11 +164,8 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
RacingProcedureType inRaceLogType = racingProcedureAnalyzer.analyze();
if (inRaceLogType != RacingProcedureType.UNKNOWN) {
return inRaceLogType;
} else if (configuration.getDefaultRacingProcedureType() != null
&& configuration.getDefaultRacingProcedureType() != RacingProcedureType.UNKNOWN) {
return configuration.getDefaultRacingProcedureType();
} else {
return fallbackInitialProcedureType;
return configuration.getDefaultRacingProcedureType();
}
}
@@ -165,6 +178,17 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
public ReadonlyRacingProcedure getRacingProcedure() {
return racingProcedure;
}
@Override
public ReadonlyRacingProcedure getRacingProcedureNoFallback() {
final ReadonlyRacingProcedure result;
if (cachedRacingProcedureTypeNoFallback == null || cachedRacingProcedureTypeNoFallback == RacingProcedureType.UNKNOWN) {
result = null;
} else {
result = getRacingProcedure();
}
return result;
}
@SuppressWarnings("unchecked")
@Override
@@ -22,6 +22,7 @@ import java.util.NavigableSet;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
@@ -253,6 +254,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
private transient Object cacheInvalidationTimerLock;
protected transient ConcurrentHashMap<Serializable, RaceLog> attachedRaceLogs;
/**
* Holds optional race states for the race logs in {@link #attachedRaceLogs}. By using a {@link WeakHashMap},
* these race states can be garbage-collected when the race log is no longer attached. The race states are created
* lazily, synchronizing on this weak hash map.
*/
protected final transient WeakHashMap<RaceLog, ReadonlyRaceState> raceStates;
protected transient ConcurrentHashMap<Serializable, RegattaLog> attachedRegattaLogs;
@@ -307,6 +315,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
long delayToLiveInMillis, final long millisecondsOverWhichToAverageWind,
long millisecondsOverWhichToAverageSpeed, long delayForWindEstimationCacheInvalidation, boolean useMarkPassingCalculator) {
super(race, trackedRegatta, windStore, millisecondsOverWhichToAverageWind);
raceStates = new WeakHashMap<>();
shortTimeWindCache = new ShortTimeWindCache(this, millisecondsOverWhichToAverageWind / 2);
locksForMarkPassings = new IdentityHashMap<>();
attachedRaceLogs = new ConcurrentHashMap<>();
@@ -2858,6 +2867,18 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
loadFixesForLog(raceLog, attachedRaceLogs);
}
private ReadonlyRaceState getRaceState(RaceLog raceLog) {
ReadonlyRaceState result;
synchronized (raceStates) {
result = raceStates.get(raceLog);
if (result == null) {
result = RaceStateImpl.create(raceLog);
raceStates.put(raceLog, result);
}
}
return result;
}
@Override
public void attachRegattaLog(RegattaLog regattaLog) {
loadFixesForLog(regattaLog, attachedRegattaLogs);
@@ -3333,8 +3354,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
public Boolean isGateStart() {
Boolean result = null;
for (RaceLog raceLog : attachedRaceLogs.values()) {
ReadonlyRaceState raceState = RaceStateImpl.create(raceLog);
ReadonlyRacingProcedure procedure = raceState.getRacingProcedure();
ReadonlyRaceState raceState = getRaceState(raceLog);
ReadonlyRacingProcedure procedure = raceState.getRacingProcedureNoFallback();
if (procedure != null && procedure.getType() != null) {
result = procedure.getType() == RacingProcedureType.GateStart;
break;
@@ -3348,7 +3369,7 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
final Distance result;
final Leg startLeg = getRace().getCourse().getFirstLeg();
final TrackedLegOfCompetitor competitorLeg;
if (startLeg != null && isGateStart() == true && (competitorLeg=getTrackedLeg(competitor, startLeg)).hasStartedLeg(timePoint)) {
if (startLeg != null && isGateStart() == Boolean.TRUE && (competitorLeg=getTrackedLeg(competitor, startLeg)).hasStartedLeg(timePoint)) {
TimePoint competitorLegStartTime = competitorLeg.getStartTime();
final Mark portMarkOfStartLine = getStartLine(competitorLegStartTime).getPortMarkWhileApproachingLine();
final Position portSideOfStartLinePosition = getOrCreateTrack(portMarkOfStartLine)
@@ -110,7 +110,7 @@ eventRegattaRacesLegendWind=Wind Data
eventRegattaRacesLegendVideo=Video Stream
eventRegattaRacesLegendAudio=Audio Stream
eventSponsorsTitle=Event Sponsorships
footerCopyright=\u00A9 2014 SAP Sailing Analytics
footerCopyright=\u00A9 2015 SAP Sailing Analytics
footerLanguage=SAP Sailing offered in
footerLegal=Legal Disclosure
footerPrivacy=Privacy
@@ -110,7 +110,7 @@ eventRegattaRacesLegendWind=Winddaten
eventRegattaRacesLegendVideo=Video Stream
eventRegattaRacesLegendAudio=Audio Stream
eventSponsorsTitle=Veranstaltungssponsoren
footerCopyright=\u00A9 2014 SAP Sailing Analytics
footerCopyright=\u00A9 2015 SAP Sailing Analytics
footerLanguage=SAP Sailing in
footerLegal=Impressum
footerPrivacy=Datenschutz