Merge remote-tracking branch 'origin/master' into design2015

Conflicts:
	java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch
	java/com.sap.sailing.gwt.ui/SailingGWT.launch
This commit is contained in:
Steffen Schaefer committed 2015-05-28 09:55:11 +02:00
commit e07c585934
36 files changed
+230 -148

No files matched your search

@@ -1,4 +1,4 @@
<<<<<<< HEAD:java/com.googlecode.mgwt/.settings/org.eclipse.jdt.core.prefs
<<<<<<< HEAD:java/com.googlecode.mgwt/.settings/org.eclipse.jdt.core.prefs
#Thu Jan 19 09:46:08 CET 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
@@ -7,25 +7,25 @@ org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
||||||| merged common ancestors
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
=======
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
>>>>>>> origin/master:java/com.sap.sailing.datamining.test/.settings/org.eclipse.jdt.core.prefs
||||||| merged common ancestors
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
=======
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8
>>>>>>> origin/master:java/com.sap.sailing.datamining.test/.settings/org.eclipse.jdt.core.prefs
@@ -16,4 +16,6 @@ public interface LiveDataConnection {
boolean waitForConnection(long timeoutInMillis) throws InterruptedException;
void addListener(BulkFixReceiver listener);
void removeListener(BulkFixReceiver listener);
}
@@ -26,7 +26,7 @@ public class IgtimiWindTracker extends AbstractWindTracker implements WindTracke
private static final Logger logger = Logger.getLogger(IgtimiWindTracker.class.getName());
private static final int TIME_INTERVAL_TO_TRACK_BEFORE_RACE_START_MILLIS = 10*60*1000; // 10 minutes
private static final long TIME_INTERVAL_TO_TRACK_AFTER_END_OF_RACE_MILLIS = 60*60*1000; // 60 minutes
private final Map<LiveDataConnection, Util.Pair<Iterable<String>, Account>> liveConnectionsAndDeviceSerialNumber;
private final Map<LiveDataConnection, Util.Triple<Iterable<String>, Account, IgtimiWindReceiver>> liveConnectionsAndDeviceSerialNumber;
private final IgtimiWindTrackerFactory windTrackerFactory;
private boolean stopping;
@@ -51,7 +51,8 @@ public class IgtimiWindTracker extends AbstractWindTracker implements WindTracke
IgtimiWindReceiver windReceiver = new IgtimiWindReceiver(correctByDeclination ? DeclinationService.INSTANCE : null);
liveConnection.addListener(windReceiver);
windReceiver.addListener(new WindListenerSendingToTrackedRace(Collections.singleton(getTrackedRace()), windTrackerFactory));
liveConnectionsAndDeviceSerialNumber.put(liveConnection, new Util.Pair<Iterable<String>, Account>(devicesWeShouldListenTo, account));
liveConnectionsAndDeviceSerialNumber.put(liveConnection, new Util.Triple<Iterable<String>, Account, IgtimiWindReceiver>(
devicesWeShouldListenTo, account, windReceiver));
}
}
} catch (Exception e) {
@@ -111,15 +112,16 @@ public class IgtimiWindTracker extends AbstractWindTracker implements WindTracke
synchronized (this) {
windTrackerFactory.windTrackerStopped(getTrackedRace().getRace(), this);
for (LiveDataConnection ldc : liveConnectionsAndDeviceSerialNumber.keySet()) {
final Util.Triple<Iterable<String>, Account, IgtimiWindReceiver> deviceSerialNumberAndAccountAndReceiver = liveConnectionsAndDeviceSerialNumber.get(ldc);
try {
logger.info("Stopping Igtimi live connection "+ldc);
ldc.stop();
ldc.stop(); // does reference counting and stops the live connection only if no other client is active anymore
ldc.removeListener(deviceSerialNumberAndAccountAndReceiver.getC());
} catch (Exception e) {
final Util.Pair<Iterable<String>, Account> deviceSerialNumberAndAccount = liveConnectionsAndDeviceSerialNumber.get(ldc);
logger.log(Level.INFO,
"Exception trying to stop Igtimi live connection for wind receiver for race "
+ getTrackedRace().getRace() + " and device " + deviceSerialNumberAndAccount.getA()
+ " in account " + deviceSerialNumberAndAccount.getB());
+ getTrackedRace().getRace() + " and device " + deviceSerialNumberAndAccountAndReceiver.getA()
+ " in account " + deviceSerialNumberAndAccountAndReceiver.getB());
}
}
}
@@ -33,9 +33,12 @@ public class LiveDataConnectionFactoryImpl implements LiveDataConnectionFactory
Util.addAll(deviceSerialNumbers, deviceSerialNumbersAsSet);
LiveDataConnection result = dataConnectionsForDeviceSerialNumbers.get(deviceSerialNumbersAsSet);
if (result == null) {
logger.info("Didn't find an existing Igtimi LiveDataConnection for devices "+deviceSerialNumbersAsSet+"; creating one...");
result = new WebSocketConnectionManager(connectionFactory, deviceSerialNumbers, account);
dataConnectionsForDeviceSerialNumbers.put(deviceSerialNumbersAsSet, result);
deviceSerialNumersForDataConnections.put(result, deviceSerialNumbersAsSet);
} else {
logger.info("Found an existing Igtimi LiveDataConnection for devices "+deviceSerialNumbersAsSet+"; using it.");
}
Integer usageCount = usageCounts.get(result);
if (usageCount == null) {
@@ -34,6 +34,11 @@ public class LiveDataConnectionWrapper implements LiveDataConnection {
actualConnection.addListener(listener);
}
@Override
public void removeListener(BulkFixReceiver listener) {
actualConnection.removeListener(listener);
}
/**
* Makes the actual connection available to other classes in this package, particularly the test classes in the test fragment of the same package
*/
@@ -152,6 +152,11 @@ public class WebSocketConnectionManager extends WebSocketAdapter implements Live
listeners.put(listener, listener);
}
@Override
public void removeListener(BulkFixReceiver listener) {
listeners.remove(listener);
}
private void notifyListeners(List<Fix> fixes) {
for (BulkFixReceiver listener : listeners.keySet()) {
try {
@@ -17,7 +17,7 @@ import com.sap.sse.common.media.MimeType;
*
*/
public interface MediaDB {
/**
* Stores a new track to the database, returning the db-generated id.
*/
@@ -40,7 +40,7 @@ public interface MediaDB {
TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> regattaAndRace);
List<MediaTrack> loadAllMediaTracks();
List<MediaTrack> loadAllMediaTracks();
void deleteMediaTrack(String dbId);
@@ -53,7 +53,7 @@ public interface MediaDB {
void updateDuration(String dbId, Duration duration);
void updateRace(String dbId, Set<RegattaAndRaceIdentifier> race);
MediaDB TEST_STUB = new MediaDB() {
@Override
@@ -61,7 +61,7 @@ public interface MediaDB {
TimePoint startTime, Duration duration, MimeType mimeType,
Set<RegattaAndRaceIdentifier> assignedRaces) {
return "0";
}
}
@Override
public void insertMediaTrackWithId(String dbId, String videoTitle,
@@ -121,8 +121,8 @@ public class MediaDBImpl implements MediaDB {
String dbId = ((ObjectId) dbObject.get(DbNames.Fields._id.name())).toHexString();
String title = (String) dbObject.get(DbNames.Fields.MEDIA_TITLE.name());
String url = (String) dbObject.get(DbNames.Fields.MEDIA_URL.name());
Date startTime = (Date) dbObject.get(DbNames.Fields.STARTTIME.name());
Number duration = (Number) dbObject.get(DbNames.Fields.DURATION_IN_MILLIS.name());
Date startTime = (Date) dbObject.get(DbNames.Fields.STARTTIME.name());
Number duration = (Number) dbObject.get(DbNames.Fields.DURATION_IN_MILLIS.name());
String mimeTypeText = (String) dbObject.get(DbNames.Fields.MIME_TYPE.name());
MimeType mimeType = MimeType.byName(mimeTypeText);
Set<RegattaAndRaceIdentifier> assignedRaces = new HashSet<RegattaAndRaceIdentifier>();
@@ -239,9 +239,9 @@ public class WindEstimationOnConstructedTracksTest extends StoredTrackBasedTest
assertNotNull(estimatedWindDirectionCached);
assertEquals(185., estimatedWindDirectionCached.getBearing().getDegrees(), 0.00000001);
// now add a GPS fix and make sure the cache is invalidated by adding it inside the averaging interval
now = new MillisecondsTimePoint(checkTime.asMillis() + track.getMillisecondsOverWhichToAverageWind()/2);
setBearingForCompetitor(competitors.get(0), now, 330);
setBearingForCompetitor(competitors.get(0), now, 310);
now = new MillisecondsTimePoint(checkTime.asMillis() + track.getMillisecondsOverWhichToAverageWind()/2);
setBearingForCompetitor(competitors.get(0), now, 330);
setBearingForCompetitor(competitors.get(0), now, 310);
Wind estimatedWindDirectionNew = track.getAveragedWind(/* position */ null, checkTime);
assertFalse(cachedFixes.isEmpty());
assertNotNull(estimatedWindDirectionNew);
@@ -68,27 +68,35 @@ public class RaceStartedAndFinishedReceiver extends AbstractReceiverWithQueue<IR
System.out.print("StartStop");
DynamicTrackedRace trackedRace = getTrackedRace(event.getA());
if (trackedRace != null) {
IStartStopData startEndTrackingTimesData = event.getB();
if (startEndTrackingTimesData != null) {
final long startTrackingTime = startEndTrackingTimesData.getStartTime();
TimePoint startOfTracking = startTrackingTime == 0 ? null : getSimulator() == null ?
new MillisecondsTimePoint(startTrackingTime) :
getSimulator().advance(new MillisecondsTimePoint(startTrackingTime));
trackedRace.setStartOfTrackingReceived(startOfTracking);
final long endTrackingTime = startEndTrackingTimesData.getStopTime();
TimePoint endOfTracking = endTrackingTime == 0 ? null : getSimulator() == null ?
new MillisecondsTimePoint(endTrackingTime) :
getSimulator().advance(new MillisecondsTimePoint(endTrackingTime));
trackedRace.setEndOfTrackingReceived(endOfTracking);
}
IStartStopData startEndRaceTimesData = event.getC();
if (startEndRaceTimesData != null) {
final long startTime = startEndRaceTimesData.getStartTime();
TimePoint startOfRace = startTime == 0 ? null : getSimulator() == null ?
new MillisecondsTimePoint(startTime) :
getSimulator().advance(new MillisecondsTimePoint(startTime));
trackedRace.setStartTimeReceived(startOfRace);
// Note that end of race can't currently be set on a tracked race
final IRace race = event.getA();
// An uninitialized race means that all timing data is not valid; we replace start of tracking,
// end of tracking and start time received by null values.
if (!race.isInitialized()) {
trackedRace.setStartOfTrackingReceived(null);
trackedRace.setEndOfTrackingReceived(null);
trackedRace.setStartTimeReceived(null);
} else {
IStartStopData startEndTrackingTimesData = event.getB();
if (startEndTrackingTimesData != null) {
final long startTrackingTime = startEndTrackingTimesData.getStartTime();
TimePoint startOfTracking = startTrackingTime == 0 ? null
: getSimulator() == null ? new MillisecondsTimePoint(startTrackingTime) : getSimulator()
.advance(new MillisecondsTimePoint(startTrackingTime));
trackedRace.setStartOfTrackingReceived(startOfTracking);
final long endTrackingTime = startEndTrackingTimesData.getStopTime();
TimePoint endOfTracking = endTrackingTime == 0 ? null
: getSimulator() == null ? new MillisecondsTimePoint(endTrackingTime) : getSimulator()
.advance(new MillisecondsTimePoint(endTrackingTime));
trackedRace.setEndOfTrackingReceived(endOfTracking);
}
IStartStopData startEndRaceTimesData = event.getC();
if (startEndRaceTimesData != null) {
final long startTime = startEndRaceTimesData.getStartTime();
TimePoint startOfRace = startTime == 0 ? null : getSimulator() == null ? new MillisecondsTimePoint(
startTime) : getSimulator().advance(new MillisecondsTimePoint(startTime));
trackedRace.setStartTimeReceived(startOfRace);
// Note that end of race can't currently be set on a tracked race
}
}
} else {
logger.warning("Couldn't find tracked race for race " + event.getA().getName()
@@ -51,6 +51,8 @@ public interface Series extends SeriesBase {
*/
RaceColumnInSeries addRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry);
RaceColumnInSeries addRaceColumn(int insertIndex, String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry);
void moveRaceColumnUp(String raceColumnName);
void moveRaceColumnDown(String raceColumnName);
@@ -132,10 +132,15 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe
*/
@Override
public RaceColumnInSeries addRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
return addRaceColumn(raceColumns.size(), raceColumnName, trackedRegattaRegistry);
}
@Override
public RaceColumnInSeries addRaceColumn(int insertIndex, String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
RaceColumnInSeriesImpl result = createRaceColumn(raceColumnName, trackedRegattaRegistry);
if (raceColumnListeners.canAddRaceColumnToContainer(result)) {
result.addRaceColumnListener(this);
raceColumns.add(result);
raceColumns.add(insertIndex, result);
raceColumnListeners.notifyListenersAboutRaceColumnAddedToContainer(result);
} else {
result = null;
@@ -75,6 +75,9 @@ public class WaypointPositionAndDistanceCache {
private final TrackedRace trackedRace;
/**
* A synchronized list
*/
private final List<Waypoint> waypoints;
public WaypointPositionAndDistanceCache(TrackedRace race, Duration timeRangeResolution) {
@@ -190,24 +193,28 @@ public class WaypointPositionAndDistanceCache {
SortedMap<TimePoint, Position> map = waypointPositionCache.get(controlPoint);
if (map != null) {
final SortedMap<TimePoint, Position> tailMap = map.tailMap(roundToResolution(affectedTimeRange.from()));
for (Entry<TimePoint, Position> e : tailMap.entrySet()) {
final TimePoint timePoint = e.getKey();
if (timePoint.after(affectedTimeRange.to())) {
break;
}
assert timePoint.equals(roundToResolution(timePoint));
map.remove(timePoint);
synchronized (waypoints) {
for (Waypoint otherWaypoint : waypoints) {
ControlPoint otherControlPoint = otherWaypoint.getControlPoint();
if (otherControlPoint != controlPoint) {
final Map<TimePoint, Distance> distanceMap = distanceCache.get(new Pair<>(controlPoint, otherControlPoint));
if (distanceMap != null) {
distanceMap.remove(timePoint);
}
final Map<TimePoint, Distance> otherDistanceMap = distanceCache.get(new Pair<>(otherControlPoint, controlPoint));
if (otherDistanceMap != null) {
otherDistanceMap.remove(timePoint);
synchronized (map) {
for (Entry<TimePoint, Position> e : tailMap.entrySet()) {
final TimePoint timePoint = e.getKey();
if (timePoint.after(affectedTimeRange.to())) {
break;
}
assert timePoint.equals(roundToResolution(timePoint));
map.remove(timePoint);
synchronized (waypoints) {
for (Waypoint otherWaypoint : waypoints) {
ControlPoint otherControlPoint = otherWaypoint.getControlPoint();
if (otherControlPoint != controlPoint) {
final Map<TimePoint, Distance> distanceMap = distanceCache.get(new Pair<>(controlPoint,
otherControlPoint));
if (distanceMap != null) {
distanceMap.remove(timePoint);
}
final Map<TimePoint, Distance> otherDistanceMap = distanceCache.get(new Pair<>(
otherControlPoint, controlPoint));
if (otherDistanceMap != null) {
otherDistanceMap.remove(timePoint);
}
}
}
}
@@ -774,11 +774,17 @@ public interface TrackedRace extends Serializable {
boolean isUsingMarkPassingCalculator();
/**
* @param timepoint Used for positions of marks and wind information
* Calculates the estimated time it takes a competitor to sail the race, from start to finish.
*
* @param timepoint
* Used for positions of marks and wind information; note that sometimes the marks are not in place yet
* when the race starts and that a windward mark may be collected already before the race finishes.
*
* @return estimated time it takes to complete the race
* @throws NotEnoughDataHasBeenAddedException thrown if not enough polar data has been added or polar data service
* is not available
* @throws NoWindException
*
* @throws NotEnoughDataHasBeenAddedException
* thrown if not enough polar data has been added or polar data service is not available
* @throws NoWindException
*/
Duration getEstimatedTimeToComplete(TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, NoWindException;
+3 -3
View File
@@ -6,9 +6,9 @@
provider-name="SAP">
<description url="http://www.sap.com">
The SAP Sailing Server.
Provides connectivity to a TracTrac live GPS feed as well as a live feed from an Expedition system.
The SAP Sailing Server.
Provides connectivity to a TracTrac live GPS feed as well as a live feed from an Expedition system.
Computes leaderboard information for sailing races and offers RESTful APIs to all of this.
</description>
@@ -4,21 +4,6 @@
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
<booleanAttribute key="com.google.gwt.eclipse.core.CODE_SERVER_PORT_AUTO" value="true"/>
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
<listEntry value="com.sap.sailing.gwt.ui.Leaderboard"/>
<listEntry value="com.sap.sailing.gwt.ui.PolarSheets"/>
<listEntry value="com.sap.sailing.gwt.regattaoverview.RegattaOverview"/>
<listEntry value="com.sap.sailing.gwt.ui.Spectator"/>
<listEntry value="com.sap.sailing.gwt.ui.AdminConsole"/>
<listEntry value="com.sap.sailing.gwt.ui.LeaderboardEditing"/>
<listEntry value="com.sap.sailing.gwt.ui.DataMining"/>
<listEntry value="com.sap.sailing.gwt.Home"/>
<listEntry value="com.sap.sailing.gwt.ui.RaceBoard"/>
<listEntry value="com.sap.sailing.gwt.ui.YoutubePopup"/>
<listEntry value="com.sap.sailing.gwt.AutoPlay"/>
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
</listAttribute>
<booleanAttribute key="com.google.gwt.eclipse.core.SUPERDEVMODE_ENABLED" value="true"/>
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
@@ -71,7 +56,7 @@
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.Home com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-superDevMode -incremental -war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort auto -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.regattaoverview.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.PolarSheets com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.AutoPlay com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.Home com.sap.sailing.gwt.ui.RaceBoard"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms1024m -Xmx3072m"/>
</launchConfiguration>
@@ -31,6 +31,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
@@ -289,14 +290,16 @@ public class RegattaDetailsComposite extends Composite {
final boolean seriesNameChanged = !series.getName().equals(seriesDescriptor.getSeriesName());
final RegattaIdentifier regattaIdentifier = new RegattaName(regatta.getName());
List<RaceColumnDTO> existingRaceColumns = series.getRaceColumns();
final List<String> raceColumnsToAdd = new ArrayList<String>();
final List<String> raceColumnsToRemove = new ArrayList<String>();
final List<Pair<String, Integer>> raceColumnNamesToAddWithInsertIndex = new ArrayList<>();
final List<String> raceColumnsToRemove = new ArrayList<>();
// TODO see bug 1447: the resulting order currently doesn't necessarily match the order of races in this dialog!
int insertIndex = 0;
for (RaceColumnDTO newRaceColumn : newRaceColumns) {
if (!existingRaceColumns.contains(newRaceColumn)) {
raceColumnsToAdd.add(newRaceColumn.getName());
raceColumnNamesToAddWithInsertIndex.add(new Pair<>(newRaceColumn.getName(), insertIndex));
}
insertIndex++;
}
for (RaceColumnDTO existingRaceColumn : existingRaceColumns) {
if (!newRaceColumns.contains(existingRaceColumn)) {
@@ -314,32 +317,32 @@ public class RegattaDetailsComposite extends Composite {
racesToRemove.append(raceColumnToRemove);
}
if (raceColumnsToRemove.isEmpty() || Window.confirm(stringMessages.reallyRemoveRace(racesToRemove.toString()))) {
sailingService.addRaceColumnsToSeries(regattaIdentifier, series.getName(), raceColumnsToAdd,
new AsyncCallback<List<RaceColumnInSeriesDTO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to add race columns " + raceColumnsToAdd
+ " to series " + series.getName() + ": " + caught.getMessage());
}
@Override
public void onSuccess(List<RaceColumnInSeriesDTO> raceColumns) {
regattaRefresher.fillRegattas();
}
});
// first remove:
sailingService.removeRaceColumnsFromSeries(regattaIdentifier, series.getName(), raceColumnsToRemove,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to remove race columns " + raceColumnsToAdd
errorReporter.reportError("Error trying to remove race columns " + raceColumnNamesToAddWithInsertIndex
+ " from series " + series.getName() + ": " + caught.getMessage());
}
@Override
public void onSuccess(Void v) {
regattaRefresher.fillRegattas();
// when successfully removed, insert:
sailingService.addRaceColumnsToSeries(regattaIdentifier, series.getName(), raceColumnNamesToAddWithInsertIndex,
new AsyncCallback<List<RaceColumnInSeriesDTO>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to add race columns " + raceColumnNamesToAddWithInsertIndex
+ " to series " + series.getName() + ": " + caught.getMessage());
}
@Override
public void onSuccess(List<RaceColumnInSeriesDTO> raceColumns) {
regattaRefresher.fillRegattas();
}
});
}
});
if (isMedalChanged || seriesResultDiscardingThresholdsChanged || isStartsWithZeroScoreChanged
@@ -205,7 +205,8 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, UUID defaultCourseAreaUuid,
RegattaConfigurationDTO regattaConfiguration, boolean useStartTimeInference);
List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName,
List<Pair<String, Integer>> columnNames);
void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal,
int[] resultDiscardingThresholds, boolean startsWithZeroScore,
@@ -396,7 +396,7 @@ public interface SailingServiceAsync extends BuildVersionRetriever, FileStorageM
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent,
ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, boolean useStartTimeInference, AsyncCallback<RegattaDTO> callback);
void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<Pair<String, Integer>> columnNames,
AsyncCallback<List<RaceColumnInSeriesDTO>> callback);
void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal,
@@ -78,7 +78,7 @@ public class LeaderboardSettingsFactory {
/* refresh interval */ null, /* name of race to sort */ nameOfRaceToSort,
/* ascending */ true, /* updateUponPlayStateChange */ true, raceColumnSelection.getType(),
/*showAddedScores*/ false, /*showOverallRacesCompleted*/ false,
/*showCompetitorSailIdColumns*/showCompetitorSailIdColumn, /*showCompetitorFullNameColumn*/showCompetitorNameColumn);
/*showCompetitorSailIdColumns*/showCompetitorSailIdColumn, /*showCompetitorFullNameColumn*/showCompetitorNameColumn);
break;
case Replay:
settings = createNewDefaultSettings(namesOfRaceColumnsToShow, namesOfRacesToShow, nameOfRaceToSort, /* autoExpandFirstRace */
@@ -3615,11 +3615,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName,
List<String> columnNames) {
List<Pair<String, Integer>> columnNamesWithInsertIndex) {
List<RaceColumnInSeriesDTO> result = new ArrayList<RaceColumnInSeriesDTO>();
for (String columnName : columnNames) {
for (Pair<String, Integer> columnNameAndInsertIndex : columnNamesWithInsertIndex) {
RaceColumnInSeries raceColumnInSeries = getService().apply(
new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
new AddColumnToSeries(columnNameAndInsertIndex.getB(), regattaIdentifier, seriesName, columnNameAndInsertIndex.getA()));
if (raceColumnInSeries != null) {
result.add(convertToRaceColumnInSeriesDTO(raceColumnInSeries));
}
@@ -3996,11 +3996,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
*/
private void addRaceColumnsToRegattaSeries(RegattaDTO regatta, String eventName) {
for (SeriesDTO series : regatta.series) {
List<String> raceNames = new ArrayList<String>();
List<Pair<String, Integer>> raceNamesAndInsertIndex = new ArrayList<>();
int insertIndex = 0;
for (RaceColumnDTO raceColumnInSeries : series.getRaceColumns()) {
raceNames.add(raceColumnInSeries.getName());
raceNamesAndInsertIndex.add(new Pair<>(raceColumnInSeries.getName(), insertIndex));
insertIndex++;
}
addRaceColumnsToSeries(regatta.getRegattaIdentifier(), series.getName(), raceNames);
addRaceColumnsToSeries(regatta.getRegattaIdentifier(), series.getName(), raceNamesAndInsertIndex);
}
}
@@ -197,7 +197,7 @@ public class PolarFixFilterCriteria implements FilterCriterion<GPSFixMovingWithP
TimePoint raceStartTime = race.getStartOfRace();
TimePoint startTime;
TimePoint passedStartTimePoint = startPassing.getTimePoint();
if (passedStartTimePoint.after(raceStartTime)) {
if (raceStartTime == null || passedStartTimePoint.after(raceStartTime)) {
startTime = passedStartTimePoint;
} else {
startTime = raceStartTime;
@@ -59,4 +59,4 @@ implements JsonDeserializer<Util.Triple<DeviceIdentifier, Serializable, List<GPS
return new Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>>(deviceId, sessionId, fixes);
}
}
}
@@ -37,4 +37,4 @@ public class GPSFixMovingJsonDeserializer extends TypeBasedJsonDeserializer<GPSF
protected String getType() {
return TYPE;
}
}
}
@@ -40,4 +40,4 @@ public class GPSFixMovingNmeaDTOJsonDeserializer extends TypeBasedJsonDeserializ
return fix;
}
}
}
@@ -43,4 +43,4 @@ public class GPSFixNmeaDTOJsonDeserializer extends TypeBasedJsonDeserializer<GPS
return fix;
}
}
}
@@ -43,4 +43,4 @@ public class DeviceAndSessionIdentifierWithGPSFixesSerializer<D extends DeviceId
return result;
}
}
}
@@ -19,4 +19,4 @@ public class GPSFixJsonSerializer implements JsonSerializer<GPSFix> {
return result;
}
}
}
@@ -18,4 +18,4 @@ public class GPSFixMovingJsonSerializer implements JsonSerializer<GPSFixMoving>
return result;
}
}
}
@@ -33,4 +33,4 @@ public class GPSFixMovingNmeaDTOJsonSerializer implements JsonSerializer<GPSFixM
return result;
}
}
}
@@ -52,4 +52,4 @@ public class GPSFixNmeaDTOJsonSerializer implements JsonSerializer<GPSFix> {
return result;
}
}
}
@@ -73,6 +73,8 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim
try {
if (liveDataConnection != null) {
liveDataConnection.stop();
liveDataConnection.removeListener(igtimiWindReceiver);
liveDataConnection.removeListener(this);
}
} catch (Exception e) {
e.printStackTrace();
@@ -97,7 +99,7 @@ public class WindStatusServlet extends SailingServerHttpServlet implements Igtim
out.println("<meta http-equiv=refresh content='10; url="+req.getRequestURI()+"'>");
out.println("</head>");
out.println("<body>");
out.println("<p>Reload wind connectors with parameter reloadWindReceiver=true. This will force a connection reset and a reloading of the wind receivers.</p>");
out.println("<p>Reload wind connectors with parameter <a href=\"/sailingserver/windStatus?reloadWindReceiver=true\">reloadWindReceiver=true</a>. This will force a connection reset and a reloading of the wind receivers.</p>");
out.println("<h3>Igtimi Wind Status ("+igtimiRawMessageCount+" raw messages received)</h3>");
if (lastIgtimiMessages != null && !lastIgtimiMessages.isEmpty()) {
final List<IgtimiMessageInfo> copyOfLastIgtimiMessages;
@@ -12,7 +12,10 @@
<h2>URL: /api/v1/regattas/{regattaname}/races/{racename}/targettime</h2>
<b>Description:</b>
<p>Gets the estimated target time of the race</p>
<p>Gets the estimated time it will take to sail a race. The mark positions and the wind data are
taken from the optional timeasmillis parameter which defaults to the current time. Note that sometimes the marks are not in place yet
when the race starts and that a windward mark may be collected already before the race finishes.
</p>
<br/>
<table>
<tr>
@@ -9,8 +9,18 @@ import com.sap.sailing.server.RacingEventServiceOperation;
public class AddColumnToSeries extends AbstractColumnInSeriesOperation<RaceColumnInSeries> {
private static final long serialVersionUID = 8987540636040301063L;
/**
* -1 means append
*/
private final int insertIndex;
public AddColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
this(/* insertIndex==-1 means append */ -1, regattaIdentifier, seriesName, columnName);
}
public AddColumnToSeries(int insertIndex, RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
super(regattaIdentifier, seriesName, columnName);
this.insertIndex = insertIndex;
}
@Override
@@ -18,7 +28,11 @@ public class AddColumnToSeries extends AbstractColumnInSeriesOperation<RaceColum
RaceColumnInSeries result = null;
Series series = getSeries(toState);
if (series != null) {
result = series.addRaceColumn(getColumnName(), toState);
if (insertIndex == -1) {
result = series.addRaceColumn(getColumnName(), toState);
} else {
result = series.addRaceColumn(insertIndex, getColumnName(), toState);
}
if (result != null && series.getRegatta().isPersistent()) {
toState.updateStoredRegatta(series.getRegatta());
}
+31 -4
View File
@@ -44,10 +44,37 @@ Build number: 10715
- It is possible to add two or more subscriptions for the same subscriber (Reported by Jorge Piera, 02/05/2015)
- If a race is in a not initialized state and it is loaded using the parameters file, the library assumes that
the consumer application wants to load the race and it changes its initialized attribute to true. This assumption
is wrong. Now, if a race is not initialized it will continue being uninitialized until the event administrator
changes its state to initialized (Reported by Axel Uhl, 17/05/2015)
- An initialized race is a race where the tracking is on. A not
initialized race is a race where the tracking is off. If a race is in a
not initialized state and it is loaded using the parameters file, the
library assumes that the consumer application wants to load the race and
it changes its initialized attribute to true (the tracking is on). This
assumption is wrong. Now, if a race is not initialized it will continue
being uninitialized until the event administrator changes its state to
initialized.
When a race changes its state from not initialized to initialized,
some events are thrown in the system:
1.
IRaceStartStopTimesChangeListener.gotTrackingStartStopTime(IRace,
IStartStopData): where the IStartStopData object contains the new
tracking interval.
2. IRacesListener.startTracking(UUID): the UUID is the race
identifier
3. IRacesListener.updateRace(IRace): IRace is the new updated
race where the IRace.isInitialized is true and it has values for both
the getTrackingStartTime and the getTrackingEndTime methods.
When a race changes its state from initialized to not initialized,
the following events are thrown in the system:
1.
IRaceStartStopTimesChangeListener.gotTrackingStartStopTime(IRace,
IStartStopData): where the IStartStopData object contains the null
interval ([0, 0])
2. IRacesListener.abandonRace(UUID): the UUID is the race identifier
3. IRacesListener.updateRace(IRace): IRace is the new updated
race where the IRace.isInitialized is false and it has null values for
both the getTrackingStartTime and the getTrackingEndTime methods.
(Reported by Axel Uhl, 17/05/2015)
********************************************
************* TracAPI 3.0.10 ***************
@@ -28,4 +28,4 @@ steffen: steffen,spectator,moderator,administrator
jacob@sejlsport.dk: !hsf/sf67, eventmanager
m.welte@stg-academy.org: mwelte, eventmanager
e.anders@stg-academy.org: eanders, eventmanager
siegmund@ubilabs.net: psiegmund,spectator,moderator,administrator
siegmund@ubilabs.net: psiegmund,spectator,moderator,administrator