From d9aaab20274d7c3df22e9bb36f5693b779602be2 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:17:34 +0200 Subject: [PATCH 1/6] implemented removewind REST API in admin app --- .../sailing/domain/test/CourseUpdateTest.java | 1 + .../domain/test/ReceiveTrackingDataTest.java | 3 + .../impl/TracTracTrackedLegImpl.java | 8 ++ .../sailing/domain/tracking/TrackedLeg.java | 7 ++ .../tracking/TrackedLegOfCompetitor.java | 2 +- .../sailing/domain/tracking/TrackedRace.java | 2 + .../sailing/domain/tracking/WindListener.java | 2 + .../sailing/domain/tracking/WindTrack.java | 2 + .../tracking/impl/DynamicTrackedRaceImpl.java | 23 +++++ .../domain/tracking/impl/TrackedLegImpl.java | 49 +++++++++++ .../impl/TrackedLegOfCompetitorImpl.java | 40 +-------- .../domain/tracking/impl/WindTrackImpl.java | 23 ++++- .../test/MockedTrackedRace.java | 6 ++ .../mongodb/impl/MongoWindListener.java | 6 ++ .../src/com/sap/sailing/server/AdminApp.java | 88 ++++++++++++++----- .../com/sap/sailing/server/ModeratorApp.java | 20 +++-- 16 files changed, 212 insertions(+), 70 deletions(-) diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java index d86fb541416..1bfbdf32c1f 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CourseUpdateTest.java @@ -83,5 +83,6 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest { @Test public void testLastWaypointRemoved() { Iterable waypoints = course.getWaypoints(); + // TODO continue with testLastWaypointRemoved()... } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java index 48dcaa9f339..957fddb5af3 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ReceiveTrackingDataTest.java @@ -66,6 +66,9 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest { @Override public void windDataReceived(Wind wind) { } + @Override + public void windDataRemoved(Wind wind) { + } }; List listeners = new ArrayList(); Event event = domainFactory.createEvent(getEvent()); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracTrackedLegImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracTrackedLegImpl.java index edbc0fa780c..bb90faffdc0 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracTrackedLegImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracTrackedLegImpl.java @@ -5,6 +5,8 @@ import java.util.Map; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; +import com.sap.sailing.domain.base.TimePoint; +import com.sap.sailing.domain.tracking.NoWindException; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; @@ -43,4 +45,10 @@ public class TracTracTrackedLegImpl implements TrackedLeg { return trackedRace; } + @Override + public boolean isUpOrDownwindLeg(TimePoint at) throws NoWindException { + // TODO Auto-generated method stub + return false; + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java index 486cc438c9b..0edd9bf8c60 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLeg.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.tracking; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; +import com.sap.sailing.domain.base.TimePoint; public interface TrackedLeg { Leg getLeg(); @@ -12,4 +13,10 @@ public interface TrackedLeg { TrackedRace getTrackedRace(); + /** + * Determines whether the current {@link #getLeg() leg} is +/- {@link #UPWIND_DOWNWIND_TOLERANCE_IN_DEG} degrees + * collinear with the current wind's bearing. + */ + boolean isUpOrDownwindLeg(TimePoint at) throws NoWindException; + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java index 22961206546..7edc0c8afb0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java @@ -90,5 +90,5 @@ public interface TrackedLegOfCompetitor { * Returns null in case this leg's competitor hasn't started the leg yet. */ Double getEstimatedTimeToNextMarkInSeconds(TimePoint timePoint) throws NoWindException; - + } 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 0e565067bbc..edf1297beb3 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 @@ -139,4 +139,6 @@ public interface TrackedRace { TimePoint getTimePointOfNewestEvent(); NavigableSet getMarkPassings(Competitor competitor); + + void removeWind(Wind wind, WindSource windSource); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindListener.java index 819110994a0..88e6bf7a161 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindListener.java @@ -2,4 +2,6 @@ package com.sap.sailing.domain.tracking; public interface WindListener { void windDataReceived(Wind wind); + + void windDataRemoved(Wind wind); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindTrack.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindTrack.java index 5e059e4bc59..7c3a1646079 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindTrack.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/WindTrack.java @@ -24,4 +24,6 @@ public interface WindTrack extends Track { * A listener is notified whenever a new fix is added to this track */ void addListener(WindListener listener); + + void remove(Wind wind); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index b6a01902e7e..0dd42e047fb 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -89,6 +89,17 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements } } + private void notifyListenersWindRemoved(Wind wind) { + for (RaceChangeListener listener : getListeners()) { + try { + listener.windDataRemoved(wind); + } catch (Throwable t) { + logger.log(Level.SEVERE, "RaceChangeListener " + listener + " threw exception " + t.getMessage()); + logger.throwing(DynamicTrackedRaceImpl.class.getName(), "notifyListenersWindRemoved(Wind)", t); + } + } + } + private void notifyListeners(MarkPassing markPassing) { for (RaceChangeListener listener : getListeners()) { try { @@ -141,6 +152,12 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements getWindTrack(windSource).add(wind); updated(wind.getTimePoint()); } + + @Override + public void removeWind(Wind wind, WindSource windSource) { + getWindTrack(windSource).remove(wind); + updated(wind.getTimePoint()); + } @Override public void gpsFixReceived(GPSFix fix, Competitor competitor) { @@ -158,6 +175,12 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements notifyListeners(wind); } + @Override + public void windDataRemoved(Wind wind) { + notifyListenersWindRemoved(wind); + } + + @Override protected TrackedLeg createTrackedLeg(RaceDefinition race, Leg leg) { return new TrackedLegImpl(this, leg, race.getCompetitors()); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java index c79dee1053b..d47868100f9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegImpl.java @@ -4,11 +4,15 @@ import java.util.HashMap; import java.util.Map; import java.util.TreeSet; +import com.sap.sailing.domain.base.Bearing; +import com.sap.sailing.domain.base.Buoy; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Leg; +import com.sap.sailing.domain.base.Position; import com.sap.sailing.domain.base.TimePoint; import com.sap.sailing.domain.tracking.GPSFix; import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.NoWindException; import com.sap.sailing.domain.tracking.RaceChangeListener; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; @@ -16,6 +20,8 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.Wind; public class TrackedLegImpl implements TrackedLeg, RaceChangeListener { + private final static double UPWIND_DOWNWIND_TOLERANCE_IN_DEG = 40; // TracTrac does 22.5, Marcus Baur suggest 40 + private final Leg leg; private final Map trackedLegsOfCompetitors; private TrackedRaceImpl trackedRace; @@ -82,6 +88,44 @@ public class TrackedLegImpl implements TrackedLeg, RaceChangeListener competitorTracksByRank = getTrackedLeg().getCompetitorTracksOrderedByRank(timePoint); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java index 1be25a2c35d..d3c8f740e70 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/WindTrackImpl.java @@ -39,12 +39,27 @@ public class WindTrackImpl extends TrackImpl implements WindTrack { @Override public synchronized void add(Wind wind) { getInternalFixes().add(wind); + notifyListenersAboutReceive(wind); + } + + private void notifyListenersAboutReceive(Wind wind) { for (WindListener listener : listeners) { try { listener.windDataReceived(wind); } catch (Throwable t) { logger.log(Level.SEVERE, "WindListener "+listener+" threw exception "+t.getMessage()); - logger.throwing(WindTrackImpl.class.getName(), "add(Wind)", t); + logger.throwing(WindTrackImpl.class.getName(), "notifyListenersAboutReceive(Wind)", t); + } + } + } + + private void notifyListenersAboutRemoval(Wind wind) { + for (WindListener listener : listeners) { + try { + listener.windDataRemoved(wind); + } catch (Throwable t) { + logger.log(Level.SEVERE, "WindListener "+listener+" threw exception "+t.getMessage()); + logger.throwing(WindTrackImpl.class.getName(), "notifyListenersAboutRemoval(Wind)", t); } } } @@ -167,4 +182,10 @@ public class WindTrackImpl extends TrackImpl implements WindTrack { public void addListener(WindListener listener) { listeners.add(listener); } + + @Override + public void remove(Wind wind) { + getInternalFixes().remove(wind); + notifyListenersAboutRemoval(wind); + } } diff --git a/java/com.sap.sailing.expeditionconnector.test/src/com/sap/sailing/expeditionconnector/test/MockedTrackedRace.java b/java/com.sap.sailing.expeditionconnector.test/src/com/sap/sailing/expeditionconnector/test/MockedTrackedRace.java index 956f26e3eed..59df8765486 100755 --- a/java/com.sap.sailing.expeditionconnector.test/src/com/sap/sailing/expeditionconnector/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.expeditionconnector.test/src/com/sap/sailing/expeditionconnector/test/MockedTrackedRace.java @@ -237,4 +237,10 @@ public class MockedTrackedRace implements DynamicTrackedRace { return null; } + @Override + public void removeWind(Wind wind, WindSource windSource) { + // TODO Auto-generated method stub + + } + } diff --git a/java/com.sap.sailing.mongodb/src/com/sap/sailing/mongodb/impl/MongoWindListener.java b/java/com.sap.sailing.mongodb/src/com/sap/sailing/mongodb/impl/MongoWindListener.java index 6d9f19bd9c7..4ff95d07d60 100755 --- a/java/com.sap.sailing.mongodb/src/com/sap/sailing/mongodb/impl/MongoWindListener.java +++ b/java/com.sap.sailing.mongodb/src/com/sap/sailing/mongodb/impl/MongoWindListener.java @@ -32,4 +32,10 @@ public class MongoWindListener implements com.sap.sailing.domain.tracking.WindLi windTracksCollection.insert(windTrackEntry); } + @Override + public void windDataRemoved(Wind wind) { + DBObject windTrackEntry = mongoObjectFactory.storeWindTrackEntry(trackedEvent.getEvent(), trackedRace.getRace(), windSource, wind); + windTracksCollection.remove(windTrackEntry); + } + } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java index 6dfe249948d..e14819df1b9 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/AdminApp.java @@ -58,6 +58,8 @@ public class AdminApp extends Servlet { private static final String ACTION_NAME_SET_WIND = "setwind"; + private static final String ACTION_NAME_REMOVE_WIND = "removewind"; + private static final String ACTION_NAME_SELECT_WIND_SOURCE = "selectwindsource"; private static final String ACTION_NAME_SHOW_WIND = "showwind"; @@ -106,7 +108,7 @@ public class AdminApp extends Servlet { public AdminApp() { } - + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { @@ -128,6 +130,8 @@ public class AdminApp extends Servlet { listWindTrackers(req, resp); } else if (ACTION_NAME_SET_WIND.equals(action)) { setWind(req, resp); + } else if (ACTION_NAME_REMOVE_WIND.equals(action)) { + removeWind(req, resp); } else if (ACTION_NAME_SELECT_WIND_SOURCE.equals(action)) { selectWindSource(req, resp); } else if (ACTION_NAME_SHOW_WIND.equals(action)) { @@ -135,7 +139,7 @@ public class AdminApp extends Servlet { } else if (ACTION_NAME_ADD_WIND_TO_MARKS.equals(action)) { addWindToMarks(req, resp); } else { - resp.sendError(500, "Unknown action \""+action+"\""); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unknown action \""+action+"\""); } } else { resp.getWriter().println("Hello admin!"); @@ -150,11 +154,11 @@ public class AdminApp extends Servlet { InvalidDateException, NoWindException { Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { TrackedRace trackedRace = getService().getDomainFactory().trackEvent(event).getTrackedRace(race); TimePoint time = getTimePoint(req, PARAM_NAME_TIME, PARAM_NAME_TIME_MILLIS, MillisecondsTimePoint.now()); @@ -192,11 +196,11 @@ public class AdminApp extends Servlet { private void showWind(HttpServletRequest req, HttpServletResponse resp) throws IOException, InvalidDateException { Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { TrackedRace trackedRace = getService().getDomainFactory().trackEvent(event).getTrackedRace(race); TimePoint from = getTimePoint(req, PARAM_NAME_FROM_TIME, PARAM_NAME_FROM_TIME_MILLIS, @@ -241,17 +245,17 @@ public class AdminApp extends Servlet { private void selectWindSource(HttpServletRequest req, HttpServletResponse resp) throws IOException { String sourceName = req.getParameter(PARAM_NAME_WINDSOURCE_NAME); if (sourceName == null) { - resp.sendError(500, "Wind source name not provided"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Wind source name not provided"); } else { try { WindSource windSource = WindSource.valueOf(sourceName); Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { TrackedRace trackedRace = getService().getDomainFactory().trackEvent(event) .getTrackedRace(race); @@ -273,7 +277,7 @@ public class AdminApp extends Servlet { } errorMessage.append(s.toString()); } - resp.sendError(500, errorMessage.toString()); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMessage.toString()); } } } @@ -281,11 +285,11 @@ public class AdminApp extends Servlet { private void setWind(HttpServletRequest req, HttpServletResponse resp) throws IOException { Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { String bearingAsString = req.getParameter(PARAM_NAME_BEARING); if (bearingAsString != null) { @@ -311,10 +315,50 @@ public class AdminApp extends Servlet { Wind wind = new WindImpl(p, timePoint, speed); getService().getDomainFactory().trackEvent(event).getTrackedRace(race).recordWind(wind, WindSource.WEB); } catch (InvalidDateException e) { - resp.sendError(500, "Couldn't parse time specification " + e.getMessage()); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Couldn't parse time specification " + e.getMessage()); } } else { - resp.sendError(500, "wind bearing parameter "+PARAM_NAME_BEARING+" missing"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "wind bearing parameter "+PARAM_NAME_BEARING+" missing"); + } + } + } + } + + private void removeWind(HttpServletRequest req, HttpServletResponse resp) throws IOException { + Event event = getEvent(req); + if (event == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); + } else { + RaceDefinition race = getRaceDefinition(req); + if (race == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); + } else { + String sourceName = req.getParameter(PARAM_NAME_WINDSOURCE_NAME); + if (sourceName == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Wind source name not provided"); + } else { + WindSource windSource = WindSource.valueOf(sourceName); + if (windSource == null) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Wind source name " + sourceName + " unknown"); + } else { + try { + WindTrack windTrack = getService().getDomainFactory().trackEvent(event) + .getTrackedRace(race).getWindTrack(windSource); + TimePoint timePoint = getTimePoint(req, PARAM_NAME_TIME, PARAM_NAME_TIME_MILLIS, + MillisecondsTimePoint.now()); + Wind wind = windTrack.getLastFixAtOrBefore(timePoint); + if (wind != null && wind.getTimePoint().equals(timePoint)) { + windTrack.remove(wind); + resp.getWriter().println("Successfully removed entry "+wind); + } else { + resp.getWriter().println( + "No wind recorded for event " + event.getName() + " and race " + race.getName() + + " at " + timePoint.asDate()+". No error, just no effect :-)"); + } + } catch (InvalidDateException e) { + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Couldn't parse time specification " + e.getMessage()); + } + } } } } @@ -335,11 +379,11 @@ public class AdminApp extends Servlet { private void stopReceivingExpeditionWindForRace(HttpServletRequest req, HttpServletResponse resp) throws SocketException, IOException { Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { getService().stopTrackingWind(event, race); } @@ -349,15 +393,15 @@ public class AdminApp extends Servlet { private void startReceivingExpeditionWindForRace(HttpServletRequest req, HttpServletResponse resp) throws IOException { Event event = getEvent(req); if (event == null) { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } else { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { String portParam = req.getParameter(PARAM_NAME_PORT); if (portParam == null) { - resp.sendError(500, "No port parameter provided"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "No port parameter provided"); } else { int port = Integer.valueOf(portParam); String correctByDeclination = req @@ -375,7 +419,7 @@ public class AdminApp extends Servlet { if (event != null) { getService().stopTracking(event); } else { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } } @@ -415,12 +459,12 @@ public class AdminApp extends Servlet { if (event != null) { RaceDefinition race = getRaceDefinition(req); if (race == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { getService().stopTracking(event, race); } } else { - resp.sendError(500, "Event not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Event not found"); } } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java index 0e7b23008b2..22bd83d1474 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/ModeratorApp.java @@ -67,7 +67,7 @@ public class ModeratorApp extends Servlet { } else if (ACTION_NAME_SHOW_BOAT_POSITIONS.equals(action)) { showBoatPositions(req, resp); } else { - resp.sendError(500, "Unknown action \""+action+"\""); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unknown action \""+action+"\""); } } else { resp.getWriter().println("Hello moderator!"); @@ -81,7 +81,7 @@ public class ModeratorApp extends Servlet { private void showBoatPositions(HttpServletRequest req, HttpServletResponse resp) throws IOException { TrackedRace trackedRace = getTrackedRace(req); if (trackedRace == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { try { TimePoint sinceTimePoint = getTimePoint(req, PARAM_NAME_SINCE, PARAM_NAME_SINCE_MILLIS, null); @@ -119,7 +119,7 @@ public class ModeratorApp extends Servlet { jsonRace.put("competitors", jsonCompetitors); jsonRace.writeJSONString(resp.getWriter()); } catch (InvalidDateException e) { - resp.sendError(500, "Couldn't parse time specification " + e.getMessage()); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Couldn't parse time specification " + e.getMessage()); } } } @@ -127,7 +127,7 @@ public class ModeratorApp extends Servlet { private void showWaypoints(HttpServletRequest req, HttpServletResponse resp) throws IOException { TrackedRace trackedRace = getTrackedRace(req); if (trackedRace == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { try { TimePoint timePoint = getTimePoint(req, PARAM_NAME_TIME, PARAM_NAME_TIME_MILLIS, @@ -159,7 +159,7 @@ public class ModeratorApp extends Servlet { } jsonWaypoints.writeJSONString(resp.getWriter()); } catch (InvalidDateException e) { - resp.sendError(500, "Couldn't parse time specification " + e.getMessage()); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Couldn't parse time specification " + e.getMessage()); } } } @@ -179,7 +179,7 @@ public class ModeratorApp extends Servlet { Event event = getEvent(req); TrackedRace trackedRace = getTrackedRace(req); if (trackedRace == null) { - resp.sendError(500, "Race not found"); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Race not found"); } else { try { TimePoint timePoint = getTimePoint(req, PARAM_NAME_TIME, PARAM_NAME_TIME_MILLIS, @@ -220,6 +220,12 @@ public class ModeratorApp extends Servlet { JSONObject jsonLeg = new JSONObject(); jsonLeg.put("from", leg.getLeg().getFrom().getName()); jsonLeg.put("to", leg.getLeg().getTo().getName()); + try { + jsonLeg.put("upordownwindleg", leg.isUpOrDownwindLeg(timePoint)); + } catch (NoWindException e) { + // no wind, then it's simply no upwind or downwind leg + jsonLeg.put("upordownwindleg", "false"); + } JSONArray jsonCompetitors = new JSONArray(); for (Competitor competitor : event.getCompetitors()) { JSONObject jsonCompetitorInLeg = new JSONObject(); @@ -304,7 +310,7 @@ public class ModeratorApp extends Servlet { } jsonRace.writeJSONString(resp.getWriter()); } catch (InvalidDateException e) { - resp.sendError(500, "Couldn't parse time specification " + e.getMessage()); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Couldn't parse time specification " + e.getMessage()); } } System.out.println("showrace took "+(System.currentTimeMillis()-start)+"ms"); From 6346b92f2b64a81620eae12307478d7ffbde1fe6 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:21:15 +0200 Subject: [PATCH 2/6] merged java/TODO with Simon's top-level TODO --- TODO | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/TODO b/TODO index 6d453a0e046..986dd82aad6 100644 --- a/TODO +++ b/TODO @@ -2,8 +2,27 @@ Axel ==== -+ UDP Ports prüfen -+ Branches einrichten für dev, test, prod1, prod2 + + - Implement and test course update with corresponding TrackedLeg[OfCompetitor] updates + + - Clarify Equinox server upgrade process from the maven-repository + + - Open test server firewall ports for UDP / Expedition wind integration + + - test UDP ports + + - Set up two Expedition machines with RF and UMTS transmission, test killing one + + - enable switching between our and TracTrac-provided leaderboard information + + - Test fail-over in case one of the two Java VM fails + + - Pass final production instance URL information to BeTomorrow for wind integration + + - Display gain/loss for next-best competitor (green/red arrow up/down) based on VMG comparison + + - Improve Mongo-based tests by using Mongo transactions instead of waiting for prior transactions to complete + Simon ===== From 56e99d863e3c8e6d4f2c93e3a7c070bc29cd564b Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:21:34 +0200 Subject: [PATCH 3/6] merged old java/TODO in top-level TODO --- java/TODO | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 java/TODO diff --git a/java/TODO b/java/TODO deleted file mode 100644 index c94ad166eaa..00000000000 --- a/java/TODO +++ /dev/null @@ -1,18 +0,0 @@ - - Implement and test course update with corresponding TrackedLeg[OfCompetitor] updates - - - Clarify Equinox server upgrade process from the maven-repository - - - Open test server firewall ports for UDP / Expedition wind integration - - - Set up two Expedition machines with RF and UMTS transmission, test killing one - - - enable switching between our and TracTrac-provided leaderboard information - - - Test fail-over in case one of the two Java VM fails - - - Pass final production instance URL information to BeTomorrow for wind integration - - - Display gain/loss for next-best competitor (green/red arrow up/down) based on VMG comparison - - - Improve Mongo-based tests by using Mongo transactions instead of waiting for prior transactions to complete - From becc95ad4916d7eeeaa327e16ac67e9758e953b8 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:26:56 +0200 Subject: [PATCH 4/6] fixed pattern that at least excludes Java .class files --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c4c27613a20..ee4b0848468 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .metadata -java/*/bin +*.class *.swp From a1daeaedf41ea8cd19659bd86cc964b891e44424 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:37:10 +0200 Subject: [PATCH 5/6] added TODO --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 986dd82aad6..a22d92599a4 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,7 @@ Axel ==== + - write regression test for WindTrack problem earlier today - Implement and test course update with corresponding TrackedLeg[OfCompetitor] updates From 989fa4258cde04193884af1d7d8d73c1f4c8cfd2 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Fri, 10 Jun 2011 21:46:59 +0200 Subject: [PATCH 6/6] added regression test for bug fixed by 20a3aa6c2d37ace556ff9315fe343bebc7e8760f --- TODO | 2 -- .../com/sap/sailing/domain/test/WindTest.java | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) mode change 100755 => 100644 java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java diff --git a/TODO b/TODO index a22d92599a4..ecb0254d52b 100644 --- a/TODO +++ b/TODO @@ -2,8 +2,6 @@ Axel ==== - - write regression test for WindTrack problem earlier today - - Implement and test course update with corresponding TrackedLeg[OfCompetitor] updates - Clarify Equinox server upgrade process from the maven-repository diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java old mode 100755 new mode 100644 index f165c53173a..c76b5cbee02 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/WindTest.java @@ -2,8 +2,12 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; +import java.text.ParseException; +import java.text.SimpleDateFormat; + import org.junit.Test; +import com.sap.sailing.domain.base.TimePoint; import com.sap.sailing.domain.base.impl.DegreeBearingImpl; import com.sap.sailing.domain.base.impl.DegreePosition; import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl; @@ -77,4 +81,35 @@ public class WindTest { assertEquals(10, estimate.getKnots(), 0.000000001); assertEquals(105, estimate.getBearing().getDegrees(), 0.00000001); } + + @Test + public void testUsingNewerThanRequestedIfCloserThanOlder() throws ParseException { + /* + Imagine the following wind measurements: + + 2009-07-11T13:45:00.000+0200@null: 10.0kn from 278.0� avg(30000ms): 2009-07-11T13:45:00.000+0200@null: 10.0kn from 278.0� + 2009-07-11T13:45:05.000+0200@null: 10.0kn from 265.0� avg(30000ms): 2009-07-11T13:45:05.000+0200@null: 10.0kn from 269.0� + 2009-07-12T17:31:40.000+0200@null: 10.0kn from 260.0� avg(30000ms): 2009-07-12T17:31:40.000+0200@null: 10.0kn from 260.0� + + Now assume a query for 2009-07-12T17:30:00 which is closest to the newest entry but (much) more than + the averaging interval after the previous entry (2009-07-11T13:45:05.000). This test ensures that + the WindTrack uses the newer entry even though it's after the time point requested because it's + much closer, and the previous entry would be out of the averaging interval anyway. + */ + SimpleDateFormat df = new SimpleDateFormat("yyyy-DD-mm'T'hh:mm:ss"); + Wind wind1 = new WindImpl(null, new MillisecondsTimePoint(df.parse("2009-07-11T13:45:00").getTime()), + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(98))); + Wind wind2 = new WindImpl(null, new MillisecondsTimePoint(df.parse("2009-07-11T13:45:05").getTime()), + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(85))); + Wind wind3 = new WindImpl(null, new MillisecondsTimePoint(df.parse("2009-07-11T17:31:40").getTime()), + new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(80))); + WindTrack track = new WindTrackImpl(/* millisecondsOverWhichToAverage */ 30000); + track.add(wind1); + track.add(wind2); + track.add(wind3); + TimePoint timePoint = new MillisecondsTimePoint(df.parse("2009-07-11T17:31:38").getTime()); + Wind result = track.getEstimatedWind(null, timePoint); + assertEquals(wind3.getKnots(), result.getKnots(), 0.000000001); + assertEquals(wind3.getBearing().getDegrees(), result.getBearing().getDegrees(), 0.0000000001); + } }