From abcd5ac3f38f2862e971420de93966a0ec8fe59a Mon Sep 17 00:00:00 2001 From: Lennart Hensler Date: Fri, 30 Mar 2012 08:48:56 +0200 Subject: [PATCH] Moved calculation of the start and finish for a tracked race to the sailing service --- .../test/LongRangeRegattaGeocoderTest.java | 71 ------------------ .../domain/test/mock/MockedTrackedRace.java | 7 -- .../sailing/domain/tracking/TrackedRace.java | 6 -- .../domain/tracking/impl/TrackedRaceImpl.java | 74 ------------------- .../META-INF/MANIFEST.MF | 3 +- .../gwt/ui/server/SailingServiceImpl.java | 67 ++++++++++++++++- 6 files changed, 68 insertions(+), 160 deletions(-) delete mode 100644 java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LongRangeRegattaGeocoderTest.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LongRangeRegattaGeocoderTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LongRangeRegattaGeocoderTest.java deleted file mode 100644 index 2ed61d338b7..00000000000 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LongRangeRegattaGeocoderTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.sap.sailing.domain.test; - -import static org.junit.Assert.assertNotNull; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.Buoy; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.impl.MillisecondsTimePoint; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Placemark; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.TimePoint; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.impl.Util.Pair; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.impl.GPSFixImpl; -import com.sap.sailing.domain.tractracadapter.ReceiverType; - -public class LongRangeRegattaGeocoderTest extends AbstractManeuverDetectionTestCase { - - public LongRangeRegattaGeocoderTest() throws MalformedURLException, URISyntaxException { - super(); - } - - @Before - public void setUp() throws URISyntaxException, IOException, InterruptedException { - super.setUp(); - super.setUp("event_20110609_KielerWoch", - /* raceId */"357c700a-9d9a-11e0-85be-406186cbf87c", new ReceiverType[] { ReceiverType.MARKPASSINGS, - ReceiverType.RACESTARTFINISH, ReceiverType.RACECOURSE }); - fixApproximateMarkPositionsForGeocoder(getTrackedRace()); - dateFormat = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); - } - - private void fixApproximateMarkPositionsForGeocoder(DynamicTrackedRace race) { - TimePoint epoch = new MillisecondsTimePoint(0l); - TimePoint now = MillisecondsTimePoint.now(); - Map buoyPositions = new HashMap(); - buoyPositions.put("K Start (left)", new DegreePosition(5.90906782829855, -55.16166687011719)); - buoyPositions.put("K Start (right)", new DegreePosition(5.939801840526332, -55.17402648925781)); - buoyPositions.put("K Mark1", new DegreePosition(8.233237111274565, -31.640625)); - buoyPositions.put("K Mark4 (right)", new DegreePosition(13.63083009512624, -21.8243408203125)); - buoyPositions.put("K Mark4 (left)", new DegreePosition(13.870080100685891, -21.9122314453125)); - buoyPositions.put("K Finish (left)", new DegreePosition(14.694198629294522, -17.39307403564453)); - buoyPositions.put("K Finish (right)", new DegreePosition(14.693866535193942, -17.371788024902344)); - for (Waypoint w : race.getRace().getCourse().getWaypoints()) { - for (Buoy buoy : w.getBuoys()) { - race.getOrCreateTrack(buoy).addGPSFix(new GPSFixImpl(buoyPositions.get(buoy.getName()), epoch)); - race.getOrCreateTrack(buoy).addGPSFix(new GPSFixImpl(buoyPositions.get(buoy.getName()), now)); - } - } - } - - @Test - public void testSetupOK() throws ParseException, NoWindException { - assertNotNull(getTrackedRace()); - Pair placemarks = getTrackedRace().getStartFinishPlacemarks(); - assertNotNull(placemarks.getA()); - assertNotNull(placemarks.getB()); - } -} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index bb2b336388b..3f38a9a0664 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -12,7 +12,6 @@ import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Placemark; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.Tack; @@ -421,12 +420,6 @@ public class MockedTrackedRace implements DynamicTrackedRace { // TODO Auto-generated method stub } - @Override - public Pair getStartFinishPlacemarks() { - // TODO Auto-generated method stub - return null; - } - @Override public RaceIdentifier getRaceIdentifier() { // TODO Auto-generated method stub diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 49541b95576..d774c63fd07 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -45,12 +45,6 @@ public interface TrackedRace { RaceIdentifier getRaceIdentifier(); - /** - * @return A pair of placemarks, where A is the start placemark and B is the finish placemark.
- * The returning pair is never null, but A and/or B can be null. - */ - Pair getStartFinishPlacemarks(); - /** * Computes the estimated start time for this race (not to be confused with the {@link #getStartOfTracking()} time point * which is expected to be before the race start time). When there are no {@link MarkPassing}s for the first mark, null 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 a21ada29b36..d1958a46822 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 @@ -1,6 +1,5 @@ package com.sap.sailing.domain.tracking.impl; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -18,8 +17,6 @@ import java.util.concurrent.ConcurrentSkipListSet; import java.util.logging.Level; import java.util.logging.Logger; -import org.json.simple.parser.ParseException; - import com.sap.sailing.domain.base.BearingWithConfidence; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Buoy; @@ -43,7 +40,6 @@ import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.ManeuverType; import com.sap.sailing.domain.common.NoWindError; import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Placemark; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.Tack; @@ -74,19 +70,12 @@ import com.sap.sailing.domain.tracking.Wind; import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.geocoding.ReverseGeocoder; public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { private static final Logger logger = Logger.getLogger(TrackedRaceImpl.class.getName()); private static final double PENALTY_CIRCLE_DEGREES_THRESHOLD = 320; - /** - * Used in {@link #getStartFinishPlacemarks()} to calculate the radius for the - * {@link ReverseGeocoder#getPlacemarksNear(Position, double) GetPlacemarksNear-Service}. - */ - private static final double GEONAMES_RADIUS_CACLCULATION_FACTOR = 10.0; - // TODO make this variable private static final long DELAY_FOR_CACHE_CLEARING_IN_MILLISECONDS = 7500; @@ -1431,69 +1420,6 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener { } } - @Override - public Pair getStartFinishPlacemarks() { - Pair placemarks = new Pair(null, null); - Placemark startBest = null; - Placemark finishBest = null; - - // Get start postition - Iterator startBuoys = getRace().getCourse().getFirstWaypoint().getBuoys().iterator(); - GPSFix startBuoyFix = startBuoys.hasNext() ? getOrCreateTrack(startBuoys.next()).getLastRawFix() : null; - Position startPosition = startBuoyFix != null ? startBuoyFix.getPosition() : null; - if (startPosition != null) { - try { - // Get distance to nearest placemark and calculate the search radius - Placemark startNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(startPosition); - if (startNearest != null) { - Distance startNearestDistance = startNearest.distanceFrom(startPosition); - double startRadius = startNearestDistance.getKilometers() * GEONAMES_RADIUS_CACLCULATION_FACTOR; - - // Get the estimated best start place - startBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(startPosition, startRadius, - new Placemark.ByPopulationDistanceRatio(startPosition)); - } - } catch (IOException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } catch (ParseException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } - } - - // Get finish position - Iterator finishBuoys = getRace().getCourse().getFirstWaypoint().getBuoys().iterator(); - GPSFix finishBuoyFix = finishBuoys.hasNext() ? getOrCreateTrack(finishBuoys.next()).getLastRawFix() : null; - Position finishPosition = finishBuoyFix != null ? finishBuoyFix.getPosition() : null; - if (startPosition != null && finishPosition != null) { - if (startPosition.getDistance(finishPosition).getKilometers() <= ReverseGeocoder.POSITION_CACHE_DISTANCE_LIMIT_IN_KM) { - finishBest = startBest; - } else { - try { - // Get distance to nearest placemark and calculate the search radius - Placemark finishNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(finishPosition); - Distance finishNearestDistance = finishNearest.distanceFrom(finishPosition); - double finishRadius = finishNearestDistance.getKilometers() * GEONAMES_RADIUS_CACLCULATION_FACTOR; - - // Get the estimated best finish place - finishBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(finishPosition, finishRadius, - new Placemark.ByPopulationDistanceRatio(finishPosition)); - } catch (IOException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } catch (ParseException e) { - logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); - } - } - } - - if (startBest != null) { - placemarks.setA(startBest); - } - if (finishBest != null) { - placemarks.setB(finishBest); - } - return placemarks; - } - @Override public Distance getWindwardDistanceToOverallLeader(Competitor competitor, TimePoint timePoint) throws NoWindException { diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index c5112cd74af..917ea8ee810 100755 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -16,7 +16,8 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.domain.tractracadapter.persistence, com.google.gwt.osgi;bundle-version="2.4.0", com.sap.sailing.domain.common, - org.moxieapps.gwt.highcharts;bundle-version="1.1.4" + org.moxieapps.gwt.highcharts;bundle-version="1.1.4", + com.sap.sailing.geocoding Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator Bundle-ActivationPolicy: lazy Export-Package: com.sap.sailing.gwt.ui.client;x-friends:="com.sap.sailing.gwt.ui.test", diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 3ba58793528..33c321437e4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -100,10 +100,12 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.Wind; import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; import com.sap.sailing.domain.tracking.impl.WindImpl; import com.sap.sailing.domain.tractracadapter.DomainFactory; import com.sap.sailing.domain.tractracadapter.RaceRecord; import com.sap.sailing.domain.tractracadapter.TracTracConfiguration; +import com.sap.sailing.geocoding.ReverseGeocoder; import com.sap.sailing.gwt.ui.client.SailingService; import com.sap.sailing.gwt.ui.shared.BoatClassDTO; import com.sap.sailing.gwt.ui.shared.CompetitorDTO; @@ -1211,7 +1213,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS if (withAdditionalData) { //Getting the places of the race - Pair startAndFinish = trackedRace.getStartFinishPlacemarks(); + Pair startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace); PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO(); if (startAndFinish.getA() != null) { racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getA())); @@ -1237,6 +1239,69 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS return dto; } + private Pair getStartFinishPlacemarksForTrackedRace(TrackedRace race) { + double radiusCalculationFactor = 10.0; + Pair placemarks = new Pair(null, null); + Placemark startBest = null; + Placemark finishBest = null; + + // Get start postition + Iterator startBuoys = race.getRace().getCourse().getFirstWaypoint().getBuoys().iterator(); + GPSFix startBuoyFix = startBuoys.hasNext() ? race.getOrCreateTrack(startBuoys.next()).getLastRawFix() : null; + Position startPosition = startBuoyFix != null ? startBuoyFix.getPosition() : null; + if (startPosition != null) { + try { + // Get distance to nearest placemark and calculate the search radius + Placemark startNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(startPosition); + if (startNearest != null) { + Distance startNearestDistance = startNearest.distanceFrom(startPosition); + double startRadius = startNearestDistance.getKilometers() * radiusCalculationFactor; + + // Get the estimated best start place + startBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(startPosition, startRadius, + new Placemark.ByPopulationDistanceRatio(startPosition)); + } + } catch (IOException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } catch (org.json.simple.parser.ParseException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } + } + + // Get finish position + Iterator finishBuoys = race.getRace().getCourse().getFirstWaypoint().getBuoys().iterator(); + GPSFix finishBuoyFix = finishBuoys.hasNext() ? race.getOrCreateTrack(finishBuoys.next()).getLastRawFix() : null; + Position finishPosition = finishBuoyFix != null ? finishBuoyFix.getPosition() : null; + if (startPosition != null && finishPosition != null) { + if (startPosition.getDistance(finishPosition).getKilometers() <= ReverseGeocoder.POSITION_CACHE_DISTANCE_LIMIT_IN_KM) { + finishBest = startBest; + } else { + try { + // Get distance to nearest placemark and calculate the search radius + Placemark finishNearest = ReverseGeocoder.INSTANCE.getPlacemarkNearest(finishPosition); + Distance finishNearestDistance = finishNearest.distanceFrom(finishPosition); + double finishRadius = finishNearestDistance.getKilometers() * radiusCalculationFactor; + + // Get the estimated best finish place + finishBest = ReverseGeocoder.INSTANCE.getPlacemarkLast(finishPosition, finishRadius, + new Placemark.ByPopulationDistanceRatio(finishPosition)); + } catch (IOException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } catch (org.json.simple.parser.ParseException e) { + logger.throwing(TrackedRaceImpl.class.getName(), "getPlaceOrder()", e); + } + } + } + + if (startBest != null) { + placemarks.setA(startBest); + } + if (finishBest != null) { + placemarks.setB(finishBest); + } + return placemarks; + } + @Override public void updateLeaderboard(String leaderboardName, String newLeaderboardName, int[] newDiscardingThreasholds) { if (!leaderboardName.equals(newLeaderboardName)) {