From 0935a5afea360a1c6e2594d577c2d1599a1c1c10 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 9 Mar 2012 11:23:48 +0100 Subject: [PATCH] fixed caching problem in getDirectionFromStartToNextMark; fixed bug 388 (course-based wind track extended) --- .../impl/CourseBasedWindTrackImpl.java | 18 ++++++-- .../domain/tracking/impl/TrackedRaceImpl.java | 42 ++++++++++++------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseBasedWindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseBasedWindTrackImpl.java index b95f34c130b..87bd46253d4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseBasedWindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/CourseBasedWindTrackImpl.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking.impl; import java.util.NavigableSet; +import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.Wind; @@ -19,6 +20,12 @@ import com.sap.sailing.util.impl.UnmodifiableNavigableSet; * */ public class CourseBasedWindTrackImpl extends WindTrackImpl { + /** + * The first leg's direction will be measured this many milliseconds before the estimated race start time, + * at estimated race start time and this many milliseconds after estimated race start time. + */ + private final long MILLISECONDS_AROUND_START_TO_TRACK = 30000l; + private final TrackedRace trackedRace; private static final NavigableSet empty = new UnmodifiableNavigableSet(new ArrayListNavigableSet(WindComparator.INSTANCE)); @@ -33,10 +40,13 @@ public class CourseBasedWindTrackImpl extends WindTrackImpl { if (trackedRace.raceIsKnownToStartUpwind()) { TimePoint startTime = trackedRace.getStart(); if (startTime != null) { - result = new ArrayListNavigableSet(1, WindComparator.INSTANCE); - final Wind directionFromStartToNextMark = trackedRace.getDirectionFromStartToNextMark(startTime); - if (directionFromStartToNextMark != null) { - result.add(directionFromStartToNextMark); + result = new ArrayListNavigableSet(3, WindComparator.INSTANCE); + for (long t = startTime.asMillis() - MILLISECONDS_AROUND_START_TO_TRACK; t <= startTime.asMillis() + + MILLISECONDS_AROUND_START_TO_TRACK; t += MILLISECONDS_AROUND_START_TO_TRACK) { + final Wind directionFromStartToNextMark = trackedRace.getDirectionFromStartToNextMark(new MillisecondsTimePoint(t)); + if (directionFromStartToNextMark != null) { + result.add(directionFromStartToNextMark); + } } } else { result = empty; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 679a3ecf4c7..53bcb068f0e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -134,7 +134,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { */ private final Map windTracks; - private Wind directionFromStartToNextMarkCache; + private final Map directionFromStartToNextMarkCache; private final Map> buoyTracks; @@ -152,6 +152,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { this.updateCount = 0; this.race = race; this.windStore = windStore; + this.directionFromStartToNextMarkCache = new HashMap(); this.millisecondsOverWhichToAverageSpeed = millisecondsOverWhichToAverageSpeed; this.millisecondsOverWhichToAverageWind = millisecondsOverWhichToAverageWind; this.startToNextMarkCacheInvalidationListeners = new HashMap(); @@ -591,18 +592,21 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { @Override public Wind getDirectionFromStartToNextMark(TimePoint at) { - Wind result = directionFromStartToNextMarkCache; - if (result == null) { - Leg firstLeg = getRace().getCourse().getLegs().iterator().next(); - Position firstLegEnd = getApproximatePosition(firstLeg.getTo(), at); - Position firstLegStart = getApproximatePosition(firstLeg.getFrom(), at); - if (firstLegStart != null && firstLegEnd != null) { - result = new WindImpl(firstLegStart, at, new KnotSpeedWithBearingImpl(1.0, - firstLegEnd.getBearingGreatCircle(firstLegStart))); - final Wind finalResult = result; - directionFromStartToNextMarkCache = finalResult; - } else { - result = null; + Wind result; + synchronized (directionFromStartToNextMarkCache) { + result = directionFromStartToNextMarkCache.get(at); + if (result == null) { + Leg firstLeg = getRace().getCourse().getLegs().iterator().next(); + Position firstLegEnd = getApproximatePosition(firstLeg.getTo(), at); + Position firstLegStart = getApproximatePosition(firstLeg.getFrom(), at); + if (firstLegStart != null && firstLegEnd != null) { + result = new WindImpl(firstLegStart, at, new KnotSpeedWithBearingImpl(1.0, + firstLegEnd.getBearingGreatCircle(firstLegStart))); + final Wind finalResult = result; + directionFromStartToNextMarkCache.put(at, finalResult); + } else { + result = null; + } } } return result; @@ -686,7 +690,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { if (zeroBasedIndex < 2) { // the observing listener on any previous buoy will be GCed; we need to ensure // that the cache is recomputed - directionFromStartToNextMarkCache = null; + clearDirectionFromStartToNextMarkCache(); Iterator waypointsIter = getRace().getCourse().getWaypoints().iterator(); waypointsIter.next(); // skip first if (waypointsIter.hasNext()) { @@ -700,6 +704,12 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { addStartToNextMarkCacheInvalidationListener(waypointThatGotAdded); } + private void clearDirectionFromStartToNextMarkCache() { + synchronized (directionFromStartToNextMarkCache) { + directionFromStartToNextMarkCache.clear(); + } + } + private void addStartToNextMarkCacheInvalidationListener(Waypoint waypoint) { for (Buoy buoy : waypoint.getBuoys()) { addStartToNextMarkCacheInvalidationListener(buoy); @@ -756,7 +766,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { if (zeroBasedIndex < 2) { // the observing listener on any previous buoy will be GCed; we need to ensure // that the cache is recomputed - directionFromStartToNextMarkCache = null; + clearDirectionFromStartToNextMarkCache(); stopAndRemoveStartToNextMarkCacheInvalidationListener(waypointThatGotRemoved); Iterator waypointsIter = getRace().getCourse().getWaypoints().iterator(); waypointsIter.next(); // skip first @@ -1253,7 +1263,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { @Override public void gpsFixReceived(GPSFix fix, Buoy buoy) { - directionFromStartToNextMarkCache = null; + clearDirectionFromStartToNextMarkCache(); } @Override