Merge branch 'master' of ssh://195.227.10.246/home/trac/git

This commit is contained in:
Simon Pamies committed 2011-06-10 21:49:50 +02:00
commit 0bae880ae6
20 files changed
+268 -91

No files matched your search

-18
View File
@@ -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
@@ -83,5 +83,6 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
@Test
public void testLastWaypointRemoved() {
Iterable<Waypoint> waypoints = course.getWaypoints();
// TODO continue with testLastWaypointRemoved()...
}
}
@@ -66,6 +66,9 @@ public class ReceiveTrackingDataTest extends AbstractTracTracLiveTest {
@Override
public void windDataReceived(Wind wind) {
}
@Override
public void windDataRemoved(Wind wind) {
}
};
List<TypeController> listeners = new ArrayList<TypeController>();
Event event = domainFactory.createEvent(getEvent());
@@ -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);
}
}
@@ -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;
}
}
@@ -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;
}
@@ -90,5 +90,5 @@ public interface TrackedLegOfCompetitor {
* Returns <code>null</code> in case this leg's competitor hasn't started the leg yet.
*/
Double getEstimatedTimeToNextMarkInSeconds(TimePoint timePoint) throws NoWindException;
}
@@ -139,4 +139,6 @@ public interface TrackedRace {
TimePoint getTimePointOfNewestEvent();
NavigableSet<MarkPassing> getMarkPassings(Competitor competitor);
void removeWind(Wind wind, WindSource windSource);
}
@@ -2,4 +2,6 @@ package com.sap.sailing.domain.tracking;
public interface WindListener {
void windDataReceived(Wind wind);
void windDataRemoved(Wind wind);
}
@@ -24,4 +24,6 @@ public interface WindTrack extends Track<Wind> {
* A listener is notified whenever a new fix is added to this track
*/
void addListener(WindListener listener);
void remove(Wind wind);
}
@@ -89,6 +89,17 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
}
}
private void notifyListenersWindRemoved(Wind wind) {
for (RaceChangeListener<Competitor> 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<Competitor> 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());
@@ -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<Competitor> {
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<Competitor, TrackedLegOfCompetitor> trackedLegsOfCompetitors;
private TrackedRaceImpl trackedRace;
@@ -82,6 +88,44 @@ public class TrackedLegImpl implements TrackedLeg, RaceChangeListener<Competitor
}
}
@Override
public boolean isUpOrDownwindLeg(TimePoint at) throws NoWindException {
Wind wind = getWindOnLeg(at);
if (wind == null) {
throw new NoWindException("Need to know wind direction to determine whether leg "+getLeg()+
" is an upwind or downwind leg");
}
// check for all combinations of start/end waypoint buoys:
for (Buoy startBuoy : getLeg().getFrom().getBuoys()) {
Position startBuoyPos = getTrackedRace().getTrack(startBuoy).getEstimatedPosition(at, false);
for (Buoy endBuoy : getLeg().getTo().getBuoys()) {
Position endBuoyPos = getTrackedRace().getTrack(endBuoy).getEstimatedPosition(at, false);
Bearing legBearing = startBuoyPos.getBearingGreatCircle(endBuoyPos);
double deltaDeg = legBearing.getDegrees() - wind.getBearing().getDegrees();
double deltaDegOpposite = legBearing.getDegrees() - wind.getBearing().reverse().getDegrees();
if (Math.min(Math.abs(deltaDeg), Math.abs(deltaDegOpposite)) < UPWIND_DOWNWIND_TOLERANCE_IN_DEG) {
return true;
}
}
}
return false;
}
private Wind getWindOnLeg(TimePoint at) {
Position approximateLegStartPosition = getTrackedRace().getTrack(
getLeg().getFrom().getBuoys().iterator().next()).getEstimatedPosition(at, false);
Position approximateLegEndPosition = getTrackedRace().getTrack(
getLeg().getTo().getBuoys().iterator().next()).getEstimatedPosition(at, false);
Wind wind = getWind(
approximateLegStartPosition.translateGreatCircle(approximateLegStartPosition.getBearingGreatCircle(approximateLegEndPosition),
approximateLegStartPosition.getDistance(approximateLegEndPosition).scale(0.5)), at);
return wind;
}
private Wind getWind(Position p, TimePoint at) {
return getTrackedRace().getWind(p, at);
}
@Override
public void gpsFixReceived(GPSFix fix, Competitor competitor) {
clearCaches();
@@ -97,6 +141,11 @@ public class TrackedLegImpl implements TrackedLeg, RaceChangeListener<Competitor
clearCaches();
}
@Override
public void windDataRemoved(Wind wind) {
clearCaches();
}
private void clearCaches() {
synchronized (competitorTracksOrderedByRank) {
competitorTracksOrderedByRank.clear();
@@ -31,7 +31,6 @@ import com.sap.sailing.domain.tracking.Wind;
public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
private final TrackedLegImpl trackedLeg;
private final Competitor competitor;
private final double UPWIND_DOWNWIND_TOLERANCE_IN_DEG = 40; // TracTrac does 22.5, Marcus Baur suggest 40
public TrackedLegOfCompetitorImpl(TrackedLegImpl trackedLeg, Competitor competitor) {
this.trackedLeg = trackedLeg;
@@ -198,7 +197,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
* @param at the wind estimation is performed for this point in time
*/
private Distance getWindwardDistance(Position pos1, Position pos2, TimePoint at) throws NoWindException {
if (isUpOrDownwindLeg(at)) {
if (getTrackedLeg().isUpOrDownwindLeg(at)) {
Wind wind = getWind(pos1.translateGreatCircle(pos1.getBearingGreatCircle(pos2), pos1.getDistance(pos2).scale(0.5)), at);
Position projectionToLineThroughPos2 = pos1.projectToLineThrough(pos2, wind.getBearing());
return projectionToLineThroughPos2.getDistance(pos2);
@@ -236,43 +235,6 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
return getTrackedRace().getWind(p, at);
}
/**
* Determines whether the current {@link #getLeg() leg} is +/- {@link #UPWIND_DOWNWIND_TOLERANCE_IN_DEG} degrees
* collinear with the current wind's bearing.
*/
private boolean isUpOrDownwindLeg(TimePoint at) throws NoWindException {
Wind wind = getWindOnLeg(at);
if (wind == null) {
throw new NoWindException("Need to know wind direction to determine whether leg "+getLeg()+
" is an upwind or downwind leg");
}
// check for all combinations of start/end waypoint buoys:
for (Buoy startBuoy : getLeg().getFrom().getBuoys()) {
Position startBuoyPos = getTrackedRace().getTrack(startBuoy).getEstimatedPosition(at, false);
for (Buoy endBuoy : getLeg().getTo().getBuoys()) {
Position endBuoyPos = getTrackedRace().getTrack(endBuoy).getEstimatedPosition(at, false);
Bearing legBearing = startBuoyPos.getBearingGreatCircle(endBuoyPos);
double deltaDeg = legBearing.getDegrees() - wind.getBearing().getDegrees();
double deltaDegOpposite = legBearing.getDegrees() - wind.getBearing().reverse().getDegrees();
if (Math.min(Math.abs(deltaDeg), Math.abs(deltaDegOpposite)) < UPWIND_DOWNWIND_TOLERANCE_IN_DEG) {
return true;
}
}
}
return false;
}
private Wind getWindOnLeg(TimePoint at) {
Position approximateLegStartPosition = getTrackedRace().getTrack(
getLeg().getFrom().getBuoys().iterator().next()).getEstimatedPosition(at, false);
Position approximateLegEndPosition = getTrackedRace().getTrack(
getLeg().getTo().getBuoys().iterator().next()).getEstimatedPosition(at, false);
Wind wind = getWind(
approximateLegStartPosition.translateGreatCircle(approximateLegStartPosition.getBearingGreatCircle(approximateLegEndPosition),
approximateLegStartPosition.getDistance(approximateLegEndPosition).scale(0.5)), at);
return wind;
}
@Override
public int getRank(TimePoint timePoint) {
TreeSet<TrackedLegOfCompetitor> competitorTracksByRank = getTrackedLeg().getCompetitorTracksOrderedByRank(timePoint);
@@ -39,12 +39,27 @@ public class WindTrackImpl extends TrackImpl<Wind> 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<Wind> implements WindTrack {
public void addListener(WindListener listener) {
listeners.add(listener);
}
@Override
public void remove(Wind wind) {
getInternalFixes().remove(wind);
notifyListenersAboutRemoval(wind);
}
}
@@ -237,4 +237,10 @@ public class MockedTrackedRace implements DynamicTrackedRace {
return null;
}
@Override
public void removeWind(Wind wind, WindSource windSource) {
// TODO Auto-generated method stub
}
}
@@ -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);
}
}
@@ -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");
}
}
@@ -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");