Merge branch 'master' into bug1994

This commit is contained in:
Axel Uhl committed 2014-07-07 18:12:37 +02:00
commit a05c16b9f5
16 files changed
+186 -27

No files matched your search

@@ -32,6 +32,7 @@ import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
@@ -45,6 +46,7 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
@@ -998,4 +1000,16 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
// TODO Auto-generated method stub
}
@Override
public void onAbortedByRaceCommittee(Flags flag) {
// TODO Auto-generated method stub
}
}
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
import com.sap.sailing.domain.tracking.TrackedLeg;
@@ -646,4 +647,10 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
// TODO Auto-generated method stub
}
}
@@ -270,4 +270,12 @@ public interface DomainFactory {
List<Sideline> createSidelines(String raceMetadataString, Iterable<? extends TracTracControlPoint> allEventControlPoints);
/**
* When a tracked race has been created for tracking with the TracTrac adapter, change listeners have to be subscribed to
* the {@link TrackedRace} which will notify certain changes to the race's state to TracTrac. This includes the course layout,
* the start time and whether a race was aborted.
*/
void addTracTracUpdateHandlers(URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername,
String tracTracPassword, RaceDefinition raceDefinition, DynamicTrackedRace trackedRace);
}
@@ -519,16 +519,8 @@ public class DomainFactoryImpl implements DomainFactory {
trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore, EmptyGPSFixStore.INSTANCE,
delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
logger.info("Added race " + raceDefinition + " to regatta " + trackedRegatta.getRegatta());
TracTracCourseDesignUpdateHandler courseDesignHandler = new TracTracCourseDesignUpdateHandler(
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
raceDefinition.getId());
trackedRace.addCourseDesignChangedListener(courseDesignHandler);
TracTracStartTimeUpdateHandler startTimeHandler = new TracTracStartTimeUpdateHandler(
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
raceDefinition.getId());
trackedRace.addStartTimeChangedListener(startTimeHandler);
addTracTracUpdateHandlers(tracTracUpdateURI, tracTracEventUuid, tracTracUsername, tracTracPassword,
raceDefinition, trackedRace);
raceCache.put(raceId, raceDefinition);
raceCache.notifyAll();
} else {
@@ -546,6 +538,23 @@ public class DomainFactoryImpl implements DomainFactory {
}
}
@Override
public void addTracTracUpdateHandlers(URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername,
String tracTracPassword, RaceDefinition raceDefinition, DynamicTrackedRace trackedRace) {
TracTracCourseDesignUpdateHandler courseDesignHandler = new TracTracCourseDesignUpdateHandler(
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
raceDefinition.getId());
trackedRace.addCourseDesignChangedListener(courseDesignHandler);
TracTracStartTimeUpdateHandler startTimeHandler = new TracTracStartTimeUpdateHandler(
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
raceDefinition.getId());
trackedRace.addStartTimeChangedListener(startTimeHandler);
TracTracRaceAbortedHandler raceAbortedHandler = new TracTracRaceAbortedHandler(
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
raceDefinition.getId());
trackedRace.addRaceAbortedListener(raceAbortedHandler);
}
private DynamicTrackedRace createTrackedRace(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines, WindStore windStore, GPSFixStore gpsFixStore,
long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate) {
return trackedRegatta.createTrackedRace(race, sidelines,
@@ -220,13 +220,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<IControlRoute,
windStore, EmptyGPSFixStore.INSTANCE, delayToLiveInMillis, millisecondsOverWhichToAverageWind,
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
raceDefinitionSetToUpdate);
TracTracCourseDesignUpdateHandler courseDesignHandler = new TracTracCourseDesignUpdateHandler(tracTracUpdateURI,
tracTracUsername, tracTracPassword,
getTracTracEvent().getId(), race.getId());
trackedRace.addCourseDesignChangedListener(courseDesignHandler);
TracTracStartTimeUpdateHandler startTimeHandler = new TracTracStartTimeUpdateHandler(tracTracUpdateURI,
tracTracUsername, tracTracPassword, getTracTracEvent().getId(), race.getId());
trackedRace.addStartTimeChangedListener(startTimeHandler);
getDomainFactory().addTracTracUpdateHandlers(tracTracUpdateURI, getTracTracEvent().getId(), tracTracUsername, tracTracPassword, race, trackedRace);
if (!Activator.getInstance().isUseTracTracMarkPassings()) {
new MarkPassingCalculator(trackedRace, true);
}
@@ -0,0 +1,60 @@
package com.sap.sailing.domain.tractracadapter.impl;
import java.io.IOException;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
public class TracTracRaceAbortedHandler extends UpdateHandler implements RaceAbortedListener {
private final static String ACTION = "update_race_status";
private final static Logger logger = Logger.getLogger(TracTracRaceAbortedHandler.class.getName());
public TracTracRaceAbortedHandler(URI updateURI, String tracTracUsername, String tracTracPassword, Serializable tracTracEventId, Serializable raceId) {
super(updateURI, ACTION, tracTracUsername, tracTracPassword, tracTracEventId, raceId);
}
@Override
public void raceAborted(Flags flag) throws MalformedURLException, IOException {
if (!isActive()) {
logger.info("Not sending race abort notification to TracTrac because no URL has been provided.");
return;
}
final String raceStatus;
if (flag == Flags.AP) {
raceStatus = "POSTPONED";
} else {
raceStatus = "ABORTED";
}
Map<String, String> additionalArgs = new HashMap<>();
additionalArgs.put("race_status", raceStatus);
URL raceAbortedURL = buildUpdateURL(additionalArgs);
logger.info("Using " + raceAbortedURL.toString() + " for the race aborted notification!");
HttpURLConnection connection = (HttpURLConnection) raceAbortedURL.openConnection();
try {
setConnectionProperties(connection);
try {
checkAndLogUpdateResponse(connection);
} catch (ParseException e) {
e.printStackTrace();
}
} finally {
if (connection != null) {
connection.disconnect();
} else {
logger.severe("Connection to TracTrac race aborted URL " + raceAbortedURL.toString() + " could not be established");
}
}
}
}
@@ -14,6 +14,7 @@ import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
@@ -62,7 +63,7 @@ public class UpdateHandler {
}
}
protected URL buildUpdateURL(HashMap<String, String> additionalParameters) throws MalformedURLException, UnsupportedEncodingException {
protected URL buildUpdateURL(Map<String, String> additionalParameters) throws MalformedURLException, UnsupportedEncodingException {
String serverUpdateURI = this.updateURI.toString();
// make sure that the update URI always ends with a slash
if (!serverUpdateURI.endsWith("/")) {
@@ -7,6 +7,7 @@ import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sse.common.Util;
public interface DynamicTrackedRace extends TrackedRace {
@@ -96,6 +97,8 @@ public interface DynamicTrackedRace extends TrackedRace {
void onCourseDesignChangedByRaceCommittee(CourseBase courseDesign);
void onStartTimeChangedByRaceCommittee(TimePoint newStartTime);
void onAbortedByRaceCommittee(Flags flag);
void invalidateStartTime();
@@ -0,0 +1,10 @@
package com.sap.sailing.domain.tracking;
import java.io.IOException;
import java.net.MalformedURLException;
import com.sap.sailing.domain.common.racelog.Flags;
public interface RaceAbortedListener {
void raceAborted(Flags flag) throws MalformedURLException, IOException;
}
@@ -9,5 +9,5 @@ import com.sap.sailing.domain.common.TimePoint;
public interface StartTimeChangedListener {
void startTimeChanged(TimePoint newTimePoint) throws MalformedURLException, IOException;
}
@@ -615,6 +615,8 @@ public interface TrackedRace extends Serializable {
void addStartTimeChangedListener(StartTimeChangedListener listener);
void addRaceAbortedListener(RaceAbortedListener listener);
/**
* Tells how far the given <code>competitor</code> was from the start line at the time point of the given seconds before the start.
* <p>
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
import com.sap.sailing.domain.tracking.CourseDesignChangedListener;
@@ -45,6 +46,7 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.GPSTrackListener;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
import com.sap.sailing.domain.tracking.TrackedLeg;
@@ -73,6 +75,7 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
private transient Set<CourseDesignChangedListener> courseDesignChangedListeners;
private transient Set<StartTimeChangedListener> startTimeChangedListeners;
private transient Set<RaceAbortedListener> raceAbortedListeners;
public DynamicTrackedRaceImpl(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines,
WindStore windStore, GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed,
@@ -80,8 +83,9 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
super(trackedRegatta, race, sidelines, windStore, gpsFixStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed,
delayForCacheInvalidationOfWindEstimation);
this.logListener = new DynamicTrackedRaceLogListener(this);
this.courseDesignChangedListeners = new HashSet<CourseDesignChangedListener>();
this.startTimeChangedListeners = new HashSet<StartTimeChangedListener>();
this.courseDesignChangedListeners = new HashSet<>();
this.startTimeChangedListeners = new HashSet<>();
this.raceAbortedListeners = new HashSet<>();
this.raceIsKnownToStartUpwind = race.getBoatClass().typicallyStartsUpwind();
if (!raceIsKnownToStartUpwind) {
Set<WindSource> windSourcesToExclude = new HashSet<WindSource>();
@@ -107,8 +111,9 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
ois.defaultReadObject();
listeners = new HashSet<RaceChangeListener>();
logListener = new DynamicTrackedRaceLogListener(this);
courseDesignChangedListeners = new HashSet<CourseDesignChangedListener>();
startTimeChangedListeners = new HashSet<StartTimeChangedListener>();
courseDesignChangedListeners = new HashSet<>();
startTimeChangedListeners = new HashSet<>();
raceAbortedListeners = new HashSet<>();
}
/**
@@ -854,7 +859,18 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
startTimeChangedListener.startTimeChanged(newStartTime);
}
} catch (IOException e) {
e.printStackTrace();
logger.log(Level.INFO, "Exception trying to notify race status change listeners about start time change", e);
}
}
@Override
public void onAbortedByRaceCommittee(Flags flag) {
try {
for (RaceAbortedListener raceAbortedListener : raceAbortedListeners) {
raceAbortedListener.raceAborted(flag);
}
} catch (IOException e) {
logger.log(Level.INFO, "Exception trying to notify race status change listeners about start time change", e);
}
}
@@ -862,6 +878,12 @@ DynamicTrackedRace, GPSTrackListener<Competitor, GPSFixMoving> {
public void addStartTimeChangedListener(StartTimeChangedListener listener) {
this.startTimeChangedListeners.add(listener);
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
this.raceAbortedListeners.add(listener);
}
/**
* @return The Bearing of a line starting at <code>w</code> that needs to be crossed to pass a mark.
*/
@@ -10,9 +10,11 @@ import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogCourseDesignChangedEvent;
import com.sap.sailing.domain.racelog.RaceLogFlagEvent;
import com.sap.sailing.domain.racelog.RaceLogPassChangeEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.AbortingFlagFinder;
import com.sap.sailing.domain.racelog.analyzing.impl.LastPublishedCourseDesignFinder;
import com.sap.sailing.domain.racelog.analyzing.impl.StartTimeFinder;
import com.sap.sailing.domain.racelog.analyzing.impl.WindFixesFinder;
@@ -34,6 +36,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
private LastPublishedCourseDesignFinder courseDesignFinder;
private StartTimeFinder startTimeFinder;
private AbortingFlagFinder abortingFlagFinder;
public DynamicTrackedRaceLogListener(DynamicTrackedRace trackedRace) {
this.trackedRace = trackedRace;
@@ -49,6 +52,7 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
trackedRace.invalidateEndTime();
courseDesignFinder = new LastPublishedCourseDesignFinder(raceLog);
startTimeFinder = new StartTimeFinder(raceLog);
abortingFlagFinder = new AbortingFlagFinder(raceLog);
initializeWindTrack(raceLog);
analyze();
}
@@ -132,6 +136,11 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
trackedRace.invalidateStartTime();
/* reset start time */
trackedRace.onStartTimeChangedByRaceCommittee(null);
RaceLogFlagEvent abortingFlag = abortingFlagFinder.analyze();
if (abortingFlag != null) {
// previous pass was aborted; notify TracTrac
trackedRace.onAbortedByRaceCommittee(abortingFlag.getUpperFlag());
}
}
@Override
@@ -149,5 +158,4 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
// add the wind fix to the race committee WindTrack
trackedRace.recordWind(event.getWindFix(), raceCommitteeWindSource);
}
}
@@ -31,6 +31,7 @@ import com.sap.sailing.domain.common.Tack;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
@@ -44,6 +45,7 @@ import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.RaceListener;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
@@ -999,4 +1001,16 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
// TODO Auto-generated method stub
}
@Override
public void onAbortedByRaceCommittee(Flags flag) {
// TODO Auto-generated method stub
}
}
@@ -32,6 +32,7 @@ import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.RaceAbortedListener;
import com.sap.sailing.domain.tracking.RaceChangeListener;
import com.sap.sailing.domain.tracking.StartTimeChangedListener;
import com.sap.sailing.domain.tracking.TrackedLeg;
@@ -595,4 +596,10 @@ public class DummyTrackedRace extends TrackedRaceWithWindEssentials {
}
@Override
public void addRaceAbortedListener(RaceAbortedListener listener) {
// TODO Auto-generated method stub
}
}
@@ -97,10 +97,10 @@ public class AbortModeSelectionDialog extends RaceDialogFragment {
TimePoint now = MillisecondsTimePoint.now();
RaceState state = getRaceState();
if (this.abortFlag.equals(Flags.AP)) {
state.setAborted(now, true, additionalFlag);
state.setAborted(now, /* postponed */ true, additionalFlag);
} else if (this.abortFlag.equals(Flags.NOVEMBER)) {
state.setAborted(now, false, additionalFlag);
state.setAborted(now, /* postponed */ false, additionalFlag);
}
state.setAdvancePass(now);
this.dismiss();