Merge remote-tracking branch 'origin/master' into mark-rounding-inference

This commit is contained in:
Nick Klose committed 2014-01-28 10:00:11 +01:00
commit 80a646e6dd
96 files changed
+1732 -899

No files matched your search

@@ -8,6 +8,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.sap.sailing.domain.common.LeaderboardType;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
@@ -26,7 +27,7 @@ public abstract class AbstractLeaderboardDTO implements Serializable {
public int[] discardThresholds;
public String regattaName;
public String displayName;
public String defaultCourseAreaIdAsString;
public UUID defaultCourseAreaId;
public String defaultCourseAreaName;
public ScoringSchemeType scoringScheme;
public LeaderboardType type;
@@ -338,7 +338,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
this.setComment(previousVersion.getComment());
}
if (this.defaultCourseAreaIdAsStringUnchanged) {
this.defaultCourseAreaIdAsString = previousVersion.defaultCourseAreaIdAsString;
this.defaultCourseAreaId = previousVersion.defaultCourseAreaId;
}
if (this.defaultCourseAreaNameUnchanged) {
this.defaultCourseAreaName = previousVersion.defaultCourseAreaName;
@@ -497,8 +497,8 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
this.displayName = null;
this.displayNameUnchanged = true;
}
if (Util.equalsWithNull(this.defaultCourseAreaIdAsString, previousVersion.defaultCourseAreaIdAsString)) {
this.defaultCourseAreaIdAsString = null;
if (Util.equalsWithNull(this.defaultCourseAreaId, previousVersion.defaultCourseAreaId)) {
this.defaultCourseAreaId = null;
this.defaultCourseAreaIdAsStringUnchanged = true;
}
if (Util.equalsWithNull(this.defaultCourseAreaName, previousVersion.defaultCourseAreaName)) {
@@ -1,7 +1,13 @@
package com.sap.sailing.domain.common.impl;
import java.net.URLEncoder;
import com.sap.sailing.domain.common.impl.Util.Pair;
/**
* This class is used by our backend, in GWT-client code and by the Android app. Therefore we cannot use classes like
* {@link URLEncoder} to help us with the encoding.
*/
public class QRCodeUtils {
private static final String fragmentKey = "identifier";
@@ -69,15 +69,20 @@ public interface RaceLog extends Track<RaceLogEvent>, WithID {
Iterable<RaceLogEventVisitor> getAllListeners();
/**
* Adds an event to this race log and returns a superset of all race log events (excluding the new
* <code>event</code>) that were added to this race log but not yet returned to the client with ID
* <code>clientId</code> by this method. In general, the list returned is not a true superset but
* equals exactly those events not yet delivered to the client. However, if the server was re-started
* since the client last called this method, and since the underlying data structures are not durably
* stored, the entire set of all race log events would be delivered to the client once.
* Adds an event to this race log and returns {@link RaceLog#getEventsToDeliver(UUID)}
* (excluding the new <code>event</code>)
*/
Iterable<RaceLogEvent> add(RaceLogEvent event, UUID clientId);
/**
* Returns a superset of all race log events that were added to this race log but not yet returned to
* the client with ID <code>clientId</code> by this method. In general, the list returned is not a true
* superset but equals exactly those events not yet delivered to the client. However, if the server
* was re-started since the client last called this method, and since the underlying data structures
* are not durably stored, the entire set of all race log events would be delivered to the client once.
*/
Iterable<RaceLogEvent> getEventsToDeliver(UUID clientId);
/**
* Returns all {@link #getRawFixes() raw fixes} and marks them as delivered to the client identified by <code>clientId</code>
* so that when that ID appears in a subsequent call to {@link #add(RaceLogEvent, UUID)}, the fixes returned by this call
@@ -190,6 +190,11 @@ public class NoAddingRaceLogWrapper implements RaceLog {
return innerRaceLog.getRawFixesDescendingIterator(startingAt, inclusive);
}
@Override
public Iterable<RaceLogEvent> getEventsToDeliver(UUID clientId) {
return innerRaceLog.getEventsToDeliver(clientId);
}
@Override
public Iterable<RaceLogEvent> getFixes(TimePoint from, boolean fromInclusive, TimePoint to, boolean toInclusive) {
return innerRaceLog.getFixes(from, fromInclusive, to, toInclusive);
@@ -152,9 +152,23 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
} else {
logger.warning(String.format("%s (%s) was not added to log. Ignoring", event, event.getClass().getName()));
}
// FIXME lock for read getInternalRawFixes?
LinkedHashSet<RaceLogEvent> stillToDeliverToClient = new LinkedHashSet<RaceLogEvent>(getInternalRawFixes());
stillToDeliverToClient.remove(event);
return getEventsToDeliver(clientId, event);
}
@Override
public Iterable<RaceLogEvent> getEventsToDeliver(UUID clientId) {
return getEventsToDeliver(clientId, null);
}
protected Iterable<RaceLogEvent> getEventsToDeliver(UUID clientId, RaceLogEvent suppressedEvent) {
final LinkedHashSet<RaceLogEvent> stillToDeliverToClient;
lockForRead();
try {
stillToDeliverToClient = new LinkedHashSet<RaceLogEvent>(getInternalRawFixes());
} finally {
unlockAfterRead();
}
stillToDeliverToClient.remove(suppressedEvent);
Set<RaceLogEvent> deliveredToClient = eventsDeliveredToClient.get(clientId);
if (deliveredToClient != null) {
stillToDeliverToClient.removeAll(deliveredToClient);
@@ -163,7 +177,7 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
eventsDeliveredToClient.put(clientId, deliveredToClient);
}
deliveredToClient.addAll(stillToDeliverToClient);
deliveredToClient.add(event);
deliveredToClient.add(suppressedEvent);
return stillToDeliverToClient;
}
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.racelog.state.racingprocedure.basic.impl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -11,6 +12,8 @@ import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEventAuthor;
import com.sap.sailing.domain.racelog.RaceLogEventFactory;
import com.sap.sailing.domain.racelog.state.RaceStateEvent;
import com.sap.sailing.domain.racelog.state.impl.RaceStateEventImpl;
import com.sap.sailing.domain.racelog.state.impl.RaceStateEvents;
import com.sap.sailing.domain.racelog.state.racingprocedure.FlagPoleState;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedureChangedListener;
import com.sap.sailing.domain.racelog.state.racingprocedure.RacingProcedurePrerequisite;
@@ -59,7 +62,7 @@ public class BasicRacingProcedureImpl extends BaseRacingProcedure {
@Override
protected Collection<RaceStateEvent> createStartStateEvents(TimePoint startTime) {
return Collections.emptyList();
return Arrays.<RaceStateEvent>asList(new RaceStateEventImpl(startTime, RaceStateEvents.START));
}
}
@@ -5,6 +5,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
@@ -266,67 +267,75 @@ public class StoreAndForward implements Runnable {
while (!stopped) {
try {
InputStream is = socket.getInputStream();
Pair<String, Long> messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
if (messageAndOptionalSequenceNumber == null) {
// found EOF; stopping
stopped = true;
} else {
// ignore any sequence number contained in the message; we'll create our own
DBObject emptyQuery = new BasicDBObject();
DBObject incrementLastMessageCountQuery = new BasicDBObject().append("$inc",
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 1));
while (!stopped && messageAndOptionalSequenceNumber != null) {
logger.fine("Thread " + this + " received message: "
+ messageAndOptionalSequenceNumber.getA());
DBObject newCountRecord = lastMessageCountCollection.findAndModify(emptyQuery,
incrementLastMessageCountQuery);
lastMessageCount = ((newCountRecord == null) ? 0l : ((Number) newCountRecord
.get(FieldNames.LAST_MESSAGE_COUNT.name())).longValue());
SailMasterMessage message = swissTimingFactory.createMessage(
messageAndOptionalSequenceNumber.getA(), lastMessageCount);
swissTimingAdapterPersistence.storeSailMasterMessage(message);
synchronized (StoreAndForward.this) {
for (OutputStream os : new ArrayList<OutputStream>(streamsToForwardTo)) {
// write the sequence number of the message into the stream before actually writing
// the
// SwissTiming message
try {
transceiver.sendMessage(message, os);
} catch (Exception e) {
logger.log(Level.SEVERE, "Error sending message to " + os, e);
int i = streamsToForwardTo.indexOf(os);
try {
Pair<String, Long> messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
if (messageAndOptionalSequenceNumber == null) {
// found EOF; stopping
stopped = true;
} else {
// ignore any sequence number contained in the message; we'll create our own
DBObject emptyQuery = new BasicDBObject();
DBObject incrementLastMessageCountQuery = new BasicDBObject().append("$inc",
new BasicDBObject().append(FieldNames.LAST_MESSAGE_COUNT.name(), 1));
while (!stopped && messageAndOptionalSequenceNumber != null) {
logger.fine("Thread " + this + " received message: "
+ messageAndOptionalSequenceNumber.getA());
DBObject newCountRecord = lastMessageCountCollection.findAndModify(emptyQuery,
incrementLastMessageCountQuery);
lastMessageCount = ((newCountRecord == null) ? 0l : ((Number) newCountRecord
.get(FieldNames.LAST_MESSAGE_COUNT.name())).longValue());
SailMasterMessage message = swissTimingFactory.createMessage(
messageAndOptionalSequenceNumber.getA(), lastMessageCount);
swissTimingAdapterPersistence.storeSailMasterMessage(message);
synchronized (StoreAndForward.this) {
for (OutputStream os : new ArrayList<OutputStream>(streamsToForwardTo)) {
// write the sequence number of the message into the stream before actually
// writing
// the
// SwissTiming message
try {
os.close();
} catch (Exception exc) {
logger.log(Level.SEVERE, "Exception closing socket output stream " + os
+ " after being unable to forward message " + message, exc);
}
streamsToForwardTo.remove(os);
Socket s = socketsToForwardTo.remove(i);
logger.info("Unable to send to socket " + s
+ ". Trying to close. Removing from sockets to forward to.");
try {
s.close();
} catch (Exception exc) {
logger.log(Level.WARNING, "Exception trying to close socket " + s
+ " after being unable to forward message " + message, exc);
transceiver.sendMessage(message, os);
} catch (Exception e) {
logger.log(Level.SEVERE, "Error sending message to " + os, e);
int i = streamsToForwardTo.indexOf(os);
try {
os.close();
} catch (Exception exc) {
logger.log(Level.SEVERE, "Exception closing socket output stream " + os
+ " after being unable to forward message " + message, exc);
}
streamsToForwardTo.remove(os);
Socket s = socketsToForwardTo.remove(i);
logger.info("Unable to send to socket " + s
+ ". Trying to close. Removing from sockets to forward to.");
try {
s.close();
} catch (Exception exc) {
logger.log(Level.WARNING, "Exception trying to close socket " + s
+ " after being unable to forward message " + message, exc);
}
}
}
}
}
if (!stopped) {
messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
if (messageAndOptionalSequenceNumber == null) {
// received EOF; stopping received
stopped = true;
if (!stopped) {
messageAndOptionalSequenceNumber = transceiver.receiveMessage(is);
if (messageAndOptionalSequenceNumber == null) {
// received EOF; stopping received
stopped = true;
}
}
}
}
} catch (SocketException e) {
logger.log(
Level.INFO,
"Error during receiving message. Terminating this receiver and waiting for another inbound connection.",
e);
stopped = true;
}
// note that we're not changing anything with the sockets to which we forward messages; that will only happen
// if forwarding to any of those sockets fails
} catch (Exception e) {
e.printStackTrace();
if (!stopped) {
logger.log(Level.INFO, "Error during forwarding message. Continuing...", e);
try {
@@ -402,7 +411,7 @@ public class StoreAndForward implements Runnable {
try {
ReceivingThread receivingThread = establishConnection();
if (!isInSailMasterListeningMode()) {
receivingThread.join(); // we're in active connecting mode; wait for thread to die, then trie again
receivingThread.join(); // we're in active connecting mode; wait for thread to die, then try again
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Exception in StoreAndForward", e);
@@ -7,10 +7,10 @@ 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.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.RaceLogPassChangeEvent;
import com.sap.sailing.domain.racelog.RaceLogRaceStatusEvent;
import com.sap.sailing.domain.racelog.RaceLogStartTimeEvent;
import com.sap.sailing.domain.racelog.RaceLogWindFixEvent;
import com.sap.sailing.domain.racelog.analyzing.impl.LastPublishedCourseDesignFinder;
@@ -20,6 +20,10 @@ import com.sap.sailing.domain.racelog.impl.BaseRaceLogEventVisitor;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.Wind;
/**
* TODO: this class could be a good place to leverage more information about a race containing in the {@link RaceLog}.
* This includes for example the {@link RaceLogRaceStatus} indicating the current race's start.
*/
public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
private static final Logger logger = Logger.getLogger(DynamicTrackedRaceLogListener.class.getName());
@@ -83,16 +87,9 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
}
private void analyze() {
analyzeStatus();
analyzeCourseDesign(null);
}
private void analyzeStatus() {
/* RaceLogRaceStatus newStatus = statusAnalyzer.analyze();*/
// TODO: What can we do with the status? Should we use DynamicTrackedRace.setStatus?
}
private void analyzeCourseDesign(CourseBase courseBaseProvidedByEvent) {
CourseBase courseDesign = courseDesignFinder.analyze();
if (courseDesign == null) {
@@ -138,11 +135,6 @@ public class DynamicTrackedRaceLogListener extends BaseRaceLogEventVisitor {
analyzeStartTime(event.getStartTime());
}
@Override
public void visit(RaceLogRaceStatusEvent event) {
analyzeStatus();
}
@Override
public void visit(RaceLogCourseDesignChangedEvent event) {
analyzeCourseDesign(event.getCourseDesign());
+1 -1
View File
@@ -3,7 +3,7 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry excluding="com/sap/sailing/gwt/ui/jre/" kind="src" path="src/main/java"/>
<classpathentry kind="lib" path="WEB-INF/lib/gwt-servlet.jar" sourcepath="/com.google.gwt.osgi/lib/gwt-user.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/lib/gwt-maps-api-3.9.0-build-17.jar"/>
<classpathentry exported="true" kind="lib" path="WEB-INF/lib/gwt-ajaxloader.jar"/>
@@ -49,7 +49,7 @@
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.google.gwt.eclipse.core.moduleClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -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/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/YoutubePopup.html com.sap.sailing.gwt.ui.YoutubePopup -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war &quot;${project_loc:com.sap.sailing.gwt.ui}&quot; -noserver -remoteUI &quot;${gwt_remote_ui_server_port}:${unique_id}&quot; -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -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/TvView.html com.sap.sailing.gwt.ui.TvView -startupUrl /gwt/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.VideoPopup"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m"/>
</launchConfiguration>
+1
View File
@@ -81,6 +81,7 @@
<extraJvmArgs>-Dgwt.persistentunitcache=false</extraJvmArgs>
<userAgents>chrome</userAgents>
<modules>
<module>com.sap.sailing.gwt.ui.EmulatedJRE</module>
<module>com.sap.sailing.gwt.ui.AdminConsole</module>
<module>com.sap.sailing.gwt.ui.Leaderboard</module>
<module>com.sap.sailing.gwt.ui.LeaderboardEditing</module>
@@ -0,0 +1,53 @@
package com.google.gwt.user.client.rpc.core.java.util;
import com.google.gwt.user.client.rpc.CustomFieldSerializer;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
import java.util.UUID;
/**
* Serializer for emulated {@link UUID}.
*/
public class UUID_CustomFieldSerializer extends CustomFieldSerializer<UUID> {
public static void serialize(SerializationStreamWriter streamWriter, UUID instance) throws SerializationException {
streamWriter.writeString(instance.toString());
}
public static UUID instantiate(SerializationStreamReader streamReader) throws SerializationException {
return UUID.fromString(streamReader.readString());
}
public static boolean hasCustomInstantiate() {
return true;
}
public static void deserialize(SerializationStreamReader streamReader, UUID instance)
throws SerializationException {
// no operation
}
@Override
public void serializeInstance(SerializationStreamWriter streamWriter, UUID instance) throws SerializationException {
serialize(streamWriter, instance);
}
@Override
public UUID instantiateInstance(SerializationStreamReader streamReader) throws SerializationException {
return instantiate(streamReader);
}
@Override
public boolean hasCustomInstantiateInstance() {
return hasCustomInstantiate();
}
@Override
public void deserializeInstance(SerializationStreamReader streamReader, UUID instance)
throws SerializationException {
deserialize(streamReader, instance);
}
}
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.adminconsole;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -25,7 +26,7 @@ public class EventDialog extends DataEntryDialog<EventDTO> {
protected TextBox venueEntryField;
protected TextBox publicationUrlEntryField;
protected CheckBox isPublicCheckBox;
protected String id;
protected UUID id;
protected List<TextBox> courseAreaNameEntryFields;
private EventDTO event;
@@ -78,9 +78,9 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo
private void setCourseAreaInDescriptor(LeaderboardDescriptor leaderboard) {
CourseAreaDTO courseArea = getSelectedCourseArea();
if (courseArea == null) {
leaderboard.setCourseAreaIdAsString(null);
leaderboard.setCourseAreaId(null);
} else {
leaderboard.setCourseAreaIdAsString(getSelectedCourseArea().uuidAsString);
leaderboard.setCourseAreaId(getSelectedCourseArea().id);
}
}
@@ -38,7 +38,7 @@ public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog {
sailingEventsListBox = createSailingEventListBox();
for (EventDTO event : existingEvents) {
for (CourseAreaDTO courseArea : event.venue.getCourseAreas()) {
if (courseArea.uuidAsString.equals(leaderboard.getCourseAreaIdAsString())) {
if (courseArea.id.equals(leaderboard.getCourseAreaId())) {
int index = existingEvents.indexOf(event) + 1; // + 1 because of the "Please select... item"
sailingEventsListBox.setSelectedIndex(index);
onEventSelectionChanged();
@@ -50,4 +50,4 @@ public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog {
}
discardThresholdBoxes = new DiscardThresholdBoxes(this, leaderboard.getDiscardThresholds(), stringMessages);
}
}
}
@@ -299,7 +299,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
TextColumn<StrippedLeaderboardDTO> courseAreaColumn = new TextColumn<StrippedLeaderboardDTO>() {
@Override
public String getValue(StrippedLeaderboardDTO leaderboard) {
return leaderboard.defaultCourseAreaIdAsString == null ? "" : leaderboard.defaultCourseAreaName;
return leaderboard.defaultCourseAreaId == null ? "" : leaderboard.defaultCourseAreaName;
}
};
@@ -324,7 +324,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name,
leaderboardDTO.displayName, /* scoring scheme provided by regatta */ null,
leaderboardDTO.discardThresholds, leaderboardDTO.regattaName,
leaderboardDTO.defaultCourseAreaIdAsString);
leaderboardDTO.defaultCourseAreaId);
AbstractLeaderboardDialog dialog = new RegattaLeaderboardEditDialog(Collections
.unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas),
descriptor, stringMessages, errorReporter,
@@ -340,7 +340,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
});
dialog.show();
} else {
LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, leaderboardDTO.displayName, leaderboardDTO.scoringScheme, leaderboardDTO.discardThresholds, leaderboardDTO.defaultCourseAreaIdAsString);
LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, leaderboardDTO.displayName, leaderboardDTO.scoringScheme, leaderboardDTO.discardThresholds, leaderboardDTO.defaultCourseAreaId);
openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, leaderboardDTO.name, descriptor);
}
}
@@ -1111,7 +1111,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
@Override
public void ok(final LeaderboardDescriptor newLeaderboard) {
sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(),
newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaIdAsString(),
newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaId(),
new MarkedAsyncCallback<StrippedLeaderboardDTO>() {
@Override
public void handleFailure(Throwable t) {
@@ -1167,7 +1167,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
private void updateLeaderboard(final String oldLeaderboardName, final LeaderboardDescriptor leaderboardToUpdate) {
sailingService.updateLeaderboard(oldLeaderboardName, leaderboardToUpdate.getName(), leaderboardToUpdate.getDisplayName(),
leaderboardToUpdate.getDiscardThresholds(), leaderboardToUpdate.getCourseAreaIdAsString(), new AsyncCallback<StrippedLeaderboardDTO>() {
leaderboardToUpdate.getDiscardThresholds(), leaderboardToUpdate.getCourseAreaId(), new AsyncCallback<StrippedLeaderboardDTO>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": "
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.UUID;
import com.sap.sailing.domain.common.ScoringSchemeType;
/**
@@ -14,29 +16,29 @@ public class LeaderboardDescriptor {
private ScoringSchemeType scoringScheme;
private int[] discardThresholds;
private String regattaName;
private String courseAreaIdAsString;
private UUID courseAreaId;
public LeaderboardDescriptor() {
}
public LeaderboardDescriptor(String name, String displayName, ScoringSchemeType scoringScheme, int[] discardThresholds, String regattaName, String courseAreaIdAsString) {
public LeaderboardDescriptor(String name, String displayName, ScoringSchemeType scoringScheme, int[] discardThresholds, String regattaName, UUID courseAreaId) {
this.name = name;
this.displayName = displayName;
this.scoringScheme = scoringScheme;
this.discardThresholds = discardThresholds;
this.regattaName = regattaName;
this.courseAreaIdAsString = courseAreaIdAsString;
this.courseAreaId = courseAreaId;
}
/**
* Leaves the {@link #regattaName} <code>null</code>, representing a flexible leaderboard, not a regatta leaderboard
*/
public LeaderboardDescriptor(String name, String displayName, ScoringSchemeType scoringScheme, int[] discardThresholds, String courseAreaIdAsString) {
public LeaderboardDescriptor(String name, String displayName, ScoringSchemeType scoringScheme, int[] discardThresholds, UUID courseAreaId) {
this.name = name;
this.displayName = displayName;
this.scoringScheme = scoringScheme;
this.discardThresholds = discardThresholds;
this.courseAreaIdAsString = courseAreaIdAsString;
this.courseAreaId = courseAreaId;
}
public String getName() {
@@ -84,11 +86,11 @@ public class LeaderboardDescriptor {
this.displayName = displayName;
}
public String getCourseAreaIdAsString() {
return courseAreaIdAsString;
public UUID getCourseAreaId() {
return courseAreaId;
}
public void setCourseAreaIdAsString(String courseAreaId) {
this.courseAreaIdAsString = courseAreaId;
public void setCourseAreaId(UUID courseAreaId) {
this.courseAreaId = courseAreaId;
}
}
@@ -318,7 +318,7 @@ public class RegattaDetailsComposite extends Composite {
if (regatta != null) {
regattaName.setText(regatta.getName());
boatClassName.setText(regatta.boatClass != null ? regatta.boatClass.getName() : "");
defaultCourseArea.setText(regatta.defaultCourseAreaUuidAsString == null ? "" : regatta.defaultCourseAreaName);
defaultCourseArea.setText(regatta.defaultCourseAreaUuid == null ? "" : regatta.defaultCourseAreaName);
if (regatta.configuration != null) {
configuration.setText(stringMessages.configured());
} else {
@@ -221,7 +221,7 @@ public class RegattaListComposite extends Composite implements RegattaDisplayer
private void commitEditedRegatta(final RegattaDTO editedRegatta) {
final RegattaIdentifier regattaName = new RegattaName(editedRegatta.getName());
sailingService.updateRegatta(regattaName, editedRegatta.defaultCourseAreaUuidAsString,
sailingService.updateRegatta(regattaName, editedRegatta.defaultCourseAreaUuid,
editedRegatta.configuration,
new AsyncCallback<Void>() {
@Override
@@ -165,7 +165,7 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega
}
sailingService.createRegatta(newRegatta.getName(), newRegatta.boatClass==null?null:newRegatta.boatClass.getName(),
new RegattaCreationParametersDTO(seriesStructure), true,
newRegatta.scoringScheme, newRegatta.defaultCourseAreaUuidAsString, new AsyncCallback<RegattaDTO>() {
newRegatta.scoringScheme, newRegatta.defaultCourseAreaUuid, new AsyncCallback<RegattaDTO>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to create new regatta " + newRegatta.getName() + ": " + t.getMessage());
@@ -1,6 +1,7 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.List;
import java.util.UUID;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
@@ -105,9 +106,9 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends DataEntryDialog<R
private void setCourseAreaInRegatta(RegattaDTO regatta) {
CourseAreaDTO courseArea = getSelectedCourseArea();
if (courseArea == null) {
regatta.defaultCourseAreaUuidAsString = null;
regatta.defaultCourseAreaUuid = null;
} else {
regatta.defaultCourseAreaUuidAsString = courseArea.uuidAsString;
regatta.defaultCourseAreaUuid = courseArea.id;
regatta.defaultCourseAreaName = courseArea.getName();
}
}
@@ -120,12 +121,12 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends DataEntryDialog<R
return null;
}
private boolean isCourseAreaInEvent(EventDTO event, String courseAreaIdAsString) {
private boolean isCourseAreaInEvent(EventDTO event, UUID courseAreaId) {
if (event.venue == null) {
return false;
}
for (CourseAreaDTO courseArea : event.venue.getCourseAreas()) {
if (courseArea.uuidAsString == courseAreaIdAsString) {
if (courseArea.id.equals(courseAreaId)) {
return true;
}
}
@@ -136,7 +137,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends DataEntryDialog<R
sailingEventsListBox.addItem(stringConstants.selectSailingEvent());
for (EventDTO event : existingEvents) {
sailingEventsListBox.addItem(event.getName());
if (isCourseAreaInEvent(event, regatta.defaultCourseAreaUuidAsString)) {
if (isCourseAreaInEvent(event, regatta.defaultCourseAreaUuid)) {
sailingEventsListBox.setSelectedIndex(sailingEventsListBox.getItemCount() - 1);
fillCourseAreaListBox(event);
}
@@ -162,7 +163,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends DataEntryDialog<R
courseAreaListBox.addItem(stringMessages.selectCourseArea());
for (CourseAreaDTO courseArea : selectedEvent.venue.getCourseAreas()) {
courseAreaListBox.addItem(courseArea.getName());
if (courseArea.uuidAsString == regatta.defaultCourseAreaUuidAsString) {
if (courseArea.id.equals(regatta.defaultCourseAreaUuid)) {
courseAreaListBox.setSelectedIndex(courseAreaListBox.getItemCount() - 1);
}
}
@@ -7,6 +7,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.FieldUpdater;
@@ -267,7 +268,7 @@ public class SailingEventManagementPanel extends SimplePanel implements EventRef
private void removeEvents(Collection<EventDTO> events) {
if (!events.isEmpty()) {
Collection<String> eventIds = new HashSet<String>();
Collection<UUID> eventIds = new HashSet<UUID>();
for (EventDTO event : events) {
eventIds.add(event.id);
}
@@ -5,6 +5,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
@@ -132,9 +133,9 @@ public interface SailingService extends RemoteService {
List<StrippedLeaderboardDTO> getLeaderboardsByEvent(RegattaDTO regatta);
StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThreasholds, String newCourseAreaIdAsString);
StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThreasholds, UUID newCourseAreaId);
StrippedLeaderboardDTO createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, String courseAreaId);
StrippedLeaderboardDTO createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, UUID courseAreaId);
StrippedLeaderboardDTO createRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds);
@@ -156,13 +157,13 @@ public interface SailingService extends RemoteService {
RegattaDTO createRegatta(String regattaName, String boatClassName,
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent,
ScoringSchemeType scoringSchemeType, String defaultCourseAreaId);
ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId);
void removeRegatta(RegattaIdentifier regattaIdentifier);
void removeRegattas(Collection<RegattaIdentifier> regattas);
void updateRegatta(RegattaIdentifier regattaIdentifier, String defaultCourseAreaUuidAsString, RegattaConfigurationDTO regattaConfiguration);
void updateRegatta(RegattaIdentifier regattaIdentifier, UUID defaultCourseAreaUuid, RegattaConfigurationDTO regattaConfiguration);
List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
@@ -250,18 +251,20 @@ public interface SailingService extends RemoteService {
void updateRacesDelayToLive(List<RegattaAndRaceIdentifier> regattaAndRaceIdentifiers, long delayToLiveInMs);
void updateEvent(String eventName, String eventIdAsString, VenueDTO venue, String publicationUrl, boolean isPublic,
void updateEvent(String eventName, UUID eventId, VenueDTO venue, String publicationUrl, boolean isPublic,
List<String> regattaNames);
EventDTO createEvent(String eventName, String venueName, String publicationUrl, boolean isPublic, List<String> courseAreaNames);
void removeEvent(String eventIdAsString);
void removeEvent(UUID eventId);
void removeEvents(Collection<String> eventIdsAsStrings);
void removeEvents(Collection<UUID> eventIds);
void renameEvent(String eventIdAsString, String newName);
void renameEvent(UUID eventId, String newName);
EventDTO getEventByName(String eventName);
EventDTO getEventById(UUID id);
Iterable<String> getScoreCorrectionProviderNames();
@@ -311,17 +314,15 @@ public interface SailingService extends RemoteService {
PolarSheetGenerationResponse generatePolarSheetForRaces(List<RegattaAndRaceIdentifier> selectedRaces,
PolarSheetGenerationSettings settings, String name) throws Exception;
CourseAreaDTO createCourseArea(String eventIdAsString, String courseAreaName);
EventDTO getEventByIdAsString(String eventIdAsString);
CourseAreaDTO createCourseArea(UUID eventId, String courseAreaName);
List<Pair<String, String>> getLeaderboardsNamesOfMetaleaderboard(String metaLeaderboardName);
Pair<String, LeaderboardType> checkLeaderboardName(String leaderboardName);
List<RaceGroupDTO> getRegattaStructureForEvent(String eventIdAsString);
List<RaceGroupDTO> getRegattaStructureForEvent(UUID eventId);
List<RegattaOverviewEntryDTO> getRaceStateEntriesForRaceGroup(String eventIdAsString, List<String> visibleCourseAreas,
List<RegattaOverviewEntryDTO> getRaceStateEntriesForRaceGroup(UUID eventId, List<UUID> visibleCourseAreas,
List<String> visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay);
String getBuildVersion();
@@ -5,6 +5,7 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.datamining.shared.DataMiningSerializationDummy;
@@ -182,9 +183,9 @@ public interface SailingServiceAsync {
void getLeaderboardsByRace(RaceDTO race, AsyncCallback<List<StrippedLeaderboardDTO>> callback);
void updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName,
int[] newDiscardingThreasholds, String newCourseAreaIdAsId, AsyncCallback<StrippedLeaderboardDTO> callback);
int[] newDiscardingThreasholds, UUID newCourseAreaId, AsyncCallback<StrippedLeaderboardDTO> callback);
void createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, String courseAreaId,
void createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, UUID courseAreaId,
AsyncCallback<StrippedLeaderboardDTO> asyncCallback);
void createRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds,
@@ -327,21 +328,21 @@ public interface SailingServiceAsync {
* If there's no event with the name <code>oldName</code> or there's already a event with the name
* <code>newName</code> a {@link IllegalArgumentException} is thrown.
*/
void renameEvent(String eventIdAsString, String newName, AsyncCallback<Void> callback);
void renameEvent(UUID eventId, String newName, AsyncCallback<Void> callback);
/**
* Removes the event with the id <code>id</code> from the service and the persistence store.
*/
void removeEvent(String eventIdAsString, AsyncCallback<Void> callback);
void removeEvent(UUID eventId, AsyncCallback<Void> callback);
void removeEvents(Collection<String> eventIdsAsStrings, AsyncCallback<Void> asyncCallback);
void removeEvents(Collection<UUID> eventIds, AsyncCallback<Void> asyncCallback);
void createEvent(String eventName, String description, String publicationUrl, boolean isPublic, List<String> courseAreaNames, AsyncCallback<EventDTO> callback);
void updateEvent(String eventName, String eventIdAsString, VenueDTO venue, String publicationUrl, boolean isPublic,
void updateEvent(String eventName, UUID eventId, VenueDTO venue, String publicationUrl, boolean isPublic,
List<String> regattaNames, AsyncCallback<Void> callback);
void createCourseArea(String eventIdAsString, String courseAreaName, AsyncCallback<CourseAreaDTO> callback);
void createCourseArea(UUID eventId, String courseAreaName, AsyncCallback<CourseAreaDTO> callback);
void removeRegatta(RegattaIdentifier regattaIdentifier, AsyncCallback<Void> callback);
@@ -361,7 +362,7 @@ public interface SailingServiceAsync {
void createRegatta(String regattaName, String boatClassName,
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent,
ScoringSchemeType scoringSchemeType, String defaultCourseAreaId, AsyncCallback<RegattaDTO> callback);
ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId, AsyncCallback<RegattaDTO> callback);
void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
AsyncCallback<List<RaceColumnInSeriesDTO>> callback);
@@ -425,11 +426,9 @@ public interface SailingServiceAsync {
void generatePolarSheetForRaces(List<RegattaAndRaceIdentifier> selectedRaces,
PolarSheetGenerationSettings settings, String name, AsyncCallback<PolarSheetGenerationResponse> asyncCallback);
void getEventByIdAsString(String eventIdAsString, AsyncCallback<EventDTO> asyncCallback);
void updateRegatta(RegattaIdentifier regattaIdentifier, String defaultCourseAreaUuidAsString, RegattaConfigurationDTO regattaConfiguration, AsyncCallback<Void> callback);
void updateRegatta(RegattaIdentifier regattaIdentifier, UUID defaultCourseAreaUuid, RegattaConfigurationDTO regattaConfiguration, AsyncCallback<Void> callback);
void getLeaderboardDataEntriesForAllRaceColumns(String leaderboardName, Date date, DetailType detailType,
AsyncCallback<List<Triple<String, List<CompetitorDTO>, List<Double>>>> callback);
@@ -442,9 +441,9 @@ public interface SailingServiceAsync {
void stopReplicatingFromMaster(AsyncCallback<Void> asyncCallback);
void getRegattaStructureForEvent(String eventIdAsString, AsyncCallback<List<RaceGroupDTO>> asyncCallback);
void getRegattaStructureForEvent(UUID eventId, AsyncCallback<List<RaceGroupDTO>> asyncCallback);
void getRaceStateEntriesForRaceGroup(String eventIdAsString, List<String> visibleCourseAreas,
void getRaceStateEntriesForRaceGroup(UUID eventId, List<UUID> visibleCourseAreas,
List<String> visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay,
AsyncCallback<List<RegattaOverviewEntryDTO>> markedAsyncCallback);
@@ -482,8 +481,16 @@ public interface SailingServiceAsync {
void removeDeviceConfiguration(DeviceConfigurationMatcherType type, List<String> clientIds, AsyncCallback<Boolean> asyncCallback);
/**
* Sets the a new start time.
* @param dto {@link RaceLogSetStartTimeDTO} identifying the race to set the start time on and the new start time.
*/
void setStartTime(RaceLogSetStartTimeDTO dto, AsyncCallback<Boolean> callback);
/**
* Gets the race's current start time and current pass identifier. If no start time is set, the pass identifier will
* still be returned, but the start time field will be <code>null</code>.
*/
void getStartTime(String leaderboardName, String raceColumnName, String fleetName,
AsyncCallback<Pair<Date, Integer>> callback);
@@ -496,5 +503,7 @@ public interface SailingServiceAsync {
void removeIgtimiAccount(String eMailOfAccountToRemove, AsyncCallback<Void> asyncCallback);
void importWindFromIgtimi(List<RaceDTO> selectedRaces, AsyncCallback<Map<RegattaAndRaceIdentifier, Integer>> asyncCallback);
void getEventById(UUID id, AsyncCallback<EventDTO> callback);
}
@@ -0,0 +1,70 @@
package java.util;
import java.io.Serializable;
/**
* <p><b>Do not use!</b></p>
*
* <p>Emulated version of {@link java.util.UUID}. Use {@link java.util.UUID} instead!</p>
*/
public class UUID implements Serializable, Comparable<UUID> {
private static final long serialVersionUID = -3096287568577694784L;
public static UUID fromString(String value) {
return new UUID(value);
}
public static UUID randomUUID() {
throw new UnsupportedOperationException("Not supported for emulation");
}
private String uuidAsString;
@SuppressWarnings("unused")
private UUID() { /* gwt */
this.uuidAsString = null;
}
protected UUID(String value) {
this.uuidAsString = value;
}
/**
* @throws UnsupportedOperationException
*/
public UUID(long mostSigBits, long leastSigBits) {
throw new UnsupportedOperationException("Not supported for emulation");
}
@Override
public int compareTo(UUID o) {
return uuidAsString.compareTo(o.uuidAsString);
}
@Override
public int hashCode() {
return uuidAsString.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
UUID other = (UUID) obj;
if (uuidAsString == null) {
if (other.uuidAsString != null)
return false;
} else if (!uuidAsString.equals(other.uuidAsString))
return false;
return true;
}
@Override
public String toString() {
return uuidAsString;
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.regattaoverview;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
@@ -51,9 +52,13 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
}
String eventIdAsString = Window.Location.getParameter(PARAM_EVENT);
if (eventIdAsString == null) {
Window.alert("Missing parameter");
return;
}
createAndAddDetailPanel();
createAndAddRegattaPanel(eventIdAsString);
createAndAddRegattaPanel(UUID.fromString(eventIdAsString));
toggleDetailPanel(false);
regattaPanel.setEntryClickedHandler(new EntryHandler() {
@@ -74,9 +79,9 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
containerPanel.setWidgetHidden(detailPanel, !visibile);
}
private void createAndAddRegattaPanel(String eventIdAsString) {
private void createAndAddRegattaPanel(UUID eventId) {
RegattaRaceStatesSettings settings = createRegattaRaceStatesSettingsFromURL();
regattaPanel = new RegattaOverviewPanel(sailingService, this, stringMessages, eventIdAsString, settings);
regattaPanel = new RegattaOverviewPanel(sailingService, this, stringMessages, eventId, settings);
Panel centerPanel = new FlowPanel();
centerPanel.add(regattaPanel);
ScrollPanel scrollPanel = new ScrollPanel(centerPanel);
@@ -94,7 +99,7 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
}
public static RegattaRaceStatesSettings createRegattaRaceStatesSettingsFromURL() {
List<String> visibleCourseAreas = new ArrayList<String>();
List<UUID> visibleCourseAreas = new ArrayList<UUID>();
List<String> visibleRegattas = new ArrayList<String>();
boolean showOnlyCurrentlyRunningRaces = Window.Location.getParameter(PARAM_ONLY_RUNNING_RACES) == null
@@ -104,7 +109,9 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
&& Window.Location.getParameter(PARAM_ONLY_RACES_OF_SAME_DAY).equalsIgnoreCase("true");
if (Window.Location.getParameterMap().containsKey(PARAM_COURSE_AREA)) {
visibleCourseAreas.addAll(Window.Location.getParameterMap().get(PARAM_COURSE_AREA));
for (String value : Window.Location.getParameterMap().get(PARAM_COURSE_AREA)) {
visibleCourseAreas.add(UUID.fromString(value));
}
}
if (Window.Location.getParameterMap().containsKey(PARAM_REGATTA)) {
@@ -114,7 +121,7 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
return new RegattaRaceStatesSettings(visibleCourseAreas, visibleRegattas, showOnlyRacesOfSameDay, showOnlyCurrentlyRunningRaces);
}
public static String getUrl(String eventIdAsString, RegattaRaceStatesSettings settings,
public static String getUrl(UUID eventId, RegattaRaceStatesSettings settings,
boolean isSetVisibleCourseAreasInUrl, boolean isSetVisibleRegattasInUrl) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
String showOnlyCurrentlyRunningRaces = "&" + PARAM_ONLY_RUNNING_RACES + "=" + (settings.isShowOnlyCurrentlyRunningRaces() ? "true" : "false");
@@ -122,11 +129,11 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
StringBuilder visibleCourseAreas = new StringBuilder();
if (isSetVisibleCourseAreasInUrl) {
for (String visibleCourseArea : settings.getVisibleCourseAreas()) {
for (UUID visibleCourseArea : settings.getVisibleCourseAreas()) {
visibleCourseAreas.append('&');
visibleCourseAreas.append(PARAM_COURSE_AREA);
visibleCourseAreas.append('=');
visibleCourseAreas.append(visibleCourseArea);
visibleCourseAreas.append(visibleCourseArea.toString());
}
}
StringBuilder visibleRegattas = new StringBuilder();
@@ -138,7 +145,7 @@ public class RegattaOverviewEntryPoint extends AbstractEntryPoint {
visibleRegattas.append(visibleRegatta);
}
}
String link = URLEncoder.encode("/gwt/RegattaOverview.html?" + PARAM_EVENT+ "=" + eventIdAsString
String link = URLEncoder.encode("/gwt/RegattaOverview.html?" + PARAM_EVENT+ "=" + eventId.toString()
+ visibleCourseAreas.toString()
+ visibleRegattas.toString()
+ showOnlyCurrentlyRunningRaces
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.regattaoverview;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
@@ -41,7 +42,7 @@ public class RegattaOverviewPanel extends SimplePanel {
protected final StringMessages stringMessages;
protected final ErrorReporter errorReporter;
private final String eventIdAsString;
private final UUID eventId;
private EventDTO eventDTO;
private List<RaceGroupDTO> raceGroupDTOs;
private List<EventAndRaceGroupAvailabilityListener> eventRaceGroupListeners;
@@ -71,11 +72,11 @@ public class RegattaOverviewPanel extends SimplePanel {
}
public RegattaOverviewPanel(SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages,
String eventIdAsString, RegattaRaceStatesSettings settings) {
UUID eventId, RegattaRaceStatesSettings settings) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
this.errorReporter = errorReporter;
this.eventIdAsString = eventIdAsString;
this.eventId = eventId;
this.serverUpdateTimer = new Timer(PlayModes.Live, serverUpdateRateInMs);
this.uiUpdateTimer = new Timer(PlayModes.Live, uiUpdateRateInMs);
this.eventDTO = null;
@@ -89,7 +90,7 @@ public class RegattaOverviewPanel extends SimplePanel {
mainPanel.setWidth("100%");
mainPanel.addStyleName(STYLE_CONTENT_WRAPPER);
regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventIdAsString, settings, uiUpdateTimer);
regattaRaceStatesComponent = new RegattaRaceStatesComponent(sailingService, errorReporter, stringMessages, eventId, settings, uiUpdateTimer);
this.eventRaceGroupListeners.add(regattaRaceStatesComponent);
regattaRaceStatesComponent.setWidth("100%");
@@ -191,12 +192,12 @@ public class RegattaOverviewPanel extends SimplePanel {
}
private void retrieveEvent() {
sailingService.getEventByIdAsString(eventIdAsString, new MarkedAsyncCallback<EventDTO>() {
sailingService.getEventById(eventId, new MarkedAsyncCallback<EventDTO>() {
@Override
protected void handleFailure(Throwable cause) {
settingsButton.setEnabled(false);
errorReporter.reportError("Error trying to load event with id " + eventIdAsString + " : "
errorReporter.reportError("Error trying to load event with id " + eventId + " : "
+ cause.getMessage());
}
@@ -228,11 +229,11 @@ public class RegattaOverviewPanel extends SimplePanel {
}
private void retrieveRegattaStructure() {
sailingService.getRegattaStructureForEvent(eventIdAsString, new MarkedAsyncCallback<List<RaceGroupDTO>>() {
sailingService.getRegattaStructureForEvent(eventId, new MarkedAsyncCallback<List<RaceGroupDTO>>() {
@Override
protected void handleFailure(Throwable cause) {
errorReporter.reportError("Error trying to load regattas for event with id " + eventIdAsString + " : "
errorReporter.reportError("Error trying to load regattas for event with id " + eventId + " : "
+ cause.getMessage());
}
@@ -8,6 +8,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.SafeHtmlCell;
@@ -84,7 +85,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
private final SailingServiceAsync sailingService;
private final StringMessages stringMessages;
private final String eventIdAsString;
private final UUID eventId;
private EventDTO eventDTO;
private List<RaceGroupDTO> raceGroupDTOs;
@@ -121,17 +122,17 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
* timer passed for this argument will be synchronized.
*/
public RegattaRaceStatesComponent(final SailingServiceAsync sailingService, ErrorReporter errorReporter,
final StringMessages stringMessages, final String eventIdAsString, RegattaRaceStatesSettings settings, Timer timerToSynchronize) {
final StringMessages stringMessages, final UUID eventId, RegattaRaceStatesSettings settings, Timer timerToSynchronize) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
this.eventIdAsString = eventIdAsString;
this.eventId = eventId;
this.allEntries = new ArrayList<RegattaOverviewEntryDTO>();
this.timerToSynchronize = timerToSynchronize;
this.eventDTO = null;
this.raceGroupDTOs = null;
this.localStorageRegattaOverviewEventKey = LOCAL_STORAGE_REGATTA_OVERVIEW_KEY + eventIdAsString;
this.localStorageRegattaOverviewEventKey = LOCAL_STORAGE_REGATTA_OVERVIEW_KEY + eventId.toString();
this.flagInterpreter = new RaceStateFlagsInterpreter(stringMessages);
@@ -178,11 +179,11 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
/**
*/
protected void loadAndUpdateEventLog() {
if (eventIdAsString == null || eventDTO == null || raceGroupDTOs == null) {
if (eventId == null || eventDTO == null || raceGroupDTOs == null) {
return;
}
final long clientTimeWhenRequestWasSent = System.currentTimeMillis();
sailingService.getRaceStateEntriesForRaceGroup(eventIdAsString, settings.getVisibleCourseAreas(), settings.getVisibleRegattas(),
sailingService.getRaceStateEntriesForRaceGroup(eventId, settings.getVisibleCourseAreas(), settings.getVisibleRegattas(),
settings.isShowOnlyCurrentlyRunningRaces(), settings.isShowOnlyRacesOfSameDay(), new MarkedAsyncCallback<List<RegattaOverviewEntryDTO>>() {
@Override
@@ -576,7 +577,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
@Override
public SettingsDialogComponent<RegattaRaceStatesSettings> getSettingsDialogComponent() {
return new RegattaRaceStatesSettingsDialogComponent(settings, stringMessages, eventIdAsString,
return new RegattaRaceStatesSettingsDialogComponent(settings, stringMessages, eventId,
Collections.unmodifiableList(eventDTO.venue.getCourseAreas()),
Collections.unmodifiableList(raceGroupDTOs));
}
@@ -626,7 +627,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
private void fillVisibleCourseAreasInSettingsIfEmpty() {
if (settings.getVisibleCourseAreas().isEmpty() && eventDTO != null) {
for (CourseAreaDTO courseArea : eventDTO.venue.getCourseAreas()) {
settings.getVisibleCourseAreas().add(courseArea.uuidAsString);
settings.getVisibleCourseAreas().add(courseArea.id);
}
}
}
@@ -664,7 +665,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component
private void storeRegattaRaceStatesSettings(RegattaRaceStatesSettings settings) {
Storage localStorage = Storage.getLocalStorageIfSupported();
if (localStorage != null && eventIdAsString != null) {
if (localStorage != null && eventId != null) {
// delete old value
localStorage.removeItem(localStorageRegattaOverviewEventKey);
@@ -2,22 +2,23 @@ package com.sap.sailing.gwt.ui.regattaoverview;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class RegattaRaceStatesSettings {
private List<String> visibleCourseAreas;
private List<UUID> visibleCourseAreas;
private List<String> visibleRegattas;
private boolean showOnlyRacesOfSameDay;
private boolean showOnlyCurrentlyRunningRaces;
public RegattaRaceStatesSettings() {
this.visibleCourseAreas = new ArrayList<String>();
this.visibleCourseAreas = new ArrayList<UUID>();
this.visibleRegattas = new ArrayList<String>();
this.showOnlyRacesOfSameDay = false;
this.showOnlyCurrentlyRunningRaces = true;
}
public RegattaRaceStatesSettings(List<String> visibleCourseAreas, List<String> visibleRegattas,
public RegattaRaceStatesSettings(List<UUID> visibleCourseAreas, List<String> visibleRegattas,
boolean showOnlyRacesOfSameDay, boolean showOnlyCurrentlyRunningRaces) {
this.visibleCourseAreas = visibleCourseAreas;
this.visibleRegattas = visibleRegattas;
@@ -25,7 +26,7 @@ public class RegattaRaceStatesSettings {
this.showOnlyCurrentlyRunningRaces = showOnlyCurrentlyRunningRaces;
}
public List<String> getVisibleCourseAreas() {
public List<UUID> getVisibleCourseAreas() {
return visibleCourseAreas;
}
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import com.google.gwt.event.dom.client.ClickEvent;
@@ -28,13 +29,13 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
private final StringMessages stringMessages;
private final RegattaRaceStatesSettings initialSettings;
private final String eventIdAsString;
private final UUID eventId;
private final List<CourseAreaDTO> courseAreas;
private final List<RaceGroupDTO> raceGroups;
private CheckBox showOnlyRacesOfSameDayCheckBox;
private CheckBox showOnlyCurrentlyRunningRacesCheckBox;
private final Map<String, CheckBox> courseAreaCheckBoxMap;
private final Map<UUID, CheckBox> courseAreaCheckBoxMap;
private final Map<String, CheckBox> regattaCheckBoxMap;
private final Anchor resultingLink;
private Button courseAreaDeselectButton;
@@ -43,13 +44,13 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
private final static String SETTINGS_DIALOG_COMPONENT = "SettingsDialogComponent";
public RegattaRaceStatesSettingsDialogComponent(RegattaRaceStatesSettings settings, StringMessages stringMessages,
String eventIdAsString, List<CourseAreaDTO> courseAreas, List<RaceGroupDTO> raceGroups) {
UUID eventId, List<CourseAreaDTO> courseAreas, List<RaceGroupDTO> raceGroups) {
this.stringMessages = stringMessages;
this.initialSettings = settings;
this.eventIdAsString = eventIdAsString;
this.eventId = eventId;
this.courseAreas = courseAreas;
this.raceGroups = raceGroups;
this.courseAreaCheckBoxMap = new HashMap<String, CheckBox>();
this.courseAreaCheckBoxMap = new HashMap<UUID, CheckBox>();
this.regattaCheckBoxMap = new HashMap<String, CheckBox>();
this.resultingLink = new Anchor(stringMessages.asLink());
}
@@ -76,10 +77,10 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
boolean allCheckboxesSelected = true;
for (CourseAreaDTO courseAreaDTO : courseAreas) {
CheckBox checkBox = dialog.createCheckbox(courseAreaDTO.getName());
boolean isCourseAreaVisible = Util.contains(initialSettings.getVisibleCourseAreas(), courseAreaDTO.uuidAsString);
boolean isCourseAreaVisible = Util.contains(initialSettings.getVisibleCourseAreas(), courseAreaDTO.id);
allCheckboxesSelected &= isCourseAreaVisible;
checkBox.setValue(isCourseAreaVisible);
courseAreaCheckBoxMap.put(courseAreaDTO.uuidAsString, checkBox);
courseAreaCheckBoxMap.put(courseAreaDTO.id, checkBox);
courseAreaGrid.setWidget(rowIndex, columnIndex++, checkBox);
if(columnIndex == maxCourseAreasPerRow) {
@@ -219,8 +220,8 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
@Override
public RegattaRaceStatesSettings getResult() {
List<String> selectedCourseAreas = new ArrayList<String>();
for (Entry<String, CheckBox> entry : courseAreaCheckBoxMap.entrySet()) {
List<UUID> selectedCourseAreas = new ArrayList<UUID>();
for (Entry<UUID, CheckBox> entry : courseAreaCheckBoxMap.entrySet()) {
if (entry.getValue().getValue()) {
selectedCourseAreas.add(entry.getKey());
}
@@ -249,7 +250,7 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
public String getErrorMessage(RegattaRaceStatesSettings settings) {
String errorMessage = null;
if (errorMessage == null) {
updateLinkUrl(eventIdAsString, settings);
updateLinkUrl(eventId, settings);
}
return errorMessage;
}
@@ -261,7 +262,7 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
return null;
}
private void updateLinkUrl(String eventIdAsString, RegattaRaceStatesSettings settings) {
private void updateLinkUrl(UUID eventId, RegattaRaceStatesSettings settings) {
boolean isSetVisibleCourseAreasInUrl = true;
boolean isSetVisibleRegattasInUrl = true;
if (settings.getVisibleCourseAreas().size() == courseAreas.size()) {
@@ -270,7 +271,7 @@ public class RegattaRaceStatesSettingsDialogComponent implements SettingsDialogC
if (settings.getVisibleRegattas().size() == raceGroups.size()) {
isSetVisibleRegattasInUrl = false;
}
resultingLink.setHref(RegattaOverviewEntryPoint.getUrl(eventIdAsString, settings, isSetVisibleCourseAreasInUrl, isSetVisibleRegattasInUrl));
resultingLink.setHref(RegattaOverviewEntryPoint.getUrl(eventId, settings, isSetVisibleCourseAreasInUrl, isSetVisibleRegattasInUrl));
}
}
@@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.regattaoverview;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
@@ -24,7 +25,7 @@ public class RegattaRaceStatesSettingsJsonDeSerializer implements GwtJsonDeSeria
JSONArray visibleCourseAreas = new JSONArray();
for (int i = 0 ; i < settings.getVisibleCourseAreas().size() ; i++) {
visibleCourseAreas.set(i, new JSONString(settings.getVisibleCourseAreas().get(i)));
visibleCourseAreas.set(i, new JSONString(settings.getVisibleCourseAreas().get(i).toString()));
}
result.put(FIELD_VISIBLE_COURSE_AREAS, visibleCourseAreas);
@@ -47,10 +48,10 @@ public class RegattaRaceStatesSettingsJsonDeSerializer implements GwtJsonDeSeria
JSONBoolean showOnlyRacesOfSameDay = (JSONBoolean) object.get(FIELD_SHOW_ONLY_RACES_OF_SAME_DAY);
JSONArray jsonVisibleCourseAreas = (JSONArray) object.get(FIELD_VISIBLE_COURSE_AREAS);
List<String> visibleCourseAreas = new ArrayList<String>();
List<UUID> visibleCourseAreas = new ArrayList<UUID>();
for (int i = 0 ; i < jsonVisibleCourseAreas.size() ; i++) {
JSONString jsonCourseArea = (JSONString) jsonVisibleCourseAreas.get(i);
visibleCourseAreas.add(jsonCourseArea.stringValue());
visibleCourseAreas.add(UUID.fromString(jsonCourseArea.stringValue()));
}
JSONArray jsonVisibleRegattas = (JSONArray) object.get(FIELD_VISIBLE_REGATTAS);
@@ -1,7 +1,9 @@
package com.sap.sailing.gwt.ui.server;
import java.io.BufferedReader;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.Serializable;
@@ -59,12 +61,12 @@ import com.sap.sailing.datamining.shared.QueryResult;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.CourseBase;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.ControlPointWithTwoMarks;
import com.sap.sailing.domain.base.Mark;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnInSeries;
@@ -668,7 +670,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
regattaDTO.boatClass = new BoatClassDTO(boatClass.getName(), boatClass.getHullLength().getMeters());
}
if (regatta.getDefaultCourseArea() != null) {
regattaDTO.defaultCourseAreaUuidAsString = regatta.getDefaultCourseArea().getId().toString();
regattaDTO.defaultCourseAreaUuid = regatta.getDefaultCourseArea().getId();
regattaDTO.defaultCourseAreaName = regatta.getDefaultCourseArea().getName();
}
regattaDTO.configuration = convertToRegattaConfigurationDTO(regatta.getRegattaConfiguration());
@@ -1822,20 +1824,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public StrippedLeaderboardDTO createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType,
String courseAreaId) {
UUID courseAreaUuid = convertIdentifierStringToUuid(courseAreaId);
UUID courseAreaId) {
return createStrippedLeaderboardDTO(getService().apply(new CreateFlexibleLeaderboard(leaderboardName, leaderboardDisplayName, discardThresholds,
baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaUuid)), false);
}
private UUID convertIdentifierStringToUuid(String identifierToConvert) {
UUID convertedUuid = null;
if (identifierToConvert != null) {
try {
convertedUuid = UUID.fromString(identifierToConvert);
} catch (IllegalArgumentException iae) {}
}
return convertedUuid;
baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaId)), false);
}
public StrippedLeaderboardDTO createRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds) {
@@ -1928,7 +1919,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
leaderboardDTO.scoringScheme = leaderboard.getScoringScheme().getType();
}
if (leaderboard.getDefaultCourseArea() != null) {
leaderboardDTO.defaultCourseAreaIdAsString = leaderboard.getDefaultCourseArea().getId().toString();
leaderboardDTO.defaultCourseAreaId = leaderboard.getDefaultCourseArea().getId();
leaderboardDTO.defaultCourseAreaName = leaderboard.getDefaultCourseArea().getName();
}
leaderboardDTO.setDelayToLiveInMillisForLatestRace(delayToLiveInMillisForLatestRace);
@@ -1959,9 +1950,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, String newCourseAreaIdAsString) {
UUID newCourseAreaUuid = convertIdentifierStringToUuid(newCourseAreaIdAsString);
Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaUuid));
public StrippedLeaderboardDTO updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, UUID newCourseAreaId) {
Leaderboard updatedLeaderboard = getService().apply(new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaId));
return createStrippedLeaderboardDTO(updatedLeaderboard, false);
}
@@ -2761,9 +2751,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public void updateEvent(String eventName, String eventIdAsString, VenueDTO venue, String publicationUrl, boolean isPublic, List<String> regattaNames) {
UUID eventUuid = convertIdentifierStringToUuid(eventIdAsString);
getService().apply(new UpdateEvent(eventUuid, eventName, venue.getName(), publicationUrl, isPublic, regattaNames));
public void updateEvent(String eventName, UUID eventId, VenueDTO venue, String publicationUrl, boolean isPublic, List<String> regattaNames) {
getService().apply(new UpdateEvent(eventId, eventName, venue.getName(), publicationUrl, isPublic, regattaNames));
}
@Override
@@ -2771,35 +2760,32 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
UUID eventUuid = UUID.randomUUID();
getService().apply(new CreateEvent(eventName, venue, publicationUrl, isPublic, eventUuid));
for (String courseAreaName : courseAreaNames) {
createCourseArea(eventUuid.toString(), courseAreaName);
createCourseArea(eventUuid, courseAreaName);
}
return getEventById(eventUuid);
}
@Override
public CourseAreaDTO createCourseArea(String eventIdAsString, String courseAreaName) {
UUID eventUuid = convertIdentifierStringToUuid(eventIdAsString);
CourseArea courseArea = getService().apply(new AddCourseArea(eventUuid, courseAreaName, UUID.randomUUID()));
public CourseAreaDTO createCourseArea(UUID eventId, String courseAreaName) {
CourseArea courseArea = getService().apply(new AddCourseArea(eventId, courseAreaName, UUID.randomUUID()));
return convertToCourseAreaDTO(courseArea);
}
@Override
public void removeEvents(Collection<String> eventIdsAsStrings) {
for (String eventId : eventIdsAsStrings) {
public void removeEvents(Collection<UUID> eventIds) {
for (UUID eventId : eventIds) {
removeEvent(eventId);
}
}
@Override
public void removeEvent(String eventIdAsString) {
UUID eventUuid = convertIdentifierStringToUuid(eventIdAsString);
getService().apply(new RemoveEvent(eventUuid));
public void removeEvent(UUID eventId) {
getService().apply(new RemoveEvent(eventId));
}
@Override
public void renameEvent(String eventIdAsString, String newName) {
UUID eventUuid = convertIdentifierStringToUuid(eventIdAsString);
getService().apply(new RenameEvent(eventUuid, newName));
public void renameEvent(UUID eventId, String newName) {
getService().apply(new RenameEvent(eventId, newName));
}
@Override
@@ -2813,14 +2799,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
return result;
}
@Override
public EventDTO getEventByIdAsString(String eventIdAsString) {
UUID eventUuid = convertIdentifierStringToUuid(eventIdAsString);
return getEventById(eventUuid);
}
private EventDTO getEventById(UUID id) {
@Override
public EventDTO getEventById(UUID id) {
EventDTO result = null;
Event event = getService().getEvent(id);
if (event != null) {
@@ -2835,7 +2816,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
eventDTO.venue.setName(event.getVenue() != null ? event.getVenue().getName() : null);
eventDTO.publicationUrl = event.getPublicationUrl();
eventDTO.isPublic = event.isPublic();
eventDTO.id = event.getId().toString();
eventDTO.id = event.getId();
eventDTO.regattas = new ArrayList<RegattaDTO>();
for (Regatta regatta: event.getRegattas()) {
RegattaDTO regattaDTO = new RegattaDTO();
@@ -2852,14 +2833,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
private CourseAreaDTO convertToCourseAreaDTO(CourseArea courseArea) {
CourseAreaDTO courseAreaDTO = new CourseAreaDTO(courseArea.getName());
courseAreaDTO.uuidAsString = courseArea.getId().toString();
courseAreaDTO.id = courseArea.getId();
return courseAreaDTO;
}
@Override
public List<RaceGroupDTO> getRegattaStructureForEvent(String eventIdAsString) {
public List<RaceGroupDTO> getRegattaStructureForEvent(UUID eventId) {
List<RaceGroupDTO> raceGroups = new ArrayList<RaceGroupDTO>();
Event event = getService().getEvent(convertIdentifierStringToUuid(eventIdAsString));
Event event = getService().getEvent(eventId);
if (event != null) {
for (CourseArea courseArea : event.getVenue().getCourseAreas()) {
for (Leaderboard leaderboard : getService().getLeaderboards().values()) {
@@ -2938,10 +2919,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public void updateRegatta(RegattaIdentifier regattaName, String defaultCourseAreaUuidAsString,
public void updateRegatta(RegattaIdentifier regattaName, UUID defaultCourseAreaUuid,
RegattaConfigurationDTO configurationDTO) {
UUID courseAreaUuid = convertIdentifierStringToUuid(defaultCourseAreaUuidAsString);
getService().apply(new UpdateSpecificRegatta(regattaName, courseAreaUuid, convertToRegattaConfiguration(configurationDTO)));
getService().apply(new UpdateSpecificRegatta(regattaName, defaultCourseAreaUuid, convertToRegattaConfiguration(configurationDTO)));
}
@Override
@@ -2997,13 +2977,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public RegattaDTO createRegatta(String regattaName, String boatClassName,
RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
boolean persistent, ScoringSchemeType scoringSchemeType, String defaultCourseAreaId) {
UUID courseAreaUuid = convertIdentifierStringToUuid(defaultCourseAreaId);
boolean persistent, ScoringSchemeType scoringSchemeType, UUID defaultCourseAreaId) {
Regatta regatta = getService().apply(
new AddSpecificRegatta(
regattaName, boatClassName, UUID.randomUUID(),
seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
persistent, baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaUuid));
persistent, baseDomainFactory.createScoringScheme(scoringSchemeType), defaultCourseAreaId));
return convertToRegattaDTO(regatta);
}
@@ -3164,17 +3143,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public List<RegattaOverviewEntryDTO> getRaceStateEntriesForRaceGroup(String eventIdAsString, List<String> visibleCourseAreaIdsAsString,
public List<RegattaOverviewEntryDTO> getRaceStateEntriesForRaceGroup(UUID eventId, List<UUID> visibleCourseAreaIds,
List<String> visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay) {
List<RegattaOverviewEntryDTO> result = new ArrayList<RegattaOverviewEntryDTO>();
Calendar dayToCheck = Calendar.getInstance();
dayToCheck.setTime(new Date());
Event event = getService().getEvent(convertIdentifierStringToUuid(eventIdAsString));
Event event = getService().getEvent(eventId);
if (event != null) {
for (CourseArea courseArea : event.getVenue().getCourseAreas()) {
if (!visibleCourseAreaIdsAsString.contains(courseArea.getId().toString())) {
if (!visibleCourseAreaIds.contains(courseArea.getId())) {
continue;
}
for (Leaderboard leaderboard : getService().getLeaderboards().values()) {
@@ -3356,7 +3335,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
HttpURLConnection connection = null;
URL serverAddress = null;
GZIPInputStream gzip = null;
InputStream inputStream = null;
BufferedReader rd = null;
try {
serverAddress = createUrl(hostname, port, query);
//set up out communications stuff
@@ -3365,17 +3345,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
connection = (HttpURLConnection)serverAddress.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
// Initial timeout needs to be big enough to allow the first parts of the response to reach this server
connection.setReadTimeout(60000);
connection.connect();
//read the result from the server
BufferedReader rd;
if (compress) {
gzip = new GZIPInputStream(connection.getInputStream());
rd = new BufferedReader(new InputStreamReader(gzip, Charset.forName("UTF-8")));
InputStream timeoutExtendingInputStream = new TimeoutExtendingInputStream(connection.getInputStream(),
connection);
inputStream = new GZIPInputStream(timeoutExtendingInputStream);
} else {
rd = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")));
inputStream = new TimeoutExtendingInputStream(connection.getInputStream(), connection);
}
rd = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
@@ -3391,8 +3374,11 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
long timeToImport = System.currentTimeMillis() - startTime;
logger.info(String.format("Took %s ms overall to import master data.", timeToImport));
try {
if (gzip != null) {
gzip.close();
if (inputStream != null) {
inputStream.close();
}
if (rd != null) {
rd.close();
}
} catch (IOException e) {
}
@@ -3626,7 +3612,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
if (result == null || result.getA() == null) {
return null;
}
return new Pair<Date, Integer>(result.getA().asDate(), result.getB());
return new Pair<Date, Integer>(result.getA() == null ? null : result.getA().asDate(), result.getB());
}
@Override
@@ -3703,4 +3689,33 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
return result;
}
private class TimeoutExtendingInputStream extends FilterInputStream {
private final HttpURLConnection connection;
protected TimeoutExtendingInputStream(InputStream in, HttpURLConnection connection) {
super(in);
this.connection = connection;
}
@Override
public int read() throws IOException {
connection.setReadTimeout(10000);
return super.read();
}
@Override
public int read(byte[] b) throws IOException {
connection.setReadTimeout(10000);
return super.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
connection.setReadTimeout(10000);
return super.read(b, off, len);
}
}
}
@@ -1,11 +1,13 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.UUID;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.dto.NamedDTO;
public class CourseAreaDTO extends NamedDTO implements IsSerializable {
private static final long serialVersionUID = -5279690838452265454L;
public String uuidAsString;
public UUID id;
public CourseAreaDTO() {
}
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.shared;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.dto.NamedDTO;
@@ -13,7 +14,7 @@ public class EventDTO extends NamedDTO implements IsSerializable {
public VenueDTO venue;
public String publicationUrl;
public boolean isPublic;
public String id;
public UUID id;
// maybe temporary: as long it's not clear how a leaderboard group relates to a sailing event
public LeaderboardGroupDTO leaderboardGroup;
@@ -4,6 +4,9 @@ import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO holding all information to set a new start time on a specific race.
*/
public class RaceLogSetStartTimeDTO implements IsSerializable {
public String leaderboardName;
public String raceColumnName;
@@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.RegattaName;
@@ -19,7 +20,7 @@ public class RegattaDTO extends NamedDTO {
public List<RaceWithCompetitorsDTO> races;
public List<SeriesDTO> series;
public ScoringSchemeType scoringScheme;
public String defaultCourseAreaUuidAsString;
public UUID defaultCourseAreaUuid;
public String defaultCourseAreaName;
public DeviceConfigurationDTO.RegattaConfigurationDTO configuration;
@@ -1,63 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='com.google.gwt.debug.Debug'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../AdminConsole.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name="com.google.gwt.resources.Resources" />
<inherits name="com.google.gwt.logging.Logging"/>
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<inherits name="de.csenk.gwt.ws.WebSocket" />
<!-- Fancy DateTimePicker (without the rest of Bootstrap!) -->
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<stylesheet src="../AdminConsoleDateTimePicker.css" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.adminconsole.AdminConsoleEntryPoint'/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
<set-property name="gwt.logging.logLevel" value="FINE"/>
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de" />
<source path='client'/>
<source path='controls'/>
<source path='components'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='masterdataimport'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='test'/>
<source path='actions'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='com.google.gwt.debug.Debug'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../AdminConsole.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name="com.google.gwt.resources.Resources" />
<inherits name="com.google.gwt.logging.Logging"/>
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<inherits name="de.csenk.gwt.ws.WebSocket" />
<!-- Fancy DateTimePicker (without the rest of Bootstrap!) -->
<!-- GWT-Bootstrap License: Apache License, Version 2.0 -->
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<stylesheet src="../AdminConsoleDateTimePicker.css" />
<super-source path="jre" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.adminconsole.AdminConsoleEntryPoint'/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
<set-property name="gwt.logging.logLevel" value="FINE"/>
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='controls'/>
<source path='components'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='masterdataimport'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='test'/>
<source path='actions'/>
<source path='simulator'/>
</module>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<super-source path="jre" />
<extend-property name="locale" values="de"/>
</module>
@@ -1,40 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
<source path='masterdataimport'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='common'/>
<source path='actions'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
<source path='masterdataimport'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='common'/>
<source path='actions'/>
<source path='simulator'/>
</module>
@@ -1,41 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='com.google.gwt.debug.Debug'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.leaderboardedit.LeaderboardEditPage'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='leaderboardedit'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name='com.google.gwt.debug.Debug'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.leaderboardedit.LeaderboardEditPage'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='leaderboardedit'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
@@ -1,34 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../PolarSheets.css" />
<inherits name="com.google.gwt.user.User" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de" />
<source path="client" />
<source path="polarsheets" />
<source path='leaderboard' />
<source path='raceboard' />
<source path='adminconsole' />
<source path='usermanagement' />
<source path='shared' />
<source path='common' />
<source path='actions' />
<source path='masterdataimport'/>
<source path='simulator'/>
<entry-point class="com.sap.sailing.gwt.ui.polarsheets.PolarSheetsEntryPoint">
</entry-point>
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../PolarSheets.css" />
<inherits name="com.google.gwt.user.User" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de" />
<source path="client" />
<source path="polarsheets" />
<source path='leaderboard' />
<source path='raceboard' />
<source path='adminconsole' />
<source path='usermanagement' />
<source path='shared' />
<source path='common' />
<source path='actions' />
<source path='masterdataimport'/>
<source path='simulator'/>
<entry-point class="com.sap.sailing.gwt.ui.polarsheets.PolarSheetsEntryPoint">
</entry-point>
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
</module>
@@ -1,45 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../RaceBoard.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.raceboard.RaceBoardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='controls'/>
<source path='raceboard'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../RaceBoard.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.raceboard.RaceBoardEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='controls'/>
<source path='raceboard'/>
<source path='leaderboard'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
@@ -1,52 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../RegattaOverview.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name="com.google.gwt.resources.Resources" />
<inherits name="com.google.gwt.logging.Logging"/>
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.regattaoverview.RegattaOverviewEntryPoint'/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
<set-property name="gwt.logging.logLevel" value="FINE"/>
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='controls'/>
<source path='components'/>
<source path='regattaoverview'/>
<source path='shared'/>
<source path='test'/>
<source path='actions'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../RegattaOverview.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name="com.google.gwt.resources.Resources" />
<inherits name="com.google.gwt.logging.Logging"/>
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.regattaoverview.RegattaOverviewEntryPoint'/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
<set-property name="gwt.logging.logLevel" value="FINE"/>
<set-property name="gwt.logging.firebugHandler" value="ENABLED" />
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="ENABLED" />
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='controls'/>
<source path='components'/>
<source path='regattaoverview'/>
<source path='shared'/>
<source path='test'/>
<source path='actions'/>
<source path='simulator'/>
</module>
@@ -1,50 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Simulator.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.simulator.Simulator" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.simulator.SimulatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='shared'/>
<source path='client'/>
<source path='actions'/>
<source path='simulator'/>
<inherits name='com.google.gwt.logging.Logging'/>
<set-property name="gwt.logging.enabled" value="FALSE"/>
<!-- Set logging level to INFO -->
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<!-- Add compiler.stackMode to get a readable stacktrace from JavaScript
It generates a set of files in WEB-INF/deploy; those files need to
be placed on the server
-->
<set-property name="compiler.stackMode" value="emulated" />
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Simulator.css" />
<!-- Google Maps API -->
<inherits name='com.google.gwt.maps.Maps' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.simulator.Simulator" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.simulator.SimulatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='shared'/>
<source path='client'/>
<source path='actions'/>
<source path='simulator'/>
<inherits name='com.google.gwt.logging.Logging'/>
<set-property name="gwt.logging.enabled" value="FALSE"/>
<!-- Set logging level to INFO -->
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.simpleRemoteHandler" value="ENABLED" />
<set-property name="gwt.logging.consoleHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<!-- Add compiler.stackMode to get a readable stacktrace from JavaScript
It generates a set of files in WEB-INF/deploy; those files need to
be placed on the server
-->
<set-property name="compiler.stackMode" value="emulated" />
</module>
@@ -1,37 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Spectator.css" />
<inherits name="com.google.gwt.resources.Resources" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.spectator.SpectatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='shared'/>
<source path='spectator'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='usermanagement'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Spectator.css" />
<inherits name="com.google.gwt.resources.Resources" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.spectator.SpectatorEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='shared'/>
<source path='spectator'/>
<source path='adminconsole'/>
<source path='leaderboard'/>
<source path='usermanagement'/>
</module>
@@ -1,44 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<stylesheet src="../RaceBoard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name='com.google.gwt.maps.Maps' />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.tv.TVEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='tv'/>
<source path='leaderboard'/>
<source path='raceboard'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='common'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<stylesheet src="../RaceBoard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<inherits name='com.google.gwt.maps.Maps' />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.tv.TVEntryPoint'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='tv'/>
<source path='leaderboard'/>
<source path='raceboard'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='common'/>
<source path='actions'/>
<source path='masterdataimport'/>
<source path='simulator'/>
</module>
@@ -1,36 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.usermanagement.UserManagementPage'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='simulator'/>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<stylesheet src="../Leaderboard.css" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Other module inherits -->
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<!-- Specify the app entry point class. -->
<entry-point class='com.sap.sailing.gwt.ui.usermanagement.UserManagementPage'/>
<!-- Specify the paths for translatable code -->
<extend-property name="locale" values="de"/>
<source path='client'/>
<source path='usermanagement'/>
<source path='shared'/>
<source path='actions'/>
<source path='simulator'/>
</module>
@@ -1,17 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<stylesheet src="../VideoPopup.css" />
<inherits name="com.google.gwt.user.User" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<entry-point
class="com.sap.sailing.gwt.ui.client.media.popup.VideoPopupWindow" />
<extend-property name="locale" values="de" />
<source path='client/media/popup' />
<source path='client/shared/media' />
<source path='client/media/shared' />
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<stylesheet src="../reset.css" />
<stylesheet src="../VideoPopup.css" />
<inherits name="com.google.gwt.user.User" />
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
<entry-point
class="com.sap.sailing.gwt.ui.client.media.popup.VideoPopupWindow" />
<extend-property name="locale" values="de" />
<source path='client/media/popup' />
<source path='client/shared/media' />
<source path='client/media/shared' />
</module>
@@ -3,7 +3,8 @@
<module>
<inherits name="com.google.gwt.user.User" />
<!-- Other module inherits -->
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<inherits name="com.sap.sailing.datamining.DataMiningDomain" />
@@ -1,5 +1,6 @@
package com.sap.sailing.server.gateway.impl.rc;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.UUID;
import java.util.logging.Logger;
@@ -16,6 +17,7 @@ import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.domain.racelog.RaceLogServletConstants;
import com.sap.sailing.server.RacingEventService;
@@ -63,7 +65,8 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet {
String.format("Missing parameter '%s'.", RaceLogServletConstants.PARAMS_RACE_FLEET_NAME));
return;
}
logger.fine("Post issued for race log of " + leaderboardName + ", " + raceColumnName + ", " + fleetName);
RacingEventService service = getService();
Leaderboard leaderboard = service.getLeaderboardByName(leaderboardName);
@@ -84,36 +87,58 @@ public class AddEntryToRaceLogJsonPostServlet extends AbstractJsonHttpServlet {
return;
}
JsonDeserializer<RaceLogEvent> deserializer = RaceLogEventDeserializer.create(getService().getBaseDomainFactory());
try {
logger.fine("Post issued for " + leaderboardName + ", " + raceColumnName + ", " + fleetName + " to add a race log event");
Object requestBody = JSONValue.parseWithException(request.getReader());
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
logger.fine("JSON requestObject is: " + requestObject.toString());
RaceLogEvent logEvent = deserializer.deserialize(requestObject);
logger.fine("JSON is deserialized to a RaceLogEvent");
Iterable<RaceLogEvent> eventsToSendBackToClient = raceColumn.getRaceLog(fleet).add(logEvent, clientUuid);
JsonSerializer<RaceLogEvent> serializer = RaceLogEventSerializer.create(new CompetitorJsonSerializer());
ServletOutputStream outputStream = response.getOutputStream();
boolean first = true;
outputStream.write('[');
for (RaceLogEvent eventToSendBackToClient : eventsToSendBackToClient) {
if (first) {
first = false;
} else {
outputStream.write(',');
}
outputStream.write(serializer.serialize(eventToSendBackToClient).toJSONString().getBytes());
}
outputStream.write(']');
} catch (ParseException pe) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
String.format("Invalid JSON in request body:\n%s", pe));
logger.warning(String.format("Exception while parsing post request:\n%s", pe.toString()));
RaceLog raceLog = raceColumn.getRaceLog(fleet);
if (raceLog == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Race Log not found.");
return;
}
BufferedReader reader = request.getReader();
StringBuilder requestBody = new StringBuilder();
String line = "";
// TODO: we are remove line feeds here, intented?
while ((line = reader.readLine()) != null) {
requestBody.append(line);
}
reader.close();
if (requestBody.length() == 0) {
logger.fine("Client wants to receive server events");
sendResponse(response, clientUuid, raceLog, raceLog.getEventsToDeliver(clientUuid));
} else {
try {
logger.fine("Client wants to add a race log event");
JsonDeserializer<RaceLogEvent> deserializer = RaceLogEventDeserializer.create(getService().getBaseDomainFactory());
Object requestObject = JSONValue.parseWithException(requestBody.toString());
JSONObject requestJsonObject = Helpers.toJSONObjectSafe(requestObject);
logger.fine("JSON requestObject is: " + requestObject.toString());
RaceLogEvent logEvent = deserializer.deserialize(requestJsonObject);
logger.fine("JSON is deserialized to a RaceLogEvent");
Iterable<RaceLogEvent> eventsToSendBackToClient = raceLog.add(logEvent, clientUuid);
sendResponse(response, clientUuid, raceLog, eventsToSendBackToClient);
} catch (ParseException pe) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
String.format("Invalid JSON in request body:\n%s", pe));
logger.warning(String.format("Exception while parsing post request: %s", pe.toString()));
}
}
}
protected void sendResponse(HttpServletResponse response, final UUID clientUuid, RaceLog raceLog,
Iterable<RaceLogEvent> eventsToSendBackToClient) throws IOException {
JsonSerializer<RaceLogEvent> serializer = RaceLogEventSerializer.create(new CompetitorJsonSerializer());
ServletOutputStream outputStream = response.getOutputStream();
boolean first = true;
outputStream.write('[');
for (RaceLogEvent eventToSendBackToClient : eventsToSendBackToClient) {
if (first) {
first = false;
} else {
outputStream.write(',');
}
outputStream.write(serializer.serialize(eventToSendBackToClient).toJSONString().getBytes());
}
outputStream.write(']');
}
}
@@ -1,7 +1,8 @@
package com.sap.sailing.server.gateway.jaxrs.api;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -13,9 +14,11 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.StreamingOutput;
import org.json.simple.JSONObject;
@@ -32,8 +35,7 @@ public class MasterDataResource extends AbstractSailingServerResource {
@Produces("application/json;charset=UTF-8")
@Path("leaderboardgroups")
public Response getMasterDataByLeaderboardGroups(@QueryParam("names[]") List<String> leaderboardGroupNames,
@QueryParam("compress") Boolean compress)
throws IOException {
@QueryParam("compress") Boolean compress) throws UnsupportedEncodingException {
long startTime = System.currentTimeMillis();
if (compress == null) {
compress = false;
@@ -57,14 +59,22 @@ public class MasterDataResource extends AbstractSailingServerResource {
JSONObject masterData = masterSerializer.serialize(requestedLeaderboardGroupNames);
ResponseBuilder resp;
if (compress) {
byte[] uncompressedResult = masterData.toJSONString().getBytes("UTF-8");
byte[] result;
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(uncompressedResult);
gzip.close();
result = out.toByteArray();
resp = Response.ok(result, MediaType.APPLICATION_JSON).header("Content-Encoding", "gzip");
final byte[] uncompressedResult = masterData.toJSONString().getBytes("UTF-8");
StreamingOutput streamingOutput = new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException, WebApplicationException {
GZIPOutputStream gzip = null;
try {
gzip = new GZIPOutputStream(output);
gzip.write(uncompressedResult);
} finally {
gzip.close();
}
}
};
resp = Response.ok(streamingOutput, MediaType.APPLICATION_JSON).header("Content-Encoding", "gzip");
} else {
String result = masterData.toJSONString();
resp = Response.ok(result, MediaType.APPLICATION_JSON);
@@ -426,7 +426,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
UUID id);
CourseArea addCourseAreaWithoutReplication(UUID eventId, UUID courseAreaId, String courseAreaName);
/**
* Returns a mobile device's configuration.
* @param identifier of the client (may include event)
@@ -454,7 +454,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
Map<DeviceConfigurationMatcher, DeviceConfiguration> getAllDeviceConfigurations();
/**
* Sets a new start time on the RaceLog identified by the passed parameters.
* Forces a new start time on the RaceLog identified by the passed parameters.
* @param leaderboardName name of the RaceLog's leaderboard.
* @param raceColumnName name of the RaceLog's column
* @param fleetName name of the RaceLog's fleet
@@ -469,10 +469,9 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime);
/**
* Gets the start time and pass identifier for the queried race. Returns <code>null</code> if there
* is no attached race log.
* Gets the start time and pass identifier for the queried race. Start time might be <code>null</code>.
*/
Pair<TimePoint, Integer> getStartTime(String leaderboardName, String raceColumnName, String fleetName);
Pair<TimePoint, Integer> getStartTime(String leaderboardName, String raceColumnName, String fleetName);
MongoObjectFactory getMongoObjectFactory();
@@ -235,6 +235,10 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
private final MediaLibrary mediaLibrary;
/**
* Currently valid pairs of {@link DeviceConfigurationMatcher}s and {@link DeviceConfiguration}s.
* The contents of this map is persisted and replicated. See {@link DeviceConfigurationMapImpl}.
*/
protected final DeviceConfigurationMapImpl configurationMap;
private final WindStore windStore;
@@ -1275,14 +1279,12 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
RegattaConfiguration newRegattaConfiguration) {
// We're not doing any renaming of the regatta itself, therefore we don't have to sync on the maps.
Regatta regatta = getRegatta(regattaIdentifier);
synchronized (regatta) {
CourseArea newCourseArea = getCourseArea(newDefaultCourseAreaId);
if (newCourseArea != regatta.getDefaultCourseArea()) {
regatta.setDefaultCourseArea(newCourseArea);
}
regatta.setRegattaConfiguration(newRegattaConfiguration);
mongoObjectFactory.storeRegatta(regatta);
CourseArea newCourseArea = getCourseArea(newDefaultCourseAreaId);
if (newCourseArea != regatta.getDefaultCourseArea()) {
regatta.setDefaultCourseArea(newCourseArea);
}
regatta.setRegattaConfiguration(newRegattaConfiguration);
mongoObjectFactory.storeRegatta(regatta);
return regatta;
}
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sap.sailing.racecommittee.app"
android:versionCode="3"
android:versionName="3.0a - Lasogga" >
android:versionCode="4"
android:versionName="4.1 - Khalid" >
<uses-sdk
android:maxSdkVersion="17"
@@ -83,11 +83,6 @@
<item >Linie</item>
<item >Ablauf</item>
</string-array>
<string-array name="course_element_changers">
<item>Nach oben</item>
<item>Nach unten</item>
<item>Entfernen</item>
</string-array>
<string name="publish">Veröffentlichen</string>
<string name="unpublish">Zurücknehmen</string>
@@ -130,7 +125,7 @@
<string name="store_wind">Windeingaben speichern</string>
<!-- SETTINGS -->
<string name="settings_category_general">Allgemeine Einstellungen</string>
<string name="settings_category_general">Weitere Einstellungen</string>
<string name="settings_general_manageareas_header">Verwaltete Rennbahnen</string>
<string name="settings_general_language_header">Sprache auswählen</string>
<string name="settings_general_language_description">Sprache auswählen. Eventuell muss die App neugestartet werden.</string>
@@ -139,14 +134,17 @@
<string name="settings_category_regattas">Regatta Einstellungen (Speziell)</string>
<string name="settings_category_course_designer">Kursdesigner Einstellungen</string>
<string name="override_default_start_procedure_type_header">Standard Startprozedur überschreiben</string>
<string name="override_default_start_procedure_type_description">Aktivieren wenn Startprozedur der Rennen überschrieben werden soll.</string>
<string name="override_default_start_procedure_type_select_header">Standard Startprozedur (wenn überschrieben)</string>
<string name="override_default_start_procedure_type_select_description">Wenn Option "Standard Startprozedur überschreiben" aktiv ist, wird ausgewählte Startprozedur als Standard gewählt.</string>
<string name="settings_please_reload">Zum Übernehmen der Änderung bitte Aktion \'Neuladen\' durchführen.</string>
<string name="settings_advanced_service_header">Server URL</string>
<string name="settings_advanced_mail_header">Empfänger der Ergebnislisten</string>
<string name="settings_category_polling">Polling Einstellungen</string>
<string name="settings_polling_active_header">Aktiviere Polling</string>
<string name="settings_polling_active_description">Wenn aktiv wird im festgelegten Intervall Änderungen an den Rennen beim Server abgefragt.</string>
<string name="settings_polling_interval_header">Polling Intervall (Minuten)</string>
<!-- SETTINGS -->
<string name="compass_view_compass">Kompass</string>
@@ -182,9 +180,60 @@
<string name="loading_configuration">Lade Konfiguration&#8230;</string>
<string name="loading_configuration_failed">Fehler beim Laden der Konfiguration.</string>
<string name="loading_configuration_not_found">Für dieses Gerät existiert keine Konfiguration auf dem Server.</string>
<string name="loading_configuration_not_found">Für dieses Gerät existiert keine Konfiguration auf dem Server.</string>
<string name="loading_configuration_succeded">Konfiguration vom Server übernommen.</string>
<string name="auto_update_install">Installieren</string>
<string name="auto_update_install_anyway">Trotzdem installieren</string>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<string name="choose_xray_flag_down">Einzelrückruf entfernen</string>
<string name="login_type_officer_on_start_vessel">Als Startschiff-Wettfahrleiter einloggen</string>
<string name="login_type_officer_on_finish_vessel">Als Zielschiff-Wettfahrleiter einloggen</string>
<string name="login_type_shore_control">Als Shore-Control einloggen</string>
<string name="generic_error">Fehler</string>
<string name="gate_launch_stops_after">Gate Launch stoppt nach %dmin</string>
<string name="override_default_course_designer_type_select_header">Kursdesigner</string>
<string name="settings_course_designer_by_name_course_names_header">Kursnamen</string>
<string name="enter_new_item">Neues Element eingeben</string>
<string name="add">Hinzufügen</string>
<string name="there_are_no_items_yet_">Bisher keine Elemente.</string>
<string name="preference_racing_procedure_rrs26_startmode_flags_header">Startmodus Flaggen</string>
<string name="preference_racing_procedure_classflag_header">Klassenflagge</string>
<string name="preference_racing_procedure_hasxray_header">Einzelrückruf</string>
<string name="preference_racing_procedure_hasxray_description">Diese Option aktiviert den Einzelrückruf</string>
<string name="preference_racing_procedure_gatestart_haspathfinder_description">Diese Option aktiviert den Pathfinder</string>
<string name="preference_racing_procedure_gatestart_haspathfinder_header">Pathfinder</string>
<string name="preference_racing_procedure_gatestart_hasadditionalgolfdowntime_description">Diese Option aktiviert das Wählen der zusätzlichen Golfflaggenzeit.</string>
<string name="preference_racing_procedure_gatestart_hasadditionalgolfdowntime_header">Zusätzliche Golfflaggenzeit.</string>
<string name="device_identifier">Gerätename</string>
<string name="synchronize_connection_settings_header">Synchronisiere mit Server</string>
<string name="synchronize_connection_settings_description">Zur Synchronisierung der Gerätekonfiguration vom Server per QR-Code hier klicken.</string>
<string name="update_app_header">Update erzwingen</string>
<string name="update_app_description">Erzwingt ein Update. Es ist besser die Synchronisierung zu nutzen.</string>
<string name="options_menu_info">Technische Informationen</string>
<string name="gate_launch">Gate Launch</string>
<string name="golf_down">Golf</string>
<string name="preference_regatta_specific_title">Regattakonfiguration - %1$s</string>
<string name="preference_regatta_specific_save_title">Speichere %1$s Konfiguration</string>
<string name="preference_regatta_specific_save_description">Hier klicken um Regattakonfiguration für 1$s zu speichern.</string>
<string name="auto_update">Auto-Update</string>
<string name="auto_update_checking_version">Prüfe Versionsinformation auf Server&#8230;</string>
<string name="auto_update_downloading_version">Versuche Versionsinformation von %1$s zu erhalten</string>
<string name="auto_update_version_file_url_invalid">Link zur Versionsinformation ungültig.</string>
<string name="auto_update_click_install">Klicke \'Installieren\' um ein Update auf Version %1$d durchzuführen.</string>
<string name="auto_update_force_install">Es ist bereits die Server-Version installiert (Version %1$d).</string>
<string name="auto_update_already_up_to_date">Alles aktuell!</string>
<string name="auto_update_downloading_apk">Downloade APK vom Server&#8230;</string>
<string name="auto_update_apk_link_invalid">Der Downloadlink ist ungültig.</string>
<string name="auto_update_apk_file_error">Konnte Zieldatei nicht erstellen.</string>
<string name="auto_update_error">Fehler beim Update.</string>
<string name="auto_update_completed">Auto-Update erfolgreich</string>
<string name="auto_update_completed_text">Update erfolgreich ausgeführt. Es sollte erneut mit dem Server synchronisiert werden.</string>
<string name="auto_update_completed_take_me_there">Bring\' mich hin</string>
<string name="wind_gps_is_disabled">GPS ist ausgeschaltet, soll es aktiviert werde?</string>
<string name="rrs26_start_mode_changed_to">Startmodus Flagge verändert zu %1$s</string>
<string name="preference_there_are_no_regattas">Bisher keine Regatta geladen.</string>
<string name="configure_regatta">Konfiguriere Regatta %1$s</string>
</resources>
@@ -23,6 +23,11 @@
<string name="preference_mail_key">mailRecipientPreference</string>
<string name="preference_mail_default">lukas.niemeier@sap.com</string>
<string name="preference_polling_active_key">pollingActivePreference</string>
<bool name="preference_polling_active_default">true</bool>
<string name="preference_polling_interval_key">pollingIntervalPreference</string>
<integer name="preference_polling_interval_default">2</integer>
<string name="preference_racing_procedure_override_key">defaultRacingProcedureType</string>
<string name="preference_racing_procedure_override_default">RRS26</string>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="empty_array"/>
<resources xmlns:tools="http://schemas.android.com/tools">
<string-array name="empty_array" tools:ignore="UnusedResources"/>
<string name="running_on_course">(on course %s)</string>
<string name="course_design_number_waypoints">Course has %s waypoints</string>
@@ -128,13 +128,11 @@
<string name="store_wind">Store wind</string>
<!-- SETTINGS -->
<string name="settings_category_general">General</string>
<string name="settings_category_general">Other</string>
<string name="settings_general_manageareas_header">Managed Course Areas</string>
<string name="settings_general_language_header">Select Language</string>
<string name="settings_general_language_description">Select the language. You might need to restart the app to have changes applied.</string>
<string name="override_default_start_procedure_type_header">Override default start procedure type</string>
<string name="override_default_start_procedure_type_description">Check the box if races should use the start procedure type defined below as a default.</string>
<string name="override_default_start_procedure_type_select_header">Default start procedure type when overriden</string>
<string name="override_default_start_procedure_type_select_description">Races will use selected start procedure type as a default. For this option to be active override checkbox has to be enabled.</string>
@@ -142,6 +140,11 @@
<string name="settings_advanced_service_header">Webservice URL</string>
<string name="settings_advanced_mail_header">Positioning mail recipient</string>
<string name="settings_category_polling">Polling</string>
<string name="settings_polling_active_header">Activate Polling</string>
<string name="settings_polling_active_description">When active the server will be polled for changes.</string>
<string name="settings_polling_interval_header">Polling Interval (minutes)</string>
<string name="compass_view_compass">Compass</string>
<string name="compass_view_needle">Needle</string>
@@ -165,13 +168,13 @@
<string name="today">Today</string>
<string name="start">Start</string>
<string name="application_information">Application Information</string>
<string name="application_identifier">Identifier</string>
<string name="application_version">Version</string>
<string name="application_install_date">Install Date</string>
<string name="persistence_information">Persistence Status</string>
<string name="persistence_waiting_events">Waiting events</string>
<string name="persistence_waiting_clear_events">Clear events</string>
<string name="application_information" translatable="false">Application Information</string>
<string name="application_identifier" translatable="false">Identifier</string>
<string name="application_install_date" translatable="false">Install Date</string>
<string name="persistence_information" translatable="false">Persistence Status</string>
<string name="persistence_waiting_clear_events" translatable="false">Clear events</string>
<string name="persistence_waiting_events" translatable="false">Waiting events</string>
<string name="application_version" translatable="false">Version</string>
<string name="generic_error">Error</string>
@@ -195,8 +198,6 @@
<string name="settings_category_regatta_defaults">Regatta Configuration (default)</string>
<string name="settings_category_regattas">Regatta Configuration (specific)</string>
<string name="settings_category_course_designer">Course Designer Configuration</string>
<string name="override_default_course_designer_type_header">Override Course Designer type</string>
<string name="override_default_course_designer_type_description">Use configured Course Designer instead of race\'s.</string>
<string name="override_default_course_designer_type_select_header">Course Designer type</string>
<string name="settings_course_designer_by_name_course_names_header">Course Names</string>
@@ -228,4 +229,22 @@
<string name="preference_regatta_specific_title">Regatta Configuration - %1$s</string>
<string name="preference_regatta_specific_save_title">Save %1$s configuration</string>
<string name="preference_regatta_specific_save_description">This will save the shown configuration for all races of %1$s.</string>
<string name="auto_update">Auto-Update</string>
<string name="auto_update_checking_version">Checking for version information on server&#8230;</string>
<string name="auto_update_downloading_version">Trying to download auto-update info from %1$s</string>
<string name="auto_update_version_file_url_invalid">The version file link was not valid.</string>
<string name="auto_update_click_install">Click \'Install\' to perform the update to version %1$d.</string>
<string name="auto_update_force_install">You already have installed the version offered by the server (version %1$d).</string>
<string name="auto_update_already_up_to_date">You are already up to date!</string>
<string name="auto_update_downloading_apk">Downloading APK from server&#8230;</string>
<string name="auto_update_apk_link_invalid">The download link was not valid.</string>
<string name="auto_update_apk_file_error">The download file couldn\'t be created.</string>
<string name="auto_update_error">Error while trying to auto-update.</string>
<string name="auto_update_completed">Auto-Update completed</string>
<string name="auto_update_completed_text">The automatic update has been completed. You should now re-synchronize your connection settings with the server.</string>
<string name="auto_update_completed_take_me_there">Take me there</string>
<string name="wind_gps_is_disabled">Your GPS seems to be disabled, do you want to enable it?</string>
<string name="rrs26_start_mode_changed_to">Start mode flag changed to %1$s</string>
<string name="preference_there_are_no_regattas">There are no regattas loaded.</string>
<string name="configure_regatta">Configure regatta %1$s</string>
</resources>
@@ -29,6 +29,21 @@
</PreferenceCategory>
<PreferenceCategory android:title="@string/settings_category_polling">
<CheckBoxPreference
android:key="@string/preference_polling_active_key"
android:defaultValue="@bool/preference_polling_active_default"
android:title="@string/settings_polling_active_header"
android:summary="@string/settings_polling_active_description" />
<com.sap.sailing.racecommittee.app.ui.views.IntegerEditTextPreference
android:key="@string/preference_polling_interval_key"
android:defaultValue="@integer/preference_polling_interval_default"
android:title="@string/settings_polling_interval_header" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/settings_category_general" >
<Preference
@@ -7,6 +7,7 @@ import java.util.Set;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.provider.Settings.Secure;
@@ -33,6 +34,10 @@ public class AppPreferences {
public static AppPreferences on(Context context, String preferenceName) {
return new AppPreferences(context, preferenceName);
}
public interface PollingActiveChangedListener {
void onPollingActiveChanged(boolean isActive);
}
private final static String HIDDEN_PREFERENCE_SENDING_ACTIVE = "sendingActivePref";
@@ -71,7 +76,7 @@ public class AppPreferences {
public boolean isSendingActive() {
return preferences.getBoolean(HIDDEN_PREFERENCE_SENDING_ACTIVE, false);
}
public void setSendingActive(boolean activate) {
preferences.edit().putBoolean(HIDDEN_PREFERENCE_SENDING_ACTIVE, activate).commit();
}
@@ -179,6 +184,18 @@ public class AppPreferences {
public void setMailRecipient(String mail) {
preferences.edit().putString(key(R.string.preference_mail_key), mail).commit();
}
public boolean isPollingActive() {
return preferences.getBoolean(key(R.string.preference_polling_active_key), false);
}
/**
* Gets polling interval in minutes
*/
public int getPollingInterval() {
return preferences.getInt(key(R.string.preference_polling_interval_key), 0);
}
public RacingProcedureType getDefaultRacingProcedureType() {
String defaultStartProcedureType = preferences.getString(key(R.string.preference_racing_procedure_override_key), "");
@@ -295,4 +312,31 @@ public class AppPreferences {
throw new IllegalArgumentException("Unknown racing procedure type.");
}
}
private Set<PollingActiveChangedListener> pollingActiveChangedListeners = new HashSet<AppPreferences.PollingActiveChangedListener>();
private OnSharedPreferenceChangeListener pollingActiveChangedListener = new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key(R.string.preference_polling_active_key).equals(key)) {
for (PollingActiveChangedListener listener : pollingActiveChangedListeners) {
listener.onPollingActiveChanged(isPollingActive());
}
}
}
};
public void registerPollingActiveChangedListener(final PollingActiveChangedListener listener) {
if (pollingActiveChangedListeners.isEmpty()) {
preferences.registerOnSharedPreferenceChangeListener(pollingActiveChangedListener);
}
pollingActiveChangedListeners.add(listener);
}
public void unregisterPollingActiveChangedListener(PollingActiveChangedListener listener) {
pollingActiveChangedListeners.remove(listener);
if (pollingActiveChangedListeners.isEmpty()) {
preferences.unregisterOnSharedPreferenceChangeListener(pollingActiveChangedListener);
}
}
}
@@ -31,7 +31,7 @@ public class RaceApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ExLog.i(TAG, "Application is starting");
ExLog.i(TAG, "Application is starting.");
Thread.setDefaultUncaughtExceptionHandler(new LoggingExceptionHandler(Thread
.getDefaultUncaughtExceptionHandler()));
@@ -232,9 +232,12 @@ public class OnlineDataManager extends DataManager {
DataHandler<DeviceConfiguration> handler = new NullDataHandler<DeviceConfiguration>();
DataParser<DeviceConfiguration> parser = new DeviceConfigurationParser(DeviceConfigurationJsonDeserializer.create());
String encodedIdentifier = URLEncoder.encode(identifier.getClientIdentifier());
encodedIdentifier = encodedIdentifier.replace("+", "%20");
return new OnlineDataLoader<DeviceConfiguration>(
context,
new URL(preferences.getServerBaseURL() + "/sailingserver/rc/configuration?client="+ identifier.getClientIdentifier()),
new URL(preferences.getServerBaseURL() + "/sailingserver/rc/configuration?client="+ encodedIdentifier),
parser, handler);
}
});
@@ -13,6 +13,10 @@ public class HttpJsonPostRequest extends HttpRequest {
private String requestBody;
public HttpJsonPostRequest(URL requestUrl) {
this(requestUrl, null);
}
public HttpJsonPostRequest(URL requestUrl, String body) {
super(requestUrl);
this.requestBody = body;
@@ -34,6 +38,8 @@ public class HttpJsonPostRequest extends HttpRequest {
}
private void sendBody(OutputStream outputStream) throws IOException {
outputStream.write(requestBody.getBytes(Charset.forName("UTF-8")));
if (requestBody != null) {
outputStream.write(requestBody.getBytes(Charset.forName("UTF-8")));
}
}
}
@@ -62,7 +62,7 @@ public abstract class HttpRequest {
* Returns a copied {@link InputStream} of the server's response.
* You must close this stream when done.
*/
public InputStream execute() throws Exception {
public InputStream execute() throws IOException {
ExLog.i(TAG, String.format("(Request %d) Executing HTTP request on %s.", this.hashCode(), url));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
@@ -94,6 +94,9 @@ public abstract class HttpRequest {
connection.disconnect();
return copiedResponseInputStream;
} catch (IOException e) {
ExLog.i(TAG, String.format("(Request %d) HTTP request failed.", this.hashCode()));
throw e;
} finally {
if (responseInputStream != null) {
responseInputStream.close();
@@ -55,7 +55,7 @@ public class PreferencesDeviceConfigurationLoader implements ConfigurationLoader
if (regattaConfigurationLoader != null) {
regattaConfigurationLoader.store();
logApply("regatta configuration", configuration.getRegattaConfiguration());
logApply("regatta configuration", "[object]");
}
if (configuration.getAllowedCourseAreaNames() != null) {
@@ -2,6 +2,7 @@ package com.sap.sailing.racecommittee.app.domain.racelog.impl;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@@ -9,35 +10,60 @@ import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEvent;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.services.sending.EventSendingService;
import com.sap.sailing.racecommittee.app.services.sending.EventSendingService.EventSendingBinder;
import com.sap.sailing.racecommittee.app.services.sending.ServerReplyCallback;
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogEventDeserializer;
/**
* <p>
* Processes (and closes) the {@link InputStream} when posting a {@link RaceLogEvent} to the server.
* </p>
* <p>
* If the server sends back some {@link RaceLogEvent}s the {@link RaceLogEventsCallback} will try to reach the
* {@link EventSendingService} and tell him about the server-side {@link RaceLogEvent}s that will be added to
* the {@link RaceLog}. This gives the {@link EventSendingService} the chance to ignore them the next time they
* come around. The execution of the {@link RaceLogEventsCallback} will be deferred until the service is bound.
* </p>
* <p>
* If the {@link EventSendingService} cannot be reached (this is a really bad sign) the events are added to the
* {@link RaceLogEvent} immediately.
* </p>
*/
public class RaceLogEventsCallback implements ServerReplyCallback {
private static final String TAG = RaceLogEventsCallback.class.getName();
@Override
public void onReply(Intent originalIntent, Context context, InputStream inputStream) {
public void processResponse(Context context, InputStream responseStream, Serializable raceId) {
ReadonlyDataManager dataManager = DataManager.create(context);
final List<RaceLogEvent> eventsToAdd = new ArrayList<RaceLogEvent>();
SharedDomainFactory domainFactory = DataManager.create(context).getDataStore().getDomainFactory();
List<RaceLogEvent> eventsToAdd = parseResponse(dataManager, responseStream);
addEvents(context, raceId, dataManager, eventsToAdd);
}
protected List<RaceLogEvent> parseResponse(ReadonlyDataManager dataManager, InputStream responseStream) {
List<RaceLogEvent> eventsToAdd = new ArrayList<RaceLogEvent>();
JSONParser parser = new JSONParser();
try {
JSONArray eventsToAddAsJson = (JSONArray) parser.parse(new InputStreamReader(inputStream));
JSONArray eventsToAddAsJson = (JSONArray) parser.parse(new InputStreamReader(responseStream));
SharedDomainFactory domainFactory = dataManager.getDataStore().getDomainFactory();
RaceLogEventDeserializer deserializer = RaceLogEventDeserializer.create(domainFactory);
for (Object o : eventsToAddAsJson) {
try {
RaceLogEvent eventToAdd = RaceLogEventDeserializer.create(domainFactory).deserialize((JSONObject) o);
RaceLogEvent eventToAdd = deserializer.deserialize((JSONObject) o);
eventsToAdd.add(eventToAdd);
} catch (JsonDeserializationException e) {
ExLog.e(TAG, "Error deserializing Race Log event:\n" + o);
@@ -45,24 +71,79 @@ public class RaceLogEventsCallback implements ServerReplyCallback {
}
} catch (Exception e) {
ExLog.e(TAG, "Error parsing server response");
//ExLog.ex(TAG, e);
}
return eventsToAdd;
}
private void addEvents(Context context, Serializable raceId, ReadonlyDataManager dataManager,
List<RaceLogEvent> eventsToAdd) {
if (eventsToAdd.isEmpty()) {
ExLog.i(TAG, "No server-side events to add for race " + raceId);
return;
}
String raceId = originalIntent.getStringExtra(AppConstants.RACE_ID_KEY);
if (dataManager.getDataStore().hasRace(raceId)) {
RaceLog raceLog = dataManager.getDataStore().getRace(raceId).getRaceLog();
if (raceLog != null) {
ExLog.i(TAG, "Successfully retrieved race log for race ID " + raceId);
for (RaceLogEvent eventToAddToRaceLog : eventsToAdd) {
raceLog.add(eventToAddToRaceLog);
ExLog.i(TAG, "added event " + eventToAddToRaceLog.toString() + " to client's race log");
}
} else {
ExLog.w(TAG, "Couldn't retrieve race log for race ID " + raceId);
}
ExLog.i(TAG, String.format("Server sent %d events to be added for race %s.", eventsToAdd.size(), raceId));
if (!dataManager.getDataStore().hasRace(raceId)) {
ExLog.w(TAG, "I have no race " + raceId);
return;
}
RaceLog raceLog = dataManager.getDataStore().getRace(raceId).getRaceLog();
if (raceLog == null) {
ExLog.w(TAG, "Unable to retrieve race log for race " + raceId);
return;
}
EventSendingConnection connection = new EventSendingConnection(context, eventsToAdd, raceLog);
if (context.bindService(new Intent(context, EventSendingService.class), connection,
Context.BIND_AUTO_CREATE)) {
// execution deferred until service is bound
ExLog.i(TAG, "Waiting for sending service to be bound.");
} else {
ExLog.w(TAG, "There is no race with id " + raceId);
ExLog.e(TAG,"Unable to bind to sending service. Processing server response without suppressing received events...");
addEvents(eventsToAdd, raceLog, null);
}
}
protected void addEvents(List<RaceLogEvent> eventsToAdd, RaceLog raceLog, EventSendingService sendingService) {
for (RaceLogEvent eventToAddToRaceLog : eventsToAdd) {
if (sendingService != null) {
sendingService.registerEventForSuppression(eventToAddToRaceLog.getId());
}
raceLog.add(eventToAddToRaceLog);
ExLog.i(TAG, "Added event " + eventToAddToRaceLog.toString() + " to client's race log");
}
}
/**
* Connects to the {@link EventSendingService} and continues with execution. The service will be released afterwards.
*/
private class EventSendingConnection implements ServiceConnection {
private final Context context;
private final List<RaceLogEvent> eventsToAdd;
private final RaceLog raceLog;
private EventSendingService sendingService;
public EventSendingConnection(Context context, List<RaceLogEvent> eventsToAdd, RaceLog raceLog) {
this.context = context;
this.eventsToAdd = eventsToAdd;
this.raceLog = raceLog;
}
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
EventSendingBinder binder = (EventSendingBinder) service;
sendingService = binder.getService();
ExLog.i(TAG, "Sending service is bound. Continue to process server response...");
addEvents(eventsToAdd, raceLog, sendingService);
context.unbindService(this);
}
@Override
public void onServiceDisconnected(ComponentName arg) {
}
}
}
@@ -33,6 +33,7 @@ import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.services.polling.RaceLogPoller;
import com.sap.sailing.racecommittee.app.services.sending.RaceEventSender;
import com.sap.sailing.racecommittee.app.ui.activities.LoginActivity;
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
@@ -65,6 +66,8 @@ public class RaceStateService extends Service {
private ReadonlyDataManager dataManager;
private RaceLogPoller poller;
private Map<ManagedRace, RaceLogEventVisitor> registeredLogListeners;
private Map<ManagedRace, RaceStateEventScheduler> registeredStateEventSchedulers;
@@ -79,6 +82,8 @@ public class RaceStateService extends Service {
this.alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
this.dataManager = DataManager.create(this);
this.poller = new RaceLogPoller(this);
this.registeredLogListeners = new HashMap<ManagedRace, RaceLogEventVisitor>();
this.registeredStateEventSchedulers = new HashMap<ManagedRace, RaceStateEventScheduler>();
this.managedIntents = new HashMap<Serializable, List<Pair<PendingIntent, RaceStateEvents>>>();
@@ -132,6 +137,8 @@ public class RaceStateService extends Service {
}
private void unregisterAllRaces() {
poller.unregisterAllAndStop();
for (Entry<ManagedRace, RaceLogEventVisitor> entry : registeredLogListeners.entrySet()) {
entry.getKey().getState().getRaceLog().removeListener(entry.getValue());
}
@@ -235,9 +242,12 @@ public class RaceStateService extends Service {
RaceLogChangedVisitor logListener = new RaceLogChangedVisitor(sender);
state.getRaceLog().addListener(logListener);
// ... register on state changes!
// ... register on state changes...
RaceStateEventScheduler stateEventScheduler = new RaceStateEventSchedulerOnService(this, race);
state.setStateEventScheduler(stateEventScheduler);
// ... and register for polling!
poller.register(race);
this.registeredLogListeners.put(race, logListener);
this.registeredStateEventSchedulers.put(race, stateEventScheduler);
@@ -0,0 +1,16 @@
package com.sap.sailing.racecommittee.app.services.polling;
import java.io.InputStream;
import java.io.Serializable;
import com.sap.sailing.domain.common.impl.Util.Pair;
public class PollingResult {
public final boolean isSuccess;
public final Pair<Serializable, InputStream> resultStreamForRaceId;
public PollingResult(boolean isSuccess, Pair<Serializable, InputStream> resultStreamForRaceId) {
this.isSuccess = isSuccess;
this.resultStreamForRaceId = resultStreamForRaceId;
}
}
@@ -0,0 +1,168 @@
package com.sap.sailing.racecommittee.app.services.polling;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.AppPreferences.PollingActiveChangedListener;
import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.racelog.impl.RaceLogEventsCallback;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.services.polling.RaceLogPollerTask.PollingResultListener;
import com.sap.sailing.racecommittee.app.services.sending.EventSendingService;
/**
* <p>
* Polls for server-side race log changes
* </p>
*
* <p>
* There is no multi-threading involved, everything will be done on the UI thread.
* </p>
*/
public class RaceLogPoller implements PollingActiveChangedListener {
protected static final String TAG = RaceLogPoller.class.getName();
private final Context context;
private final Handler pollingHandler;
private final PollingWorker pollingWorker;
private final Map<ManagedRace, URL> races;
private final AppPreferences appPreferences;
private boolean hasRacesToPoll;
public RaceLogPoller(Context context) {
this.context = context;
// We want to use the main (UI) loop
this.pollingHandler = new Handler(Looper.getMainLooper());
this.pollingWorker = new PollingWorker(this);
this.races = new HashMap<ManagedRace, URL>();
this.appPreferences = AppPreferences.on(context);
this.appPreferences.registerPollingActiveChangedListener(this);
this.hasRacesToPoll = false;
}
public void register(ManagedRace race) {
try {
races.put(race, createURL(race));
// remove pending pollingWorker, to ensure that we only have one at once
pollingHandler.removeCallbacks(pollingWorker);
long pollingInterval = getPollingIntervalInMs();
pollingHandler.postDelayed(pollingWorker, pollingInterval);
this.hasRacesToPoll = true;
ExLog.i(TAG, String.format("Registered race %s for polling, will start in %d milliseconds.", race.getId(),
pollingInterval));
} catch (MalformedURLException e) {
ExLog.e(TAG, String.format("Unable to create polling URL for race %s: %s", race.getId(), e.getMessage()));
}
}
private URL createURL(ManagedRace race) throws MalformedURLException {
return new URL(EventSendingService.getRaceLogEventSendAndReceiveUrl(context, race.getRaceGroup().getName(),
race.getName(), race.getFleet().getName()));
}
public void unregisterAllAndStop() {
hasRacesToPoll = false;
pollingHandler.removeCallbacksAndMessages(null);
races.clear();
appPreferences.unregisterPollingActiveChangedListener(this);
ExLog.i(TAG, "Polling will be stopped.");
}
protected boolean isPollingActive() {
return hasRacesToPoll && appPreferences.isPollingActive();
}
protected long getPollingIntervalInMs() {
return appPreferences.getPollingInterval() * 60 * 1000;
}
@Override
public void onPollingActiveChanged(boolean isActive) {
if (isActive) {
long pollingInterval = getPollingIntervalInMs();
pollingHandler.postDelayed(pollingWorker, pollingInterval);
ExLog.i(TAG, String.format("Polling has been activated, will start in %d milliseconds.", pollingInterval));
} else {
ExLog.i(TAG, "Polling has been deactivated, next polling attempt will be aborted.");
}
};
/**
* Will be run on the main (UI) thread!
*/
private static class PollingWorker implements Runnable, PollingResultListener {
private final RaceLogPoller poller;
private final RaceLogEventsCallback processor;
private RaceLogPollerTask task;
public PollingWorker(RaceLogPoller poller) {
this.poller = poller;
this.processor = new RaceLogEventsCallback();
}
@SuppressWarnings("unchecked")
@Override
public void run() {
ExLog.i(TAG, "Polling for server-side race log changes...");
if (!poller.isPollingActive()) {
ExLog.i(TAG, "Polling aborted.");
return;
}
List<Pair<Serializable, URL>> queries = getPollingQueries();
task = new RaceLogPollerTask(this);
task.execute(queries.toArray(new Pair[0]));
}
@Override
public void onPollingResult(PollingResult result) {
if (!poller.isPollingActive()) {
task.cancel(true);
ExLog.i(TAG, "Polling aborted.");
return;
}
if (result.isSuccess) {
Serializable raceId = result.resultStreamForRaceId.getA();
InputStream responseStream = result.resultStreamForRaceId.getB();
processor.processResponse(poller.context, responseStream, raceId);
} else {
ExLog.i(TAG, "Polling attempt not successful.");
}
}
@Override
public void onPollingFinished() {
if (!poller.isPollingActive()) {
ExLog.i(TAG, "Polling aborted.");
return;
}
long pollingInterval = poller.getPollingIntervalInMs();
ExLog.i(TAG, String.format("Polling done. Will poll again in %d milliseconds.", pollingInterval));
poller.pollingHandler.postDelayed(this, pollingInterval);
}
private List<Pair<Serializable, URL>> getPollingQueries() {
List<Pair<Serializable, URL>> queries = new ArrayList<Pair<Serializable,URL>>();
for (Entry<ManagedRace, URL> entry : poller.races.entrySet()) {
queries.add(new Pair<Serializable, URL>(entry.getKey().getId(), entry.getValue()));
}
return queries;
}
}
}
@@ -0,0 +1,62 @@
package com.sap.sailing.racecommittee.app.services.polling;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import android.os.AsyncTask;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.racecommittee.app.data.http.HttpJsonPostRequest;
import com.sap.sailing.racecommittee.app.data.http.HttpRequest;
public class RaceLogPollerTask extends AsyncTask<Pair<Serializable, URL>, PollingResult, Void> {
public interface PollingResultListener {
public void onPollingResult(PollingResult result);
public void onPollingFinished();
}
private final PollingResultListener listener;
public RaceLogPollerTask(PollingResultListener listener) {
this.listener = listener;
}
@Override
protected Void doInBackground(Pair<Serializable, URL>... queries) {
for (Pair<Serializable, URL> query : queries) {
if (isCancelled()) {
return null;
}
HttpRequest request = new HttpJsonPostRequest(query.getB());
InputStream responseStream = null;
try {
responseStream = request.execute();
publishProgress(new PollingResult(true,
new Pair<Serializable, InputStream>(query.getA(), responseStream)));
} catch (IOException e) {
if (responseStream != null) {
try {
responseStream.close();
} catch (IOException ie) {
}
}
publishProgress(new PollingResult(false, null));
}
}
return null;
}
@Override
protected void onProgressUpdate(PollingResult... values) {
listener.onPollingResult(values[0]);
}
@Override
protected void onPostExecute(Void result) {
listener.onPollingFinished();
}
}
@@ -125,9 +125,9 @@ public class EventPersistenceManager {
String[] lineParts = persistedEvent.split(";");
String url = lineParts[2];
String raceId = lineParts[0];
String serializedEventAsUrlEncodedJson = lineParts[1];
String serializedEventJson = URLDecoder.decode(lineParts[1]);
String callbackClassString = lineParts[3];
addEventToLog(raceId, serializedEventAsUrlEncodedJson);
addEventToLog(raceId, serializedEventJson);
Class<? extends RaceLogEventsCallback> callbackClass = null;
if (! "null".equals(callbackClassString)) {
@@ -141,8 +141,10 @@ public class EventPersistenceManager {
}
}
// We are passing no event id, because we know it used to suppress event sending and
// we want this event to be sent.
Intent eventIntent = EventSendingService.createEventIntent(context, url, raceId,
URLDecoder.decode(serializedEventAsUrlEncodedJson), callbackClass);
null, serializedEventJson, callbackClass);
if (eventIntent != null) {
delayedIntents.add(eventIntent);
}
@@ -168,9 +170,9 @@ public class EventPersistenceManager {
ExLog.i(TAG, "Event didn't need to be readded. Same event already in the log");
}
} catch (JsonDeserializationException e) {
ExLog.w(TAG, String.format("Error readding event to race log: %s", e.toString()));
ExLog.w(TAG, String.format("Error while readding event to race log: %s", e.toString()));
} catch (ParseException e) {
ExLog.w(TAG, String.format("Error readding event to race log: %s", e.toString()));
ExLog.w(TAG, String.format("Error while readding event to race log: %s", e.toString()));
}
}
@@ -1,5 +1,6 @@
package com.sap.sailing.racecommittee.app.services.sending;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -18,7 +19,7 @@ public class EventSenderTask extends AsyncTask<Intent, Void, Triple<Intent, Bool
private static String TAG = EventSenderTask.class.getName();
public interface EventSendingListener {
public void onResult(Intent intent, boolean success, InputStream inputStream);
public void onEventSent(Intent intent, boolean success, InputStream inputStream);
}
private EventSendingListener listener;
@@ -27,6 +28,7 @@ public class EventSenderTask extends AsyncTask<Intent, Void, Triple<Intent, Bool
this.listener = listener;
}
@SuppressWarnings("unused")
@Override
protected Triple<Intent, Boolean, InputStream> doInBackground(Intent... params) {
Triple<Intent, Boolean, InputStream> result;
@@ -40,13 +42,19 @@ public class EventSenderTask extends AsyncTask<Intent, Void, Triple<Intent, Bool
if (serializedEventAsJson == null || url == null) {
return new Triple<Intent, Boolean, InputStream>(intent, false, null);
}
InputStream responseStream = null;
try {
ExLog.i(TAG, "Posting event: " + serializedEventAsJson);
HttpRequest post = new HttpJsonPostRequest(new URL(url), serializedEventAsJson);
final InputStream inputStream = post.execute();
responseStream = post.execute();
ExLog.i(TAG, "Post successful for the following event: " + serializedEventAsJson);
result = new Triple<Intent, Boolean, InputStream>(intent, true, inputStream);
} catch (Exception e) {
result = new Triple<Intent, Boolean, InputStream>(intent, true, responseStream);
} catch (IOException e) {
if (responseStream != null) {
try {
responseStream.close();
} catch (IOException ie) { }
}
ExLog.e(TAG, String.format("Post not successful, exception occured: %s", e.toString()));
result = new Triple<Intent, Boolean, InputStream>(intent, false, null);
}
@@ -56,7 +64,7 @@ public class EventSenderTask extends AsyncTask<Intent, Void, Triple<Intent, Bool
@Override
protected void onPostExecute(Triple<Intent, Boolean, InputStream> resultTriple) {
super.onPostExecute(resultTriple);
listener.onResult(resultTriple.getA(), resultTriple.getB(), resultTriple.getC());
listener.onEventSent(resultTriple.getA(), resultTriple.getB(), resultTriple.getC());
}
}
@@ -1,12 +1,13 @@
package com.sap.sailing.racecommittee.app.services.sending;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import android.app.Service;
@@ -50,6 +51,12 @@ public class EventSendingService extends Service implements EventSendingListener
private final IBinder mBinder = new EventSendingBinder();
private EventPersistenceManager persistenceManager;
private boolean isHandlerSet;
private Set<Serializable> suppressedEventIds = new HashSet<Serializable>();
public void registerEventForSuppression(Serializable eventId) {
suppressedEventIds.add(eventId);
}
private EventSendingServiceLogger serviceLogger = new EventSendingServiceLogger() {
@Override
@@ -102,6 +109,18 @@ public class EventSendingService extends Service implements EventSendingListener
serviceLogger.onEventSentSuccessful();
}
public static String getRaceLogEventSendAndReceiveUrl(Context context, final String raceGroupName,
final String raceName, final String fleetName) {
String url = String.format("%s/sailingserver/rc/racelog?"+
RaceLogServletConstants.PARAMS_LEADERBOARD_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_RACE_FLEET_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_CLIENT_UUID+"=%s",
AppPreferences.on(context).getServerBaseURL(), URLEncoder.encode(raceGroupName),
URLEncoder.encode(raceName), URLEncoder.encode(fleetName), uuid);
return url;
}
/**
* Creates an intent that contains the event to be sent and the race id which shall be sent to the back end. See
* constants in <code>AddEntryToRaceLogJsonPostServlet</code> for URL construction rules.
@@ -116,28 +135,34 @@ public class EventSendingService extends Service implements EventSendingListener
* the class of the callback which should process the server reply
* @return the intent that shall be sent to the EventSendingService
*/
public static Intent createEventIntent(Context context, ManagedRace race, String serializedEventAsJson,
public static Intent createEventIntent(Context context, ManagedRace race, Serializable eventId, String serializedEventAsJson,
Class<? extends ServerReplyCallback> callbackClass) {
String url = String.format("%s/sailingserver/rc/racelog?"+
RaceLogServletConstants.PARAMS_LEADERBOARD_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_RACE_COLUMN_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_RACE_FLEET_NAME+"=%s&"+
RaceLogServletConstants.PARAMS_CLIENT_UUID+"=%s",
AppPreferences.on(context).getServerBaseURL(), URLEncoder.encode(race.getRaceGroup().getName()),
URLEncoder.encode(race.getName()), URLEncoder.encode(race.getFleet().getName()), uuid);
return createEventIntent(context, url, race.getId(), serializedEventAsJson, callbackClass);
String url = getRaceLogEventSendAndReceiveUrl(context,
race.getRaceGroup().getName(), race.getName(), race.getFleet().getName());
return createEventIntent(context, url, race.getId(), eventId, serializedEventAsJson, callbackClass);
}
public static Intent createEventIntent(Context context, String url, Serializable raceId, String serializedEventAsJson,
public static Intent createEventIntent(Context context, String url, Serializable raceId, Serializable eventId, String serializedEventAsJson,
Class<? extends ServerReplyCallback> callbackClass) {
Intent eventIntent = new Intent(AppConstants.INTENT_ACTION_SEND_EVENT);
eventIntent.putExtra(AppConstants.RACE_ID_KEY, raceId);
eventIntent.putExtra(EXTRAS_EVENT_ID, eventId);
eventIntent.putExtra(AppConstants.EXTRAS_JSON_SERIALIZED_EVENT, serializedEventAsJson);
eventIntent.putExtra(AppConstants.EXTRAS_URL, url);
eventIntent.putExtra(AppConstants.EXTRAS_CALLBACK_CLASS, callbackClass == null ? null : callbackClass.getName());
ExLog.i(TAG, "Created event " + eventIntent + " for sending to backend");
return eventIntent;
}
private static final String EXTRAS_EVENT_ID = "_EXTRAS_EVENT_ID";
private Serializable getEventId(Intent intent) {
Serializable id = intent.getSerializableExtra(EXTRAS_EVENT_ID);
if (id != null) {
return id;
}
ExLog.w(TAG, "Unable to extract event identifier from event intent.");
return null;
}
/*
* (non-Javadoc)
@@ -213,13 +238,19 @@ public class EventSendingService extends Service implements EventSendingListener
if (!AppPreferences.on(this).isSendingActive()) {
ExLog.i(TAG, "Sending deactivated. Event will not be sent to server.");
} else {
EventSenderTask task = new EventSenderTask(this);
task.execute(intent);
Serializable eventId = getEventId(intent);
if (eventId != null && suppressedEventIds.contains(eventId)) {
suppressedEventIds.remove(eventId);
ExLog.i(TAG, String.format("Event %s is suppressed, won't be sent.", eventId));
} else {
EventSenderTask task = new EventSenderTask(this);
task.execute(intent);
}
}
}
@Override
public void onResult(Intent intent, boolean success, InputStream inputStream) {
public void onEventSent(Intent intent, boolean success, InputStream inputStream) {
if (!success) {
ExLog.w(TAG, "Error while posting intent to server. Will persist intent...");
persistenceManager.persistIntent(intent);
@@ -248,11 +279,9 @@ public class EventSendingService extends Service implements EventSendingListener
}
}
if (callback != null) {
callback.onReply(intent, this, inputStream);
String raceId = intent.getStringExtra(AppConstants.RACE_ID_KEY);
callback.processResponse(this, inputStream, raceId);
}
try {
inputStream.close();
} catch (IOException e) {}
}
}
@@ -26,7 +26,7 @@ public class RaceEventSender implements RaceLogChangedListener {
public void eventAdded(RaceLogEvent event) {
JSONObject serializedEvent = serializer.serialize(event);
service.startService(
EventSendingService.createEventIntent(service, race, serializedEvent.toJSONString(),
EventSendingService.createEventIntent(service, race, event.getId(), serializedEvent.toJSONString(),
RaceLogEventsCallback.class));
}
@@ -1,6 +1,7 @@
package com.sap.sailing.racecommittee.app.services.sending;
import java.io.InputStream;
import java.io.Serializable;
import android.content.Context;
import android.content.Intent;
@@ -18,7 +19,7 @@ import com.sap.sailing.domain.racelog.RaceLogEvent;
*/
public interface ServerReplyCallback {
/**
* The inputStream does not need to be closed by the implementing class.
* The inputStream MUST be closed by the implementing class.
*/
void onReply(Intent originalIntent, Context context, InputStream inputStream);
void processResponse(Context context, InputStream inputStream, Serializable raceId);
}
@@ -150,7 +150,7 @@ public class WindActivity extends SessionActivity implements CompassDirectionLis
private void buildAlertMessageNoGps() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
builder.setMessage(R.string.wind_gps_is_disabled)
.setCancelable(false)
.setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
@@ -78,12 +78,6 @@ public class RaceInfoFragment extends RaceFragment implements RaceInfoListener {
@Override
public void onClick(View v) {
/* getRace().getRaceLog().add(
RaceLogEventFactory.INSTANCE.createStartTimeEvent(
MillisecondsTimePoint.now(),
AppPreferences.getAuthor(getActivity()),
getRace().getRaceLog().getCurrentPassId(),
MillisecondsTimePoint.now().plus(3000000)));*/
showCourseDesignDialog();
}
});
@@ -7,8 +7,10 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.racelog.state.RaceState;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.logging.ExLog;
@@ -92,13 +94,15 @@ public class AbortModeSelectionDialog extends RaceDialogFragment {
}
private void signalAbort(Flags additionalFlag) {
TimePoint now = MillisecondsTimePoint.now();
RaceState state = getRaceState();
if (this.abortFlag.equals(Flags.AP)) {
//getRace().getState().getStartProcedure().setPostponed(MillisecondsTimePoint.now(), additionalFlag);
getRace().getState().setAborted(MillisecondsTimePoint.now(), true, additionalFlag);
state.setAborted(now, true, additionalFlag);
} else if (this.abortFlag.equals(Flags.NOVEMBER)) {
//getRace().getState().getStartProcedure().setAbandoned(MillisecondsTimePoint.now(), additionalFlag);
getRace().getState().setAborted(MillisecondsTimePoint.now(), false, additionalFlag);
state.setAborted(now, false, additionalFlag);
}
state.setAdvancePass(now);
this.dismiss();
}
@@ -26,6 +26,7 @@ import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorStore;
import com.sap.sailing.domain.base.SharedDomainFactory;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
@@ -171,7 +172,14 @@ public class PositioningFragment extends RaceDialogFragment {
private void loadCompetitors() {
getActivity().setProgressBarIndeterminateVisibility(true);
// invalidate all competitors of this race
ReadonlyDataManager dataManager = OnlineDataManager.create(getActivity());
SharedDomainFactory domainFactory = dataManager.getDataStore().getDomainFactory();
for (Competitor competitor : getRace().getCompetitors()) {
domainFactory.getCompetitorStore().allowCompetitorResetToDefaults(competitor);
}
Loader<?> competitorLoaders = getLoaderManager().initLoader(0, null,
dataManager.createCompetitorsLoader(getRace(), new LoadClient<Collection<Competitor>>() {
@@ -6,9 +6,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.sap.sailing.racecommittee.app.ui.utils.MultiplePreferenceChangeListener;
import com.sap.sailing.racecommittee.app.ui.views.EditSetPreference;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.MultiSelectListPreference;
@@ -17,6 +14,9 @@ import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import com.sap.sailing.racecommittee.app.ui.utils.MultiplePreferenceChangeListener;
import com.sap.sailing.racecommittee.app.ui.views.EditSetPreference;
/**
* Created by I074137 on 18.09.13.
*/
@@ -9,6 +9,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
@@ -26,7 +27,6 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment {
private static int requestCodeQRCode = 45392;
private AppPreferences appPreferences;
private Preference identifierPreference;
private Preference serverUrlPreference;
@@ -35,21 +35,37 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference_general);
appPreferences = AppPreferences.on(getActivity());
setupConnection();
setupPolling();
setupGeneral();
}
protected void setupGeneral() {
setupLanguageButton();
setupIdentifierBox();
setupSyncQRCodeButton();
setupForceUpdateButton();
setupServerUrlBox();
setupCourseAreasList();
bindPreferenceSummaryToValue(findPreference(R.string.preference_server_url_key));
bindPreferenceSummaryToSet(findPreference(R.string.preference_course_areas_key));
bindPreferenceSummaryToValue(findPreference(R.string.preference_mail_key));
}
private void setupPolling() {
Preference intervalPreference = findPreference(R.string.preference_polling_interval_key);
CheckBoxPreference activePreference = findPreference(R.string.preference_polling_active_key);
bindPreferenceToCheckbox(activePreference, intervalPreference);
bindPreferenceSummaryToInteger(intervalPreference);
}
protected void setupConnection() {
setupIdentifierBox();
setupServerUrlBox();
setupSyncQRCodeButton();
setupForceUpdateButton();
bindPreferenceSummaryToValue(findPreference(R.string.preference_server_url_key));
}
private void setupIdentifierBox() {
final AppPreferences appPreferences = AppPreferences.on(getActivity());
identifierPreference = findPreference(R.string.preference_identifier_key);
identifierPreference.setSummary(appPreferences.getDeviceIdentifier());
addOnPreferenceChangeListener(identifierPreference, new OnPreferenceChangeListener() {
@@ -102,8 +118,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment {
private void setupCourseAreasList() {
EditSetPreference preference = findPreference(R.string.preference_course_areas_key);
//ReadonlyDataManager dataManager = DataManager.create(getActivity());
// TODO: example values from DataStore
preference.setExampleValues(getResources().getStringArray(R.array.preference_course_areas_example));
}
@@ -11,12 +11,18 @@ import android.preference.MultiSelectListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import com.sap.sailing.domain.base.configuration.RegattaConfiguration;
import com.sap.sailing.domain.common.CourseDesignerMode;
import com.sap.sailing.domain.common.racelog.Flags;
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.activities.SettingsActivity;
/**
* <p>This preference fragment can be redirected to display the {@link RegattaConfiguration} of a specifc regatta.</p>
*
* <p>See {@link SettingsActivity}.
*/
public class RegattaPreferenceFragment extends BasePreferenceFragment {
private boolean isRedirected = false;
@@ -5,15 +5,14 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import android.content.Context;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen;
import com.sap.sailing.domain.base.racegroup.RaceGroup;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.data.DataManager;
import com.sap.sailing.racecommittee.app.data.ReadonlyDataManager;
import com.sap.sailing.racecommittee.app.ui.activities.SettingsActivity;
@@ -31,7 +30,7 @@ public class RegattaSpecificPreferenceFragment extends BasePreferenceFragment {
Set<RaceGroup> raceGroups = getRaceGroups(context);
if (raceGroups.isEmpty()) {
Preference preference = new Preference(context);
preference.setTitle("There are no regattas loaded.");
preference.setTitle(R.string.preference_there_are_no_regattas);
screen.addPreference(preference);
} else {
List<RaceGroup> sortedGroups = new ArrayList<RaceGroup>(raceGroups);
@@ -52,7 +51,7 @@ public class RegattaSpecificPreferenceFragment extends BasePreferenceFragment {
private void addPreference(PreferenceScreen screen, final RaceGroup raceGroup) {
Preference preference = new Preference(screen.getContext());
preference.setTitle(String.format("Configure regatta %s", raceGroup.getName()));
preference.setTitle(getString(R.string.configure_regatta, raceGroup.getName()));
preference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
@@ -136,7 +136,7 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
flagName.append("|");
flagName.append(changePole.getLowerFlag().toString());
}
targetView.setText(getString(formatTextResourceId, TimeUtils.formatDuration(millisecondsTillChange), flagName));
targetView.setText(getString(formatTextResourceId, TimeUtils.formatDurationUntil(millisecondsTillChange), flagName));
}
private class ProcedureChangedListener extends BaseRacingProcedureChangedListener {
@@ -132,7 +132,7 @@ public class SetStartTimeRaceFragment extends RaceFragment {
if (startDate.get(Calendar.YEAR) == today.get(Calendar.YEAR)
&& startDate.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR)) {
btSetDate.setText("Today");
btSetDate.setText(R.string.today);
} else {
String dateString = DateFormat.getDateFormat(getActivity()).format(startDate.getTime());
btSetDate.setText(dateString);
@@ -71,7 +71,7 @@ public abstract class BaseFinishingRaceFragment<ProcedureType extends RacingProc
startCountUpTextView.setText(String.format(
getString(R.string.race_running_since_template),
getRace().getName(), TimeUtils.formatDuration(millisecondsSinceStart)));
getRace().getName(), TimeUtils.formatDurationSince(millisecondsSinceStart)));
}
String info = updateAdditionalInfoText();
@@ -80,7 +80,10 @@ public abstract class BaseRunningRaceFragment<ProcedureType extends RacingProced
generalRecallButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getRaceState().setGeneralRecall(MillisecondsTimePoint.now());
TimePoint now = MillisecondsTimePoint.now();
getRaceState().setGeneralRecall(now);
// TODO see bug 1649: Explicit passing of pass identifier in RaceState interface
getRaceState().setAdvancePass(now);
}
});
@@ -114,7 +117,7 @@ public abstract class BaseRunningRaceFragment<ProcedureType extends RacingProced
startCountUpTextView.setText(String.format(
getString(R.string.race_running_since_template),
getRace().getName(), TimeUtils.formatDuration(millisecondsSinceStart)));
getRace().getName(), TimeUtils.formatDurationSince(millisecondsSinceStart)));
if (!updateFlagChangesCountdown(nextCountdownTextView)) {
nextCountdownTextView.setText("");
@@ -2,11 +2,11 @@ package com.sap.sailing.racecommittee.app.ui.fragments.raceinfo.running;
import android.view.View;
import android.widget.Toast;
import com.sap.sailing.domain.racelog.state.racingprocedure.impl.BaseRacingProcedureChangedListener;
import com.sap.sailing.domain.racelog.state.racingprocedure.rrs26.RRS26ChangedListener;
import com.sap.sailing.domain.racelog.state.racingprocedure.rrs26.RRS26RacingProcedure;
import com.sap.sailing.domain.racelog.state.racingprocedure.rrs26.ReadonlyRRS26RacingProcedure;
import com.sap.sailing.racecommittee.app.R;
public class RRS26RunningRaceFragment extends BaseRunningRaceFragment<RRS26RacingProcedure> {
@@ -33,8 +33,7 @@ public class RRS26RunningRaceFragment extends BaseRunningRaceFragment<RRS26Racin
@Override
public void onStartmodeChanged(ReadonlyRRS26RacingProcedure racingProcedure) {
// that's a little bit late, isn't it?
Toast.makeText(getActivity(),
String.format("Start mode flag changed to %s", racingProcedure.getStartModeFlag()),
Toast.makeText(getActivity(), getString(R.string.rrs26_start_mode_changed_to, racingProcedure.getStartModeFlag()),
Toast.LENGTH_SHORT).show();
int viewMode = racingProcedure.hasIndividualRecall() ? View.VISIBLE : View.GONE;
@@ -84,7 +84,7 @@ public abstract class BaseStartphaseRaceFragment<ProcedureType extends RacingPro
startCountdownTextView.setText(String.format(
getString(R.string.race_startphase_countdown_start),
TimeUtils.formatDuration(millisecondsTillStart), getRace().getName()));
TimeUtils.formatDurationUntil(millisecondsTillStart), getRace().getName()));
updateFlagChangesCountdown(nextCountdownTextView);
}
@@ -68,7 +68,7 @@ public class FlagPoleStateRenderer {
Toast.makeText(v.getContext(), upperFlag.toString() + "|" + lowerFlag.toString(), Toast.LENGTH_SHORT).show();
}
});
if (upperFlag == Flags.CLASS) {
if (upperFlag == Flags.CLASS && race.getFleet().getColor() != null) {
flagView.setPadding(6, 6, 6, 6);
flagView.setBackgroundColor(getFleetColorId());
}
@@ -22,7 +22,7 @@ public class PreferenceHelper {
* Whenever you change a preference's type (e.g. from Integer to String) you need to bump this version code to the
* appropriate app version (see AndroidManifest.xml).
*/
private final static int LAST_COMPATIBLE_VERSION = 3;
private final static int LAST_COMPATIBLE_VERSION = 4;
/**
* Application stores preference version code in this preference file (and key).
@@ -29,8 +29,17 @@ public class TimeUtils {
return DateFormat.format(format, timePoint.asDate()).toString();
}
public static String formatDuration(long milliseconds) {
public static String formatDurationSince(long milliseconds) {
int secondsTillStart = (int) Math.floor(milliseconds / 1000f);
return formatDuration(secondsTillStart);
}
public static String formatDurationUntil(long milliseconds) {
int secondsTillStart = (int) Math.ceil(milliseconds / 1000f);
return formatDuration(secondsTillStart);
}
private static String formatDuration(int secondsTillStart) {
int hours = secondsTillStart / 3600;
int minutes = (secondsTillStart % 3600) / 60;
int seconds = (secondsTillStart % 60);
@@ -4,7 +4,6 @@ import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -12,9 +11,9 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.AppPreferences;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.logging.ExLog;
import com.sap.sailing.racecommittee.app.ui.activities.SettingsActivity;
import com.sap.sailing.racecommittee.app.ui.fragments.preference.GeneralPreferenceFragment;
@@ -83,10 +82,10 @@ public class AutoUpdater {
}
};
builder.setTitle("Auto-Update completed")
builder.setTitle(R.string.auto_update_completed)
.setMessage(
"The automatic update has been completed. You should now re-synchronize your connection settings with the server.")
.setPositiveButton("Take me there", okListener)
R.string.auto_update_completed_text)
.setPositiveButton(R.string.auto_update_completed_take_me_there, okListener)
.setNegativeButton(android.R.string.cancel, cancelListener).create().show();
}
@@ -42,7 +42,7 @@ public class AutoUpdaterChecker {
this.state = new AutoUpdaterStateImpl(forceUpdate);
this.dialog = new ProgressDialog(context);
dialog.setTitle("Auto-Update");
dialog.setTitle(context.getString(R.string.auto_update));
dialog.setCancelable(true);
dialog.setButton(context.getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
@Override
@@ -70,12 +70,12 @@ public class AutoUpdaterChecker {
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setIndeterminate(true);
dialog.setMessage("Checking for version information on server...");
dialog.setMessage(context.getString(R.string.auto_update_checking_version));
dialog.show();
try {
URL versionUrl = composeVersionUrl();
ExLog.i(TAG, String.format("Trying to download auto-update info from %s", versionUrl.toString()));
ExLog.i(TAG, context.getString(R.string.auto_update_downloading_version, versionUrl.toString()));
final AutoUpdaterVersionDownloader downloader = new AutoUpdaterVersionDownloader(this);
downloader.execute(versionUrl);
@@ -87,7 +87,7 @@ public class AutoUpdaterChecker {
});
} catch (MalformedURLException e) {
onError();
Toast.makeText(context, "The version file link was not valid.", Toast.LENGTH_LONG).show();
Toast.makeText(context, R.string.auto_update_version_file_url_invalid, Toast.LENGTH_LONG).show();
}
}
@@ -118,11 +118,11 @@ public class AutoUpdaterChecker {
}
};
String messageFormat = needsUpdate ? "Click 'Install' to perform the update to version %d." : "You already have installed the version offered by the server (version %d).";
String messageFormat = needsUpdate ? context.getString(R.string.auto_update_click_install) : context.getString(R.string.auto_update_force_install);
AlertDialog.Builder updateDialog = new AlertDialog.Builder(context);
updateDialog
.setTitle("Auto-Update")
.setTitle(R.string.auto_update)
.setMessage(String.format(messageFormat, serverVersion))
.setPositiveButton(context.getString(needsUpdate ? R.string.auto_update_install : android.R.string.ok), needsUpdate ? updateListener : dismissListener)
.setNegativeButton(context.getString(needsUpdate ? android.R.string.cancel : R.string.auto_update_install_anyway), needsUpdate ? dismissListener : updateListener)
@@ -131,12 +131,12 @@ public class AutoUpdaterChecker {
updateDialog.show();
} else {
dialog.dismiss();
Toast.makeText(context, "You are already up to date!", Toast.LENGTH_LONG).show();
Toast.makeText(context, R.string.auto_update_already_up_to_date, Toast.LENGTH_LONG).show();
}
}
private void downloadUpdate(String apkFileName) {
dialog.setMessage("Downloading APK from server...");
dialog.setMessage(context.getString(R.string.auto_update_downloading_apk));
try {
File target = updater.createApkTargetFile();
@@ -154,10 +154,10 @@ public class AutoUpdaterChecker {
});
} catch (MalformedURLException e) {
onError();
Toast.makeText(context, "The download link was not valid.", Toast.LENGTH_LONG).show();
Toast.makeText(context, R.string.auto_update_apk_link_invalid, Toast.LENGTH_LONG).show();
} catch (IOException e) {
onError();
Toast.makeText(context, "The download file couldn't be created.", Toast.LENGTH_LONG).show();
Toast.makeText(context, R.string.auto_update_apk_file_error, Toast.LENGTH_LONG).show();
}
}
@@ -180,8 +180,8 @@ public class AutoUpdaterChecker {
dialog.dismiss();
AlertDialog.Builder errorDialog = new AlertDialog.Builder(context);
errorDialog
.setTitle("Auto-Update")
.setMessage("Error while trying to auto-update.")
.setTitle(R.string.auto_update)
.setMessage(R.string.auto_update_error)
.setIcon(context.getResources().getDrawable(android.R.drawable.ic_dialog_alert))
.setPositiveButton(context.getString(android.R.string.ok), new OnClickListener() {
@Override
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
<issue id="IconDuplicatesConfig" severity="ignore" />
<issue id="UnusedResources" severity="ignore" />
</lint>
+2 -2
View File
@@ -6,7 +6,7 @@
Our current server deployment uses a 64bit Java7 Hotspot virtual machine and runs on a 64bit Linux CentOS distribution. We have a single host (sapsailing.com) which runs a number of Java VMs, some to offer the application in different development stages (dev, test, prod, ...), some to perform specific tasks such as replicating UDP wind data to the various server processes, or a process to store data received from the SwissTiming connector durably while forwarding that data to a server VM requesting it.
The various processes run in "tmux" sessions to which, once connected to sapsailing.com with an ssh client, users can gain access using the `tmux -2 attach-session -t sailing` command. The tmux environment including is started automagically upon system boot by invoking the script _/home/trac/servers/tmuxManagementConsole.sh_.
The various processes run in "tmux" sessions to which, once connected to the desired EC2 instance with an ssh client and becoming the sailing user 'su - sailing', users can gain access using the `tmux attach` command. The tmux environment including is started automagically upon system boot by invoking the script _/home/trac/servers/tmuxManagementConsole.sh_.
For the OSGi containers by convention we have one directory under _/home/trac/servers/_ per deployable branch (dev, test, prod1, prod2). In those directories we have copies of the "install" script from the git's java/target folder. Running it after a successful product build on the branch corresponding to the current directory will copy the compiled product to the server directory. Running the start script will then launch the respective server instance. A safety check in the install script avoids accidentally overwriting a server directory with a non-matching product version by comparing the directory name with the branch name checked out under _/home/trac/git_.
@@ -254,4 +254,4 @@ MongoDB configuration can be found in /opt/mongodb/etc. This service is automati
### MySQL
MySQL serves as database backend for Piwik and Bugzilla. Configuration can be found in /etc/my.cnf and database files in /var/lib/mysql.
MySQL serves as database backend for Piwik and Bugzilla. Configuration can be found in /etc/my.cnf and database files in /var/lib/mysql.