mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-03 17:49:40 +00:00
Merge remote-tracking branch 'origin/master' into racelog-to-abstract-log-refactoring
Conflicts: java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/RecordFixesTest.java java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/servlet/RecordFixesFlatJsonPostServlet.java java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/servlet/RecordFixesPostServlet.java java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch java/com.sap.sailing.gwt.ui/SailingGWT.launch java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/rc/RaceGroupJsonExportServlet.java
This commit is contained in:
commit
ceb1b90866
78 files changed
+865
-1234
No files matched your search
@@ -179,6 +179,7 @@ fi
|
||||
if [[ "$@" == "clean" ]]; then
|
||||
cd $PROJECT_HOME/java
|
||||
rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*
|
||||
rm -rf com.sap.sse.security.ui/com.sap.sse.security.ui.*
|
||||
cd $PROJECT_HOME
|
||||
echo "Using following command: mvn $extra -DargLine=\"$APP_PARAMETERS\" -fae -s $MAVEN_SETTINGS $clean"
|
||||
echo "Maven version used: `mvn --version`"
|
||||
|
||||
@@ -19,6 +19,30 @@ start_tmux() {
|
||||
}
|
||||
|
||||
start_servers() {
|
||||
launch_httpd=false
|
||||
VARS=`/opt/amazon/bin/ec2-metadata -d | sed "s/user-data\: //g" | grep -v "^not available$"`
|
||||
for var in $VARS; do
|
||||
echo "$var" | grep -q "^SERVER_NAME="
|
||||
if [ "$?" != "0" ]; then
|
||||
eval "export $var"
|
||||
fi
|
||||
echo "$var" | grep -q "^SERVER_PORT="
|
||||
if [ "$?" != "0" ]; then
|
||||
eval "export $var"
|
||||
fi
|
||||
echo "$var" | grep -q "^EVENT_ID="
|
||||
if [ "$?" != "0" ]; then
|
||||
eval "export $var"
|
||||
fi
|
||||
echo "$var" | grep -iq "^REPLICATE_ON_START=True"
|
||||
if [ "$?" != "0" ]; then
|
||||
launch_httpd=true
|
||||
fi
|
||||
done
|
||||
if [ "$launch_httpd" = "true" ]; then
|
||||
launch_httpd $SERVER_NAME $SERVER_PORT $EVENT_ID
|
||||
fi
|
||||
|
||||
for conf in $JAVA_START_INSTANCES; do
|
||||
echo "Checking for amazon update..."
|
||||
su - sailing -c "cd /home/sailing/servers/$conf && $GIT_REPOSITORY/java/target/refreshInstance.sh auto-install" 2>/var/log/sailing.err >/var/log/sailing.out
|
||||
@@ -36,7 +60,21 @@ stop_servers() {
|
||||
RETVAL=$?
|
||||
[ $RETVAL -eq 0 ] && success || failure
|
||||
done
|
||||
}
|
||||
|
||||
# launch_httpd(server_name, port, event_id)
|
||||
launch_httpd() {
|
||||
echo "launch_httpd($1, $2, $2)"
|
||||
if [ -x /etc/init.d/httpd ]; then
|
||||
server_name="`echo $1 | tr [A-Z] [a-z]`"
|
||||
port="$2"
|
||||
event_id="$3"
|
||||
echo "Use Event $server_name.sapsailing.com \"$event_id\" 127.0.0.1 $port" >>/etc/httpd/conf.d/001-events.conf
|
||||
echo "Launching httpd to map ${server_name}.sapsailing.com to event with ID $event_id with server running on local port $port..."
|
||||
service httpd start
|
||||
else
|
||||
echo Can't launch httpd; start script doesn't seem to be installed at /etc/init.d/httpd
|
||||
fi
|
||||
}
|
||||
|
||||
# See how we were called.
|
||||
|
||||
+1
-3
@@ -89,12 +89,10 @@ public enum BoatClassMasterdata {
|
||||
|
||||
public static BoatClassMasterdata resolveBoatClass(String boatClassName) {
|
||||
String boatClassNameToResolve = unifyBoatClassName(boatClassName);
|
||||
|
||||
for (BoatClassMasterdata boatClass : values()) {
|
||||
if (unifyBoatClassName(boatClass.displayName).equals(boatClassNameToResolve)) {
|
||||
return boatClass;
|
||||
}
|
||||
if(boatClass.alternativeNames != null) {
|
||||
} else if (boatClass.alternativeNames != null) {
|
||||
for (String name : boatClass.alternativeNames) {
|
||||
if (unifyBoatClassName(name).equals(boatClassNameToResolve)) {
|
||||
return boatClass;
|
||||
|
||||
+2
-1
@@ -3,8 +3,9 @@ package com.sap.sailing.domain.common.dto;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.common.Color;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
|
||||
public interface CompetitorDTO extends Serializable {
|
||||
public interface CompetitorDTO extends Serializable, MappableToDevice {
|
||||
|
||||
String getTwoLetterIsoCountryCode();
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.domain.common.racelog.tracking;
|
||||
|
||||
/**
|
||||
* Marker interface that can be applied to DTOs that represent domain objects
|
||||
* that can be mapped to a device for racelog-tracking (see {@link DeviceMapping}.
|
||||
* By doing so, they can be referred without having to use {@link Serializable}
|
||||
* as type - which has a considerable performance impact for GWT.
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public interface MappableToDevice {
|
||||
|
||||
}
|
||||
+2
-2
@@ -22,7 +22,7 @@ import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoGPSFixStoreImpl;
|
||||
import com.sap.sailing.domain.racelog.tracking.GPSFixStore;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockDeviceAndSessionIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
@@ -36,7 +36,7 @@ public class AbstractGPSFixStoreTest {
|
||||
protected RacingEventService service;
|
||||
protected final MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory();
|
||||
DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer =
|
||||
new MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer();
|
||||
new MockDeviceAndSessionIdentifierWithGPSFixesDeserializer();
|
||||
protected final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||
protected RaceLog raceLog;
|
||||
protected GPSFixStore store;
|
||||
|
||||
+2
-2
@@ -70,10 +70,10 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
gpsFixStore = service.getGPSFixStore();
|
||||
service.getMongoObjectFactory().getDatabase().dropDatabase();
|
||||
author = service.getServerAuthor();
|
||||
Series series = new SeriesImpl("series", false, Collections.singletonList(fleet),
|
||||
Collections.singletonList(columnName), service);
|
||||
Series series = new SeriesImpl("series", false, Collections.singletonList(fleet), Collections.emptySet(), service);
|
||||
regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", UUID.randomUUID(), Collections.<Series>singletonList(series),
|
||||
false, new HighPoint(), UUID.randomUUID(), /* useStartTimeInference */ true);
|
||||
series.addRaceColumn(columnName, /* trackedRegattaRegistry */ null);
|
||||
leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {});
|
||||
adapter = RaceLogTrackingAdapterFactoryImpl.INSTANCE.getAdapter(DomainFactory.INSTANCE);
|
||||
}
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
package com.sap.sailing.domain.racelogtracking.test.impl;
|
||||
|
||||
import static com.sap.sse.common.Util.size;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier;
|
||||
import com.sap.sailing.domain.racelogtracking.servlet.RecordFixesPostServlet;
|
||||
import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.DeviceAndSessionIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RecordFixesTest extends AbstractGPSFixStoreTest {
|
||||
private RecordFixesPostServlet servlet;
|
||||
private final DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer =
|
||||
new MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer();
|
||||
private final DeviceIdentifier device = new SmartphoneImeiIdentifier("a");
|
||||
|
||||
@Before
|
||||
public void setupServlet() {
|
||||
servlet = new RecordFixesPostServlet();
|
||||
servlet = spy(servlet);
|
||||
when(servlet.getRequestDeserializer()).thenReturn(deserializer);
|
||||
doReturn(service).when(servlet).getService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void areFixesStoredInDb() throws TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
map(comp, device, 0, 600);
|
||||
|
||||
int timepoint = 343;
|
||||
List<GPSFix> fixes = new ArrayList<>();
|
||||
fixes.add(createFix(timepoint, 0, 0, 0, 0));
|
||||
fixes.add(createFix(timepoint+1, 0, 0, 0, 0));
|
||||
Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>> data = new Util.Triple<>(device, null, fixes);
|
||||
servlet.process(null, data);
|
||||
|
||||
DynamicGPSFixMovingTrackImpl<Competitor> track = new DynamicGPSFixMovingTrackImpl<>(comp, 0);
|
||||
store.loadCompetitorTrack(track, raceLog, comp);
|
||||
track.lockForRead();
|
||||
assertEquals(2, size(track.getRawFixes()));
|
||||
assertEquals(timepoint, track.getFirstRawFix().getTimePoint().asMillis());
|
||||
assertTrue(track.getFirstRawFix() instanceof GPSFixMoving);
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
@@ -4,7 +4,7 @@ Bundle-Name: Testsupport
|
||||
Bundle-SymbolicName: com.sap.sailing.domain.racelogtrackingadapter.testsupport
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.common,
|
||||
|
||||
+3
-3
@@ -3,11 +3,11 @@ package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.DeviceAndSessionIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.DeviceIdentifierJsonDeserializer;
|
||||
|
||||
public class MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer extends
|
||||
public class MockDeviceAndSessionIdentifierWithGPSFixesDeserializer extends
|
||||
DeviceAndSessionIdentifierWithGPSFixesDeserializer {
|
||||
|
||||
public MockDeviceAndSessioinIdentifierWithGPSFixesDeserializer() {
|
||||
super(new MockGPSFixJsonServiceFinder(),
|
||||
public MockDeviceAndSessionIdentifierWithGPSFixesDeserializer() {
|
||||
super(new MockServiceFinder<>(new MockGPSFixJsonHandler()),
|
||||
DeviceIdentifierJsonDeserializer.create(new SmartphoneImeiJsonHandler(), SmartphoneImeiIdentifier.TYPE));
|
||||
}
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.GPSFixMovingJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler;
|
||||
|
||||
public class MockGPSFixJsonServiceFinder implements TypeBasedServiceFinder<GPSFixJsonHandler> {
|
||||
private final MockGPSFixJsonHandler handler = new MockGPSFixJsonHandler();
|
||||
|
||||
@Override
|
||||
public GPSFixJsonHandler findService(String fixType) {
|
||||
if (fixType.equals(GPSFixMovingJsonDeserializer.TYPE)) {
|
||||
return handler;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackService(GPSFixJsonHandler fallback) {
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
|
||||
public class MockServiceFinder<T> implements TypeBasedServiceFinder<T> {
|
||||
private final T handler;
|
||||
private T fallback;
|
||||
|
||||
public MockServiceFinder(T handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T findService(String deviceType) {
|
||||
if (deviceType.equals(SmartphoneImeiIdentifier.TYPE)) return handler;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackService(T fallback) {
|
||||
this.fallback = fallback;
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
|
||||
/**
|
||||
* A simplified implementation of the {@link TypeBasedServiceFinder} interface that, when the device type
|
||||
* {@link SmartphoneImeiIdentifier#TYPE} is requested, returns a specific handler that was passed to this object's
|
||||
* constructor.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class MockSmartphoneImeiJsonServiceFinder implements TypeBasedServiceFinder<DeviceIdentifierJsonHandler> {
|
||||
private final SmartphoneImeiJsonHandler handler = new SmartphoneImeiJsonHandler();
|
||||
private DeviceIdentifierJsonHandler fallback;
|
||||
|
||||
@Override
|
||||
public DeviceIdentifierJsonHandler findService(String deviceType) {
|
||||
if (deviceType.equals(SmartphoneImeiIdentifier.TYPE)) return handler;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackService(DeviceIdentifierJsonHandler fallback) {
|
||||
this.fallback = fallback;
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
|
||||
|
||||
/**
|
||||
* A simplified implementation of the {@link TypeBasedServiceFinder} interface that, when the device type
|
||||
* {@link SmartphoneImeiIdentifier#TYPE} is requested, returns a specific handler that was passed to this object's
|
||||
* constructor.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class MockSmartphoneImeiMongoServiceFinder implements TypeBasedServiceFinder<DeviceIdentifierMongoHandler> {
|
||||
private final SmartphoneImeiMongoHandler handler = new SmartphoneImeiMongoHandler();
|
||||
private DeviceIdentifierMongoHandler fallback;
|
||||
|
||||
@Override
|
||||
public DeviceIdentifierMongoHandler findService(String deviceType) {
|
||||
if (deviceType.equals(SmartphoneImeiIdentifier.TYPE)) return handler;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallbackService(DeviceIdentifierMongoHandler fallback) {
|
||||
this.fallback = fallback;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -22,10 +22,10 @@ public class MockSmartphoneImeiServiceFinderFactory implements TypeBasedServiceF
|
||||
Map<Class<?>, TypeBasedServiceFinder<?>> serviceFinders = new HashMap<Class<?>, TypeBasedServiceFinder<?>>();
|
||||
|
||||
public MockSmartphoneImeiServiceFinderFactory() {
|
||||
serviceFinders.put(DeviceIdentifierMongoHandler.class, new MockSmartphoneImeiMongoServiceFinder());
|
||||
serviceFinders.put(DeviceIdentifierJsonHandler.class, new MockSmartphoneImeiJsonServiceFinder());
|
||||
serviceFinders.put(DeviceIdentifierMongoHandler.class, new MockServiceFinder<>(new SmartphoneImeiMongoHandler()));
|
||||
serviceFinders.put(DeviceIdentifierJsonHandler.class, new MockServiceFinder<>(new SmartphoneImeiJsonHandler()));
|
||||
serviceFinders.put(GPSFixMongoHandler.class, new MockGPSFixMongoServiceFinder());
|
||||
serviceFinders.put(GPSFixJsonHandler.class, new MockGPSFixJsonServiceFinder());
|
||||
serviceFinders.put(GPSFixJsonHandler.class, new MockServiceFinder<>(new MockGPSFixJsonHandler()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.sap.sailing.domain.racelog.tracking.test.mock;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinderFactory;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler;
|
||||
import com.sap.sailing.domain.persistence.racelog.tracking.GPSFixMongoHandler;
|
||||
import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDMongoHandler;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.impl.SmartphoneUUIDJsonHandler;
|
||||
|
||||
/**
|
||||
* A simplified implementation of the {@link TypeBasedServiceFinder} interface that, when the device type
|
||||
* {@link SmartphoneImeiIdentifier#TYPE} is requested, returns a specific handler that was passed to this object's
|
||||
* constructor.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class MockSmartphoneUuidServiceFinderFactory implements TypeBasedServiceFinderFactory {
|
||||
Map<Class<?>, TypeBasedServiceFinder<?>> serviceFinders = new HashMap<Class<?>, TypeBasedServiceFinder<?>>();
|
||||
|
||||
public MockSmartphoneUuidServiceFinderFactory() {
|
||||
serviceFinders.put(DeviceIdentifierMongoHandler.class, new MockServiceFinder<>(new SmartphoneUUIDMongoHandler()));
|
||||
serviceFinders.put(DeviceIdentifierJsonHandler.class, new MockServiceFinder<>(new SmartphoneUUIDJsonHandler()));
|
||||
serviceFinders.put(GPSFixMongoHandler.class, new MockGPSFixMongoServiceFinder());
|
||||
serviceFinders.put(GPSFixJsonHandler.class, new MockServiceFinder<>(new MockGPSFixJsonHandler()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <ServiceT> TypeBasedServiceFinder<ServiceT> createServiceFinder(Class<ServiceT> clazz) {
|
||||
return (TypeBasedServiceFinder<ServiceT>) serviceFinders.get(clazz);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,5 @@ Import-Package: com.mongodb,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.6.0"
|
||||
Export-Package: com.sap.sailing.domain.racelogtracking,
|
||||
com.sap.sailing.domain.racelogtracking.impl;x-friends:="com.sap.sailing.domain.racelogtrackingadapter.testsupport,com.sap.sailing.gwt.ui.test",
|
||||
com.sap.sailing.domain.racelogtracking.servlet;x-friends:="com.sap.sailing.domain.racelogtrackingadapter.test"
|
||||
Web-ContextPath: /tracking
|
||||
com.sap.sailing.domain.racelogtracking.impl;x-friends:="com.sap.sailing.domain.racelogtrackingadapter.testsupport,com.sap.sailing.gwt.ui.test"
|
||||
Bundle-Activator: com.sap.sailing.domain.racelogtracking.impl.Activator
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
|
||||
|
||||
<!-- Disable directory listing: -->
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet
|
||||
</servlet-class>
|
||||
<init-param>
|
||||
<param-name>dirAllowed</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>RecordFixesPostServlet</servlet-name>
|
||||
<servlet-class>com.sap.sailing.domain.racelogtracking.servlet.RecordFixesPostServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>RecordFixesPostServlet</servlet-name>
|
||||
<url-pattern>/recordFixes</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>RecordFixesFlatJsonPostServlet</servlet-name>
|
||||
<servlet-class>com.sap.sailing.domain.racelogtracking.servlet.RecordFixesFlatJsonPostServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>RecordFixesFlatJsonPostServlet</servlet-name>
|
||||
<url-pattern>/recordFixesFlatJson</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
package com.sap.sailing.domain.racelogtracking.servlet;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.server.gateway.AbstractJsonPostServlet;
|
||||
import com.sap.sailing.server.gateway.HttpExceptionWithMessage;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
public class RecordFixesFlatJsonPostServlet extends AbstractJsonPostServlet<Pair<UUID, GPSFixMoving>, Void> {
|
||||
private static final long serialVersionUID = -4618399862031700634L;
|
||||
|
||||
private final JsonDeserializer<Pair<UUID, GPSFixMoving>> deserializer =
|
||||
new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer();
|
||||
|
||||
@Override
|
||||
public JsonDeserializer<Pair<UUID, GPSFixMoving>> getRequestDeserializer() {
|
||||
return deserializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<Void> getResponseSerializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void process(Map<String, String> parameterValues, Pair<UUID, GPSFixMoving> domainObject)
|
||||
throws HttpExceptionWithMessage {
|
||||
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(domainObject.getA());
|
||||
GPSFixMoving fix = domainObject.getB();
|
||||
|
||||
try {
|
||||
getService().getGPSFixStore().storeFix(device, fix);
|
||||
logger.log(Level.INFO, "Added fix for device " + device.toString() + " to store");
|
||||
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
|
||||
logger.log(Level.WARNING, "Could not load store fix from device " + device);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
package com.sap.sailing.domain.racelogtracking.servlet;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TypeBasedServiceFinder;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.server.gateway.AbstractJsonPostServlet;
|
||||
import com.sap.sailing.server.gateway.HttpExceptionWithMessage;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.DeviceAndSessionIdentifierWithGPSFixesDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.DeviceIdentifierJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RecordFixesPostServlet extends
|
||||
AbstractJsonPostServlet<Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>>, Void> {
|
||||
private static final long serialVersionUID = 2778739335260621119L;
|
||||
private DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
TypeBasedServiceFinder<GPSFixJsonHandler> fixServiceFinder = getServiceFinderFactory().createServiceFinder(
|
||||
GPSFixJsonHandler.class);
|
||||
TypeBasedServiceFinder<DeviceIdentifierJsonHandler> deviceServiceFinder = getServiceFinderFactory()
|
||||
.createServiceFinder(DeviceIdentifierJsonHandler.class);
|
||||
deserializer = new DeviceAndSessionIdentifierWithGPSFixesDeserializer(fixServiceFinder,
|
||||
new DeviceIdentifierJsonDeserializer(deviceServiceFinder));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonDeserializer<Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>>> getRequestDeserializer() {
|
||||
return deserializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonSerializer<Void> getResponseSerializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void process(Map<String, String> parameterValues,
|
||||
Util.Triple<DeviceIdentifier, Serializable, List<GPSFix>> domainObject) throws HttpExceptionWithMessage {
|
||||
DeviceIdentifier device = domainObject.getA();
|
||||
// might use the session id in the future
|
||||
// Serializable sessionId = domainObject.getB();
|
||||
List<GPSFix> fixes = domainObject.getC();
|
||||
|
||||
for (GPSFix fix : fixes) {
|
||||
try {
|
||||
getService().getGPSFixStore().storeFix(device, fix);
|
||||
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
|
||||
logger.log(Level.WARNING, "Could not load store fix from device " + device);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class DeviceMappingImpl<ItemType extends WithID> implements DeviceMapping
|
||||
if (originalRaceLogEventId != null) originalRaceLogEventIds.add(originalRaceLogEventId);
|
||||
}
|
||||
|
||||
public DeviceMappingImpl(ItemType mappedTo, DeviceIdentifier device, TimeRange timeRange, List<Serializable> originalRaceLogEventIds) {
|
||||
public DeviceMappingImpl(ItemType mappedTo, DeviceIdentifier device, TimeRange timeRange, List<? extends Serializable> originalRaceLogEventIds) {
|
||||
this(mappedTo, device, timeRange);
|
||||
if (originalRaceLogEventIds != null) this.originalRaceLogEventIds.addAll(originalRaceLogEventIds);
|
||||
}
|
||||
|
||||
+2
-2
@@ -272,7 +272,7 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory {
|
||||
public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) {
|
||||
synchronized (boatClassCache) {
|
||||
BoatClass result = boatClassCache.get(name);
|
||||
if(result == null) {
|
||||
if (result == null && name != null) {
|
||||
BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name);
|
||||
if (boatClassMasterdata != null) {
|
||||
result = new BoatClassImpl(name, boatClassMasterdata);
|
||||
@@ -289,7 +289,7 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory {
|
||||
|
||||
@Override
|
||||
public BoatClass getOrCreateBoatClass(String name) {
|
||||
return getOrCreateBoatClass(name, /* typicallyStartsUpwind */!mayStartWithNoUpwindLeg.contains(name.toLowerCase()));
|
||||
return getOrCreateBoatClass(name, name == null || /* typicallyStartsUpwind */!mayStartWithNoUpwindLeg.contains(name.toLowerCase()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Executable
+25
@@ -0,0 +1,25 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
|
||||
public class BoatClassWithNullNameTest {
|
||||
/**
|
||||
* See bug 2471
|
||||
*/
|
||||
@Test
|
||||
public void testCreatingBoatClassWithNullName() {
|
||||
DomainFactory domainFactory = DomainFactory.INSTANCE;
|
||||
BoatClass boatClass = domainFactory.getOrCreateBoatClass(null);
|
||||
assertNotNull(boatClass);
|
||||
assertNull(boatClass.getName());
|
||||
BoatClass boatClass2 = domainFactory.getOrCreateBoatClass(null);
|
||||
assertSame(boatClass, boatClass2);
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
package com.sap.sailing.domain.common.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.omg.CORBA.LongHolder;
|
||||
|
||||
/**
|
||||
* Compare Java 8 stream and function performance to direct method call performance
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class Java8FunctionsPerformanceTest {
|
||||
private static final Logger logger = Logger.getLogger(Java8FunctionsPerformanceTest.class.getName());
|
||||
private List<Integer> intList;
|
||||
private final static int SIZE = 10000000;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
intList = new ArrayList<Integer>(SIZE);
|
||||
for (int i=0; i<SIZE; i++) {
|
||||
intList.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intArraySumWithIterator() {
|
||||
long start = System.currentTimeMillis();
|
||||
long sum = 0;
|
||||
for (Integer i : intList) {
|
||||
sum += i;
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
assertEquals(((long) SIZE)*((long) SIZE-1l)/2, sum);
|
||||
logger.info("took "+(end-start)+"ms");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intArraySumWithStream() {
|
||||
long start = System.currentTimeMillis();
|
||||
final LongHolder sum = new LongHolder(0);
|
||||
intList.stream().forEach((i) -> sum.value += i);
|
||||
long end = System.currentTimeMillis();
|
||||
assertEquals(((long) SIZE)*((long) SIZE-1l)/2, sum.value);
|
||||
logger.info("took "+(end-start)+"ms");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intArraySumWithForEach() {
|
||||
long start = System.currentTimeMillis();
|
||||
final LongHolder sum = new LongHolder(0);
|
||||
intList.forEach((i) -> sum.value += i);
|
||||
long end = System.currentTimeMillis();
|
||||
assertEquals(((long) SIZE)*((long) SIZE-1l)/2, sum.value);
|
||||
logger.info("took "+(end-start)+"ms");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intArraySumWithIntRangeStream() {
|
||||
IntStream is = IntStream.range(0, SIZE);
|
||||
long start = System.currentTimeMillis();
|
||||
final LongHolder sum = new LongHolder(0);
|
||||
is.forEach(i -> sum.value += i);
|
||||
long end = System.currentTimeMillis();
|
||||
assertEquals(((long) SIZE)*((long) SIZE-1l)/2, sum.value);
|
||||
logger.info("took "+(end-start)+"ms");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intSum() {
|
||||
long start = System.currentTimeMillis();
|
||||
long sum = 0;
|
||||
for (int i=0; i<SIZE; i++) {
|
||||
sum += i;
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
assertEquals(((long) SIZE)*((long) SIZE-1l)/2, sum);
|
||||
logger.info("took "+(end-start)+"ms");
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.mongodb"
|
||||
id="com.sap.sse.mongodb"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
</listAttribute>
|
||||
<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.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/sapjvm7"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/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/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.ui.Search -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/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/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator 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 -Xdebug -Xrunjdwp:transport=dt_socket,address=7999,server=y"/>
|
||||
</launchConfiguration>
|
||||
@@ -3,11 +3,7 @@
|
||||
<booleanAttribute key="com.google.gdt.eclipse.core.RUN_SERVER" value="false"/>
|
||||
<stringAttribute key="com.google.gdt.eclipse.suiteMainTypeProcessor.PREVIOUSLY_SET_MAIN_TYPE_NAME" value="com.google.gwt.dev.GWTShell"/>
|
||||
<booleanAttribute key="com.google.gdt.eclipse.suiteWarArgumentProcessor.IS_WAR_FROM_PROJECT_PROPERTIES" value="true"/>
|
||||
<listAttribute key="com.google.gwt.eclipse.core.ENTRY_POINT_MODULES">
|
||||
<listEntry value="com.sap.sailing.gwt.ui.VideoPopup"/>
|
||||
<listEntry value="com.sap.sailing.gwt.ui.Simulator"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/AdminConsole.html"/>
|
||||
<stringAttribute key="com.google.gwt.eclipse.core.URL" value="/gwt/Home.html"/>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/com.sap.sailing.gwt.ui"/>
|
||||
</listAttribute>
|
||||
@@ -32,7 +28,7 @@
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.declination/resources" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.udpconnector/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.mongodb/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.mongodb/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.persistence/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.domain.swisstimingadapter.persistence/src" path="3" type="2"/> "/>
|
||||
@@ -47,12 +43,15 @@
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.google.gwt.osgi/lib/gwt-user.jar" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="com.sap.sailing.gwt.ui"/> </runtimeClasspathEntry> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security/src" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.security.ui/src/main/java" path="3" type="2"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sse.gwt.adminconsole/src" path="3" type="2"/> "/>
|
||||
</listAttribute>
|
||||
<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.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/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/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup -startupUrl /gwt/Search.html com.sap.sailing.gwt.ui.Search -startupUrl /security/ui/Login.html com.sap.sse.security.ui.Login -startupUrl /security/ui/EditProfile.html com.sap.sse.security.ui.EditProfile -startupUrl /security/ui/EmailValidation.html com.sap.sse.security.ui.EmailValidation com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/Home.html com.sap.sailing.gwt.Home -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/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/PolarSheets.html com.sap.sailing.gwt.ui.PolarSheets -startupUrl /gwt/RegattaOverview.html com.sap.sailing.gwt.ui.RegattaOverview -startupUrl /gwt/DataMining.html com.sap.sailing.gwt.ui.DataMining -startupUrl /gwt/Simulator.html com.sap.sailing.gwt.ui.Simulator -startupUrl /gwt/VideoPopup.html com.sap.sailing.gwt.ui.VideoPopup -startupUrl /security/ui/Login.html com.sap.sse.security.ui.Login -startupUrl /security/ui/EditProfile.html com.sap.sse.security.ui.EditProfile -startupUrl /security/ui/EmailValidation.html com.sap.sse.security.ui.EmailValidation"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m"/>
|
||||
</launchConfiguration>
|
||||
@@ -1,33 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics TV View</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
|
||||
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="highcharts/js/highcharts.js"></script>
|
||||
|
||||
<!-- Optionally, add a highcharts theme file -->
|
||||
<script type="text/javascript" src="highcharts/js/themes/grid.js"></script>
|
||||
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.TvView/com.sap.sailing.gwt.ui.TvView.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
|
||||
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
|
||||
<noscript>
|
||||
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
|
||||
Your web browser must have JavaScript enabled
|
||||
in order for this application to display correctly.
|
||||
</div>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
@@ -41,8 +41,6 @@ bin.includes = META-INF/,\
|
||||
VideoPopup.css,\
|
||||
com.sap.sailing.gwt.ui.YoutubePopup/,\
|
||||
YoutubePopup.html,\
|
||||
TvView.html,\
|
||||
com.sap.sailing.gwt.ui.TvView/,\
|
||||
BrowserUnsupported.html,\
|
||||
PolarSheets.css,\
|
||||
PolarSheets.html,\
|
||||
|
||||
@@ -127,7 +127,6 @@
|
||||
<module>com.sap.sailing.gwt.ui.RaceBoard</module>
|
||||
<module>com.sap.sailing.gwt.ui.Spectator</module>
|
||||
<module>com.sap.sailing.gwt.ui.DataMining</module>
|
||||
<module>com.sap.sailing.gwt.ui.TvView</module>
|
||||
<module>com.sap.sailing.gwt.ui.VideoPopup</module>
|
||||
<module>com.sap.sailing.gwt.ui.YoutubePopup</module>
|
||||
<module>com.sap.sailing.gwt.ui.Simulator</module>
|
||||
|
||||
+12
-4
@@ -449,12 +449,20 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeTrackingRace(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers, boolean isTracked) {
|
||||
public void racesStoppedTracking(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers) {
|
||||
// nothing needs to be done here; the race doesn't change its linkedness status only because it stopped tracking
|
||||
}
|
||||
|
||||
/**
|
||||
* When a race is removed from the server, it will also have been unlinked. Represent the unlinking by clearing the
|
||||
* tracked race link for any race column / fleet that points to it:
|
||||
*/
|
||||
@Override
|
||||
public void racesRemoved(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers) {
|
||||
for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) {
|
||||
for (RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName : raceColumnTable.getDataProvider().getList()) {
|
||||
if (raceColumnAndFleetName.getA().getRaceColumnName().equals(regattaAndRaceIdentifier.getRaceName())) {
|
||||
raceColumnAndFleetName.getA().setRaceIdentifier(raceColumnAndFleetName.getB(),
|
||||
regattaAndRaceIdentifier);
|
||||
if (Util.equalsWithNull(raceColumnAndFleetName.getA().getRaceIdentifier(raceColumnAndFleetName.getB()), regattaAndRaceIdentifier)) {
|
||||
raceColumnAndFleetName.getA().setRaceIdentifier(raceColumnAndFleetName.getB(), null);
|
||||
}
|
||||
}
|
||||
raceColumnTable.getDataProvider().refresh();
|
||||
|
||||
+2
-2
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -24,6 +23,7 @@ import com.google.gwt.view.client.SelectionModel;
|
||||
import com.google.gwt.view.client.SingleSelectionModel;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox;
|
||||
@@ -43,7 +43,7 @@ public class AddDeviceMappingDialog extends DataEntryDialog<DeviceMappingDTO> {
|
||||
private final MarkTableWrapper<SingleSelectionModel<MarkDTO>> markTable;
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
private Serializable selectedItem;
|
||||
private MappableToDevice selectedItem;
|
||||
|
||||
public AddDeviceMappingDialog(SailingServiceAsync sailingService, final ErrorReporter errorReporter,
|
||||
final StringMessages stringMessages, String leaderboardName, String raceColumnName, String fleetName,
|
||||
|
||||
+2
-23
@@ -5,12 +5,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.DockPanel;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.RootLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.TabLayoutPanel;
|
||||
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
|
||||
@@ -33,13 +29,11 @@ import com.sap.sailing.gwt.ui.shared.SecurityStylesheetResources;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
import com.sap.sse.gwt.adminconsole.AdminConsolePanel;
|
||||
import com.sap.sse.gwt.adminconsole.DefaultRefreshableAdminConsolePanel;
|
||||
import com.sap.sse.gwt.adminconsole.SystemInformationPanel;
|
||||
import com.sap.sse.gwt.client.EntryPointHelper;
|
||||
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
||||
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
|
||||
import com.sap.sse.security.ui.client.component.UserManagementPanel;
|
||||
import com.sap.sse.security.ui.client.i18n.StringMessages;
|
||||
import com.sap.sse.security.ui.loginpanel.LoginPanel;
|
||||
|
||||
public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements RegattaRefresher, LeaderboardsRefresher, LeaderboardGroupsRefresher {
|
||||
private Set<RegattasDisplayer> regattasDisplayers;
|
||||
@@ -75,10 +69,10 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements
|
||||
}, getStringMessages().events(), SailingAdminConsoleFeatures.MANAGE_EVENTS);
|
||||
leaderboardGroupsDisplayers.add(eventManagementPanel);
|
||||
|
||||
RegattaStructureManagementPanel regattaManagementPanel = new RegattaStructureManagementPanel(
|
||||
RegattaManagementPanel regattaManagementPanel = new RegattaManagementPanel(
|
||||
sailingService, this, getStringMessages(), this);
|
||||
regattaManagementPanel.ensureDebugId("RegattaStructureManagement");
|
||||
panel.addToVerticalTabPanel(new DefaultRefreshableAdminConsolePanel<RegattaStructureManagementPanel>(regattaManagementPanel) {
|
||||
panel.addToVerticalTabPanel(new DefaultRefreshableAdminConsolePanel<RegattaManagementPanel>(regattaManagementPanel) {
|
||||
@Override
|
||||
public void refreshAfterBecomingVisible() {
|
||||
fillRegattas();
|
||||
@@ -227,21 +221,6 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint implements
|
||||
fillRegattas();
|
||||
fillLeaderboardGroups();
|
||||
fillLeaderboards();
|
||||
|
||||
final DockPanel informationPanel = new DockPanel();
|
||||
informationPanel.setSize("100%", "95%");
|
||||
informationPanel.setSpacing(10);
|
||||
informationPanel.add(new LoginPanel(SecurityStylesheetResources.INSTANCE.css(), getUserService()), DockPanel.WEST);
|
||||
informationPanel.add(persistentAlertLabel, DockPanel.CENTER);
|
||||
|
||||
SystemInformationPanel sysinfoPanel = new SystemInformationPanel(sailingService, this);
|
||||
sysinfoPanel.ensureDebugId("SystemInformation");
|
||||
|
||||
final Anchor releaseNotesLink = new Anchor(new SafeHtmlBuilder().appendEscaped(getStringMessages().releaseNotes()).toSafeHtml(), "/release_notes_admin.html");
|
||||
sysinfoPanel.add(releaseNotesLink);
|
||||
informationPanel.add(sysinfoPanel, DockPanel.EAST);
|
||||
informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
|
||||
RootLayoutPanel rootPanel = RootLayoutPanel.get();
|
||||
rootPanel.add(panel);
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -15,6 +14,7 @@ import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SingleSelectionModel;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO;
|
||||
@@ -31,7 +31,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
|
||||
private final MarkTableWrapper<SingleSelectionModel<MarkDTO>> markTable;
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
private final Map<TrackFileImportDeviceIdentifierDTO, Serializable> mappings = new HashMap<>();
|
||||
private final Map<TrackFileImportDeviceIdentifierDTO, MappableToDevice> mappings = new HashMap<>();
|
||||
|
||||
private TrackFileImportDeviceIdentifierDTO deviceToSelect;
|
||||
private CompetitorDTO compToSelect;
|
||||
@@ -130,7 +130,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
|
||||
}
|
||||
}
|
||||
|
||||
private void mappedToSelectionChanged(Serializable mappedTo) {
|
||||
private void mappedToSelectionChanged(MappableToDevice mappedTo) {
|
||||
if (! inInstableTransitionState) {
|
||||
TrackFileImportDeviceIdentifierDTO device = deviceIdTable.getSelectionModel().getSelectedObject();
|
||||
if (device != null) {
|
||||
@@ -155,7 +155,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
|
||||
markToSelect = null;
|
||||
|
||||
if (deviceId != null) {
|
||||
Serializable mappedTo = mappings.get(deviceId);
|
||||
MappableToDevice mappedTo = mappings.get(deviceId);
|
||||
if (mappedTo instanceof CompetitorDTO) {
|
||||
compToSelect = (CompetitorDTO) mappedTo;
|
||||
} else if (mappedTo instanceof MarkDTO) {
|
||||
@@ -192,7 +192,7 @@ public class ImportFixesAndAddMappingsDialog extends DataEntryDialog<Collection<
|
||||
List<DeviceMappingDTO> result = new ArrayList<>();
|
||||
for (TrackFileImportDeviceIdentifierDTO device : mappings.keySet()) {
|
||||
DeviceIdentifierDTO deviceIdDto = new DeviceIdentifierDTO("FILE", device.uuidAsString);
|
||||
Serializable mappedTo = mappings.get(device);
|
||||
MappableToDevice mappedTo = mappings.get(device);
|
||||
DeviceMappingDTO mapping = new DeviceMappingDTO(deviceIdDto, device.from, device.to,
|
||||
mappedTo, null);
|
||||
result.add(mapping);
|
||||
|
||||
-1
@@ -312,7 +312,6 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return getSelectedLeaderboard() != null && !getSelectedLeaderboard().type.isRegattaLeaderboard();
|
||||
|
||||
}
|
||||
})) {
|
||||
@Override
|
||||
|
||||
+1
@@ -374,6 +374,7 @@ public class RegattaDetailsComposite extends Composite {
|
||||
|
||||
private void updateRegattaDetails() {
|
||||
if (regatta != null) {
|
||||
mainPanel.setCaptionText(stringMessages.regatta() + " " + regatta.getName());
|
||||
regattaName.setText(regatta.getName());
|
||||
boatClassName.setText(regatta.boatClass != null ? regatta.boatClass.getName() : "");
|
||||
defaultCourseArea.setText(regatta.defaultCourseAreaUuid == null ? "" : regatta.defaultCourseAreaName);
|
||||
|
||||
+22
-4
@@ -23,7 +23,6 @@ import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.google.gwt.view.client.MultiSelectionModel;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SelectionModel;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.impl.NaturalComparator;
|
||||
@@ -32,6 +31,7 @@ import com.sap.sailing.gwt.ui.client.RegattaSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.RegattasDisplayer;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
@@ -42,7 +42,7 @@ import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
|
||||
|
||||
public class RegattaListComposite extends Composite implements RegattasDisplayer {
|
||||
|
||||
private final SelectionModel<RegattaDTO> regattaSelectionModel;
|
||||
private final MultiSelectionModel<RegattaDTO> regattaSelectionModel;
|
||||
private final CellTable<RegattaDTO> regattaTable;
|
||||
private ListDataProvider<RegattaDTO> regattaListDataProvider;
|
||||
private List<RegattaDTO> allRegattas;
|
||||
@@ -90,6 +90,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer
|
||||
regattaTable = createRegattaTable();
|
||||
regattaTable.ensureDebugId("RegattasCellTable");
|
||||
regattaTable.setVisible(false);
|
||||
|
||||
filterablePanelRegattas = new LabeledAbstractFilterablePanel<RegattaDTO>(filterRegattasLabel, allRegattas,
|
||||
regattaTable, regattaListDataProvider) {
|
||||
@Override
|
||||
@@ -105,7 +106,10 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer
|
||||
filterablePanelRegattas.getTextBox().ensureDebugId("ReggatasFilterTextBox");
|
||||
panel.add(filterablePanelRegattas);
|
||||
|
||||
regattaSelectionModel = new MultiSelectionModel<RegattaDTO>();
|
||||
@SuppressWarnings("unchecked")
|
||||
MultiSelectionModel<RegattaDTO> multiSelectionModel = (MultiSelectionModel<RegattaDTO>) regattaTable.getSelectionModel();
|
||||
regattaSelectionModel = multiSelectionModel;
|
||||
|
||||
regattaSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
|
||||
@Override
|
||||
public void onSelectionChange(SelectionChangeEvent event) {
|
||||
@@ -117,7 +121,6 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer
|
||||
RegattaListComposite.this.regattaSelectionProvider.setSelection(selectedRaceIdentifiers);
|
||||
}
|
||||
});
|
||||
regattaTable.setSelectionModel(regattaSelectionModel);
|
||||
|
||||
panel.add(regattaTable);
|
||||
|
||||
@@ -129,6 +132,19 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer
|
||||
regattaListDataProvider.addDataDisplay(table);
|
||||
table.setWidth("100%");
|
||||
|
||||
SelectionCheckboxColumn<RegattaDTO> regattaSelectionCheckboxColumn = new SelectionCheckboxColumn<RegattaDTO>(tableRes.cellTableStyle().cellTableCheckboxSelected(),
|
||||
tableRes.cellTableStyle().cellTableCheckboxDeselected(), tableRes.cellTableStyle().cellTableCheckboxColumnCell()) {
|
||||
@Override
|
||||
protected ListDataProvider<RegattaDTO> getListDataProvider() {
|
||||
return regattaListDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue(RegattaDTO row) {
|
||||
return regattaTable.getSelectionModel().isSelected(row);
|
||||
}
|
||||
};
|
||||
|
||||
ListHandler<RegattaDTO> columnSortHandler = new ListHandler<RegattaDTO>(regattaListDataProvider.getList());
|
||||
table.addColumnSortHandler(columnSortHandler);
|
||||
|
||||
@@ -175,9 +191,11 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer
|
||||
}
|
||||
});
|
||||
|
||||
table.addColumn(regattaSelectionCheckboxColumn, regattaSelectionCheckboxColumn.getHeader());
|
||||
table.addColumn(regattaNameColumn, stringMessages.regattaName());
|
||||
table.addColumn(regattaBoatClassColumn, stringMessages.boatClass());
|
||||
table.addColumn(regattaActionColumn, stringMessages.actions());
|
||||
table.setSelectionModel(regattaSelectionCheckboxColumn.getSelectionModel(), regattaSelectionCheckboxColumn.getSelectionManager());
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
+14
-13
@@ -6,14 +6,12 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HasVerticalAlignment;
|
||||
import com.google.gwt.user.client.ui.CaptionPanel;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
@@ -40,7 +38,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
|
||||
* @author Frank Mittag (C5163974)
|
||||
*
|
||||
*/
|
||||
public class RegattaStructureManagementPanel extends SimplePanel implements RegattasDisplayer, RegattaSelectionChangeListener {
|
||||
public class RegattaManagementPanel extends SimplePanel implements RegattasDisplayer, RegattaSelectionChangeListener {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final StringMessages stringMessages;
|
||||
@@ -52,7 +50,9 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega
|
||||
private RegattaListComposite regattaListComposite;
|
||||
private RegattaDetailsComposite regattaDetailsComposite;
|
||||
|
||||
public RegattaStructureManagementPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter,
|
||||
private final CaptionPanel regattasPanel;
|
||||
|
||||
public RegattaManagementPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter,
|
||||
StringMessages stringMessages, RegattaRefresher regattaRefresher) {
|
||||
this.sailingService = sailingService;
|
||||
this.stringMessages = stringMessages;
|
||||
@@ -63,6 +63,11 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega
|
||||
setWidget(mainPanel);
|
||||
mainPanel.setWidth("100%");
|
||||
|
||||
regattasPanel = new CaptionPanel(stringMessages.regattas());
|
||||
mainPanel.add(regattasPanel);
|
||||
VerticalPanel regattasContentPanel = new VerticalPanel();
|
||||
regattasPanel.setContentWidget(regattasContentPanel);
|
||||
|
||||
HorizontalPanel regattaManagementControlsPanel = new HorizontalPanel();
|
||||
regattaManagementControlsPanel.setSpacing(5);
|
||||
|
||||
@@ -94,23 +99,19 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega
|
||||
}
|
||||
});
|
||||
regattaManagementControlsPanel.add(removeRegattaButton);
|
||||
mainPanel.add(regattaManagementControlsPanel);
|
||||
|
||||
Grid grid = new Grid(1 ,2);
|
||||
mainPanel.add(grid);
|
||||
regattasContentPanel.add(regattaManagementControlsPanel);
|
||||
|
||||
regattaSelectionProvider = new RegattaSelectionModel(true);
|
||||
regattaSelectionProvider.addRegattaSelectionChangeListener(this);
|
||||
|
||||
regattaListComposite = new RegattaListComposite(sailingService, regattaSelectionProvider, regattaRefresher, errorReporter, stringMessages);
|
||||
regattaListComposite.ensureDebugId("RegattaListComposite");
|
||||
grid.setWidget(0, 0, regattaListComposite);
|
||||
grid.getRowFormatter().setVerticalAlign(0, HasVerticalAlignment.ALIGN_TOP);
|
||||
grid.getColumnFormatter().getElement(1).getStyle().setPaddingTop(2.0, Unit.EM);
|
||||
regattasContentPanel.add(regattaListComposite);
|
||||
|
||||
regattaDetailsComposite = new RegattaDetailsComposite(sailingService, regattaRefresher, errorReporter, stringMessages);
|
||||
regattaDetailsComposite.ensureDebugId("RegattaDetailsComposite");
|
||||
regattaDetailsComposite.setVisible(false);
|
||||
grid.setWidget(0, 1, regattaDetailsComposite);
|
||||
mainPanel.add(regattaDetailsComposite);
|
||||
}
|
||||
|
||||
protected void removeRegattas(Collection<RegattaIdentifier> regattas) {
|
||||
+3
-1
@@ -3,5 +3,7 @@ package com.sap.sailing.gwt.ui.adminconsole;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
|
||||
public interface TrackedRaceChangedListener {
|
||||
void changeTrackingRace(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers, boolean isTracked);
|
||||
void racesStoppedTracking(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers);
|
||||
|
||||
void racesRemoved(Iterable<? extends RegattaAndRaceIdentifier> regattaAndRaceIdentifiers);
|
||||
}
|
||||
+2
-2
@@ -72,7 +72,7 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite
|
||||
public void onSuccess(Void result) {
|
||||
regattaRefresher.fillRegattas();
|
||||
for (TrackedRaceChangedListener listener : raceIsTrackedRaceChangeListener) {
|
||||
listener.changeTrackingRace(racesToStopTracking, false);
|
||||
listener.racesStoppedTracking(racesToStopTracking);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -95,7 +95,7 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite
|
||||
public void onSuccess(Void result) {
|
||||
regattaRefresher.fillRegattas();
|
||||
for (TrackedRaceChangedListener listener : raceIsTrackedRaceChangeListener) {
|
||||
listener.changeTrackingRace(regattaNamesAndRaceNames, false);
|
||||
listener.racesRemoved(regattaNamesAndRaceNames);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -490,7 +489,7 @@ public interface SailingService extends RemoteService {
|
||||
* Revoke the events in the {@code RaceLog} that are identified by the {@code eventIds}.
|
||||
* This only affects such events that implement {@link Revokable}.
|
||||
*/
|
||||
void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName, List<Serializable> eventIds)
|
||||
void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName, List<UUID> eventIds)
|
||||
throws NotRevokableException;
|
||||
|
||||
Collection<String> getGPSFixImporterTypes();
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -76,7 +75,7 @@ import com.sap.sailing.gwt.ui.shared.WindDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.search.KeywordQuery;
|
||||
import com.sap.sse.gwt.adminconsole.BuildVersionRetriever;
|
||||
import com.sap.sse.gwt.client.BuildVersionRetriever;
|
||||
|
||||
/**
|
||||
* The async counterpart of {@link SailingService}
|
||||
@@ -598,7 +597,7 @@ public interface SailingServiceAsync extends BuildVersionRetriever {
|
||||
void closeOpenEndedDeviceMapping(String leaderboardName, String raceColumnName, String fleetName,
|
||||
DeviceMappingDTO mapping, Date closingTimePoint, AsyncCallback<Void> callback);
|
||||
|
||||
void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName, List<Serializable> eventIds,
|
||||
void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName, List<UUID> eventIds,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void removeSeries(RegattaIdentifier regattaIdentifier, String seriesName, AsyncCallback<Void> callback);
|
||||
|
||||
+17
-3
@@ -194,6 +194,7 @@ import com.sap.sailing.domain.common.racelog.FlagPole;
|
||||
import com.sap.sailing.domain.common.racelog.Flags;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NotRevokableException;
|
||||
@@ -4863,7 +4864,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
null : mapping.getTimeRange().from().asDate();
|
||||
Date to = mapping.getTimeRange().to() == null || mapping.getTimeRange().to().asMillis() == Long.MAX_VALUE ?
|
||||
null : mapping.getTimeRange().to().asDate();
|
||||
Serializable item = null;
|
||||
MappableToDevice item = null;
|
||||
if (mapping.getMappedTo() instanceof Competitor) {
|
||||
item = baseDomainFactory.convertToCompetitorDTO((Competitor) mapping.getMappedTo());
|
||||
} else if (mapping.getMappedTo() instanceof Mark) {
|
||||
@@ -4871,8 +4872,20 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
} else {
|
||||
throw new RuntimeException("Can only handle Competitor or Mark as mapped item type");
|
||||
}
|
||||
//Only deal with UUIDs - otherwise we would have to pass Serializable to browser context - which
|
||||
//has a large performance implact for GWT.
|
||||
//As any Serializable subclass is converted to String by the BaseRaceLogEventSerializer, and only UUIDs are
|
||||
//recovered by the BaseRaceLogEventDeserializer, only UUIDs are safe to use anyway.
|
||||
List<UUID> originalRaceLogEventUUIDs = new ArrayList<UUID>();
|
||||
for (Serializable id : mapping.getOriginalRaceLogEventIds()) {
|
||||
if (! (id instanceof UUID)) {
|
||||
logger.log(Level.WARNING, "Got RaceLogEvent with id that was not UUID, but " + id.getClass().getName());
|
||||
throw new TransformationException("Could not send device mapping to browser: can only deal with UUIDs");
|
||||
}
|
||||
originalRaceLogEventUUIDs.add((UUID) id);
|
||||
}
|
||||
return new DeviceMappingDTO(new DeviceIdentifierDTO(mapping.getDevice().getIdentifierType(),
|
||||
deviceId), from, to, item, mapping.getOriginalRaceLogEventIds());
|
||||
deviceId), from, to, item, originalRaceLogEventUUIDs);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -4944,6 +4957,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
TimeRange timeRange = new TimeRangeImpl(from, to);
|
||||
if (dto.mappedTo instanceof MarkDTO) {
|
||||
Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true);
|
||||
//expect UUIDs
|
||||
return new DeviceMappingImpl<Mark>(mark, device, timeRange, dto.originalRaceLogEventIds);
|
||||
} else if (dto.mappedTo instanceof CompetitorDTO) {
|
||||
Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(
|
||||
@@ -4970,7 +4984,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
|
||||
@Override
|
||||
public void revokeRaceLogEvents(String leaderboardName, String raceColumnName, String fleetName,
|
||||
List<Serializable> eventIds) throws NotRevokableException {
|
||||
List<UUID> eventIds) throws NotRevokableException {
|
||||
RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName);
|
||||
for (Serializable idToRevoke : eventIds) {
|
||||
raceLog.lockForRead();
|
||||
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
|
||||
public class DeviceIdentifierDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1171014272760543228L;
|
||||
public class DeviceIdentifierDTO implements IsSerializable {
|
||||
public String deviceType;
|
||||
public String deviceId;
|
||||
|
||||
|
||||
+9
-7
@@ -1,21 +1,23 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DeviceMappingDTO implements Serializable {
|
||||
private static final long serialVersionUID = -3272980620254526040L;
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
|
||||
public class DeviceMappingDTO implements IsSerializable {
|
||||
public DeviceIdentifierDTO deviceIdentifier;
|
||||
public Date from;
|
||||
public Date to;
|
||||
public Serializable mappedTo;
|
||||
public List<Serializable> originalRaceLogEventIds;
|
||||
public MappableToDevice mappedTo;
|
||||
public List<UUID> originalRaceLogEventIds;
|
||||
|
||||
protected DeviceMappingDTO() {}
|
||||
|
||||
public DeviceMappingDTO(DeviceIdentifierDTO deviceId, Date from, Date to, Serializable mappedTo,
|
||||
List<Serializable> originalRaceLogEventIds) {
|
||||
public DeviceMappingDTO(DeviceIdentifierDTO deviceId, Date from, Date to, MappableToDevice mappedTo,
|
||||
List<UUID> originalRaceLogEventIds) {
|
||||
this.deviceIdentifier = deviceId;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
|
||||
+2
-1
@@ -4,8 +4,9 @@ import java.util.Collections;
|
||||
|
||||
import com.sap.sailing.domain.common.MarkType;
|
||||
import com.sap.sailing.domain.common.dto.PositionDTO;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice;
|
||||
|
||||
public class MarkDTO extends ControlPointDTO {
|
||||
public class MarkDTO extends ControlPointDTO implements MappableToDevice {
|
||||
private static final long serialVersionUID = -8031499997812618751L;
|
||||
public PositionDTO position;
|
||||
public String color;
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.tv;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.rpc.ServiceDefTarget;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.RootLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.RootPanel;
|
||||
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
|
||||
import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
|
||||
import com.sap.sailing.gwt.ui.client.MediaService;
|
||||
import com.sap.sailing.gwt.ui.client.MediaServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants;
|
||||
import com.sap.sailing.gwt.ui.client.SailingService;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
|
||||
import com.sap.sse.gwt.client.EntryPointHelper;
|
||||
import com.sap.sse.gwt.shared.GwtHttpRequestUtils;
|
||||
|
||||
public class TVEntryPoint extends AbstractSailingEntryPoint {
|
||||
|
||||
private static final String PARAM_LEADERBOARD_NAME = "name";
|
||||
private static final String PARAM_LEADERBOARD_GROUP_NAME = "leaderboardGroupName";
|
||||
private static final String PARAM_EMBEDDED = "embedded";
|
||||
private static final String PARAM_SHOW_RACE_DETAILS = "showRaceDetails";
|
||||
private static final String PARAM_DELAY_TO_LIVE_MILLIS = "delayToLiveMillis";
|
||||
private String leaderboardName;
|
||||
private String leaderboardGroupName;
|
||||
private TVViewController tvViewController;
|
||||
private RaceBoardViewConfiguration raceboardViewConfig;
|
||||
|
||||
private final SailingServiceAsync sailingService = GWT.create(SailingService.class);
|
||||
private final MediaServiceAsync mediaService = GWT.create(MediaService.class);
|
||||
|
||||
@Override
|
||||
public void doOnModuleLoad() {
|
||||
super.doOnModuleLoad();
|
||||
|
||||
EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.sailingServiceRemotePath);
|
||||
EntryPointHelper.registerASyncService((ServiceDefTarget) mediaService, RemoteServiceMappingConstants.mediaServiceRemotePath);
|
||||
|
||||
final boolean showRaceDetails = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_RACE_DETAILS, true);
|
||||
final boolean embedded = GwtHttpRequestUtils.getBooleanParameter(PARAM_EMBEDDED, false);
|
||||
final long delayToLiveMillis = Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS) != null ? Long
|
||||
.valueOf(Window.Location.getParameter(PARAM_DELAY_TO_LIVE_MILLIS)) : 5000l; // default 5s
|
||||
final boolean showLeaderboard = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_LEADERBOARD, true /* default */);
|
||||
final boolean showWindChart = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_WINDCHART, false /* default */);
|
||||
final boolean showViewStreamlets = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLETS, false /* default */);
|
||||
final boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, false /* default */);
|
||||
final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default */);
|
||||
String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/);
|
||||
final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default */);
|
||||
final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, false);
|
||||
raceboardViewConfig = new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard,
|
||||
showWindChart, showCompetitorsChart, showViewStreamlets, showViewSimulation, /* canReplayWhileLiveIsPossible */false, autoSelectMedia, defaultMedia);
|
||||
|
||||
sailingService.getLeaderboardNames(new AsyncCallback<List<String>>() {
|
||||
@Override
|
||||
public void onSuccess(List<String> leaderboardNames) {
|
||||
leaderboardName = Window.Location.getParameter(PARAM_LEADERBOARD_NAME);
|
||||
leaderboardGroupName = Window.Location.getParameter(PARAM_LEADERBOARD_GROUP_NAME);
|
||||
if (leaderboardNames.contains(leaderboardName)) {
|
||||
createUI(showRaceDetails, embedded, delayToLiveMillis);
|
||||
} else {
|
||||
RootPanel.get().add(new Label(getStringMessages().noSuchLeaderboard()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
reportError("Error trying to obtain list of leaderboard names: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createUI(boolean showRaceDetails, boolean embedded, long delayToLiveMillis) {
|
||||
DockLayoutPanel mainPanel = new DockLayoutPanel(Unit.PX);
|
||||
RootLayoutPanel.get().add(mainPanel);
|
||||
LogoAndTitlePanel logoAndTitlePanel = null;
|
||||
if (!embedded) {
|
||||
String leaderboardDisplayName = Window.Location.getParameter("displayName");
|
||||
if(leaderboardDisplayName == null || leaderboardDisplayName.isEmpty()) {
|
||||
leaderboardDisplayName = leaderboardName;
|
||||
}
|
||||
logoAndTitlePanel = new LogoAndTitlePanel(leaderboardGroupName, leaderboardDisplayName, getStringMessages(), this, getUserService());
|
||||
logoAndTitlePanel.addStyleName("LogoAndTitlePanel");
|
||||
mainPanel.addNorth(logoAndTitlePanel, 68);
|
||||
}
|
||||
|
||||
tvViewController = new TVViewController(sailingService, mediaService, getUserService(), getStringMessages(),
|
||||
this, leaderboardGroupName, leaderboardName, userAgent, logoAndTitlePanel, mainPanel,
|
||||
delayToLiveMillis, showRaceDetails, raceboardViewConfig);
|
||||
tvViewController.updateTvView(TVViews.Leaderboard);
|
||||
}
|
||||
}
|
||||
-276
@@ -1,276 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.tv;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.dom.client.Style.Unit;
|
||||
import com.google.gwt.user.client.ui.DockLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.dto.FleetDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
|
||||
import com.sap.sailing.gwt.ui.client.MediaServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel;
|
||||
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
|
||||
import com.sap.sse.gwt.client.player.Timer;
|
||||
import com.sap.sse.gwt.client.player.Timer.PlayModes;
|
||||
import com.sap.sse.gwt.client.useragent.UserAgentDetails;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
|
||||
public class TVViewController implements RaceTimesInfoProviderListener {
|
||||
private static final int REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD = 10000;
|
||||
private static final long REFRESH_INTERVAL_IN_MILLIS_RACEBOARD = 1000;
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final MediaServiceAsync mediaService;
|
||||
private final StringMessages stringMessages;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final UserAgentDetails userAgent;
|
||||
private final LogoAndTitlePanel logoAndTitlePanel;
|
||||
private final DockLayoutPanel dockPanel;
|
||||
private final AsyncActionsExecutor asyncActionsExecutor;
|
||||
|
||||
/**
|
||||
* We use two timers: one for the leaderboard, one for the race board. This way, we can stop one while the other continues.
|
||||
* This way, the other component stops its auto-updates.
|
||||
*/
|
||||
private final Timer leaderboardTimer;
|
||||
private final Timer raceboardTimer;
|
||||
private final RaceTimesInfoProvider raceTimesInfoProvider;
|
||||
private TVViews activeTvView;
|
||||
|
||||
// leaderboard related attributes
|
||||
private LeaderboardDTO leaderboard;
|
||||
private final String leaderboardName;
|
||||
private final String leaderboardGroupName;
|
||||
private LeaderboardSettings leaderboardSettings;
|
||||
|
||||
// raceboard related attributes
|
||||
private RegattaAndRaceIdentifier currentLiveRace;
|
||||
private boolean showRaceDetails;
|
||||
private boolean showWindChart;
|
||||
private final RaceBoardViewConfiguration raceboardViewConfig;
|
||||
private final UserService userService;
|
||||
|
||||
/**
|
||||
* @param userService TODO
|
||||
* @param logoAndTitlePanel
|
||||
* allowed to be <code>null</code>
|
||||
* @param showNavigationPanel
|
||||
* tells whether to show the navigation panel for the race board which allows users to turn on and off
|
||||
* the various components and lets them configure them; makes sense to use only if intended for "manned" mode.
|
||||
*/
|
||||
public TVViewController(SailingServiceAsync sailingService, MediaServiceAsync mediaService,
|
||||
UserService userService, StringMessages stringMessages, ErrorReporter errorReporter,
|
||||
String leaderboardGroupName, String leaderboardName, UserAgentDetails userAgent,
|
||||
LogoAndTitlePanel logoAndTitlePanel, DockLayoutPanel dockPanel, long delayToLiveInMillis,
|
||||
boolean showRaceDetails, RaceBoardViewConfiguration raceboardViewConfig) {
|
||||
this.userService = userService;
|
||||
this.raceboardViewConfig = raceboardViewConfig;
|
||||
this.sailingService = sailingService;
|
||||
this.mediaService = mediaService;
|
||||
this.stringMessages = stringMessages;
|
||||
this.errorReporter = errorReporter;
|
||||
this.leaderboardName = leaderboardName;
|
||||
this.leaderboardGroupName = leaderboardGroupName;
|
||||
this.userAgent = userAgent;
|
||||
this.logoAndTitlePanel = logoAndTitlePanel;
|
||||
this.dockPanel = dockPanel;
|
||||
this.showRaceDetails = showRaceDetails;
|
||||
|
||||
asyncActionsExecutor = new AsyncActionsExecutor();
|
||||
showWindChart = false;
|
||||
leaderboard = null;
|
||||
leaderboardSettings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(null, null, null, /* autoExpandFirstRace */ false, /* showRegattaRank */ true);
|
||||
|
||||
leaderboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
|
||||
leaderboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
|
||||
leaderboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_LEADERBOARD);
|
||||
leaderboardTimer.play();
|
||||
raceboardTimer = new Timer(PlayModes.Live, /* delayBetweenAutoAdvancesInMilliseconds */1000l);
|
||||
raceboardTimer.setLivePlayDelayInMillis(delayToLiveInMillis);
|
||||
raceboardTimer.setRefreshInterval(REFRESH_INTERVAL_IN_MILLIS_RACEBOARD);
|
||||
raceboardTimer.play();
|
||||
|
||||
raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, errorReporter, new ArrayList<RegattaAndRaceIdentifier>(), 3000l);
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(this);
|
||||
}
|
||||
|
||||
private LeaderboardPanel createLeaderboardPanel(String leaderboardGroupName, String leaderboardName, boolean showRaceDetails) {
|
||||
CompetitorSelectionModel selectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true);
|
||||
LeaderboardPanel leaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor,
|
||||
leaderboardSettings, false,
|
||||
/* preSelectedRace */null, selectionModel, leaderboardTimer, leaderboardGroupName, leaderboardName,
|
||||
errorReporter, stringMessages, userAgent, showRaceDetails, /* competitorSearchTextBox */ null, /* showRegattaRank */
|
||||
/* showSelectionCheckbox */false, /* raceTimesInfoProvider */null, false, /* autoExpandLastRaceColumn */
|
||||
/* adjustTimerDelay */true, /*autoApplyTopNFilter*/ false, false) {
|
||||
@Override
|
||||
protected void setLeaderboard(LeaderboardDTO leaderboard) {
|
||||
super.setLeaderboard(leaderboard);
|
||||
TVViewController.this.leaderboard = leaderboard;
|
||||
updateRaceTimesInfoProvider();
|
||||
}
|
||||
};
|
||||
leaderboardPanel.getElement().getStyle().setMargin(5, Unit.PX);
|
||||
return leaderboardPanel;
|
||||
}
|
||||
|
||||
private void updateRaceTimesInfoProvider() {
|
||||
boolean addedRaces = false;
|
||||
for (RaceColumnDTO race : leaderboard.getRaceList()) {
|
||||
for (FleetDTO fleet : race.getFleets()) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
|
||||
if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) {
|
||||
raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false);
|
||||
addedRaces = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addedRaces) {
|
||||
raceTimesInfoProvider.forceTimesInfosUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private RaceBoardPanel createRaceBoardPanel(String leaderboardName, RegattaAndRaceIdentifier raceToShow) {
|
||||
RaceSelectionModel raceSelectionModel = new RaceSelectionModel();
|
||||
List<RegattaAndRaceIdentifier> singletonList = Collections.singletonList(raceToShow);
|
||||
raceSelectionModel.setSelection(singletonList);
|
||||
RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, userService,
|
||||
asyncActionsExecutor, raceboardTimer, raceSelectionModel, leaderboardName, null, /* event */null,
|
||||
raceboardViewConfig, errorReporter, stringMessages, userAgent, raceTimesInfoProvider, /* showMapControls */false);
|
||||
return raceBoardPanel;
|
||||
}
|
||||
|
||||
private void clearContentPanels() {
|
||||
int childWidgetCount = dockPanel.getWidgetCount();
|
||||
for(int i = childWidgetCount-1; i >=0; i--) {
|
||||
Widget widget = dockPanel.getWidget(i);
|
||||
// don't remove the logoAndTitlePanel if exist
|
||||
if(logoAndTitlePanel == null || widget != logoAndTitlePanel) {
|
||||
dockPanel.remove(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showLeaderboard() {
|
||||
if (activeTvView != TVViews.Leaderboard) {
|
||||
clearContentPanels();
|
||||
LeaderboardPanel leaderboardPanel = createLeaderboardPanel(leaderboardGroupName, leaderboardName, showRaceDetails);
|
||||
ScrollPanel leaderboardContentPanel = new ScrollPanel();
|
||||
leaderboardContentPanel.add(leaderboardPanel);
|
||||
dockPanel.add(leaderboardContentPanel);
|
||||
if (logoAndTitlePanel != null) {
|
||||
logoAndTitlePanel.setSubTitle(leaderboardName);
|
||||
}
|
||||
currentLiveRace = null;
|
||||
activeTvView = TVViews.Leaderboard;
|
||||
raceboardTimer.pause();
|
||||
leaderboardTimer.setPlayMode(PlayModes.Live);
|
||||
}
|
||||
}
|
||||
|
||||
private void showRaceBoard() {
|
||||
if (activeTvView != TVViews.Raceboard) {
|
||||
clearContentPanels();
|
||||
RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace);
|
||||
raceBoardPanel.setSize("100%", "100%");
|
||||
if (showWindChart) {
|
||||
raceBoardPanel.setWindChartVisible(true);
|
||||
}
|
||||
FlowPanel timePanel = createTimePanel(raceBoardPanel);
|
||||
dockPanel.addSouth(timePanel, 90);
|
||||
dockPanel.add(raceBoardPanel);
|
||||
if (logoAndTitlePanel != null) {
|
||||
logoAndTitlePanel.setSubTitle(currentLiveRace.getRaceName());
|
||||
}
|
||||
activeTvView = TVViews.Raceboard;
|
||||
leaderboardTimer.pause();
|
||||
raceboardTimer.setPlayMode(PlayModes.Live);
|
||||
}
|
||||
}
|
||||
|
||||
private FlowPanel createTimePanel(RaceBoardPanel raceBoardPanel) {
|
||||
FlowPanel timeLineInnerBgPanel = new FlowPanel();
|
||||
timeLineInnerBgPanel.addStyleName("timeLineInnerBgPanel");
|
||||
timeLineInnerBgPanel.add(raceBoardPanel.getTimePanel());
|
||||
|
||||
FlowPanel timeLineInnerPanel = new FlowPanel();
|
||||
timeLineInnerPanel.add(timeLineInnerBgPanel);
|
||||
timeLineInnerPanel.addStyleName("timeLineInnerPanel");
|
||||
|
||||
FlowPanel timelinePanel = new FlowPanel();
|
||||
timelinePanel.add(timeLineInnerPanel);
|
||||
timelinePanel.addStyleName("timeLinePanel");
|
||||
|
||||
return timelinePanel;
|
||||
}
|
||||
|
||||
public void updateTvView(TVViews tvView) {
|
||||
switch (tvView) {
|
||||
case Leaderboard:
|
||||
showLeaderboard();
|
||||
break;
|
||||
case Raceboard:
|
||||
showRaceBoard();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfo, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
|
||||
raceboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
|
||||
leaderboardTimer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
|
||||
if (currentLiveRace != null) {
|
||||
RaceTimesInfoDTO currentRaceTimes = raceTimesInfo.get(currentLiveRace);
|
||||
|
||||
Date endOfRace = currentRaceTimes.endOfRace;
|
||||
long waitTimeAfterEndOfRace = 60 * 1000; // 1 min
|
||||
if (endOfRace != null && raceboardTimer.getTime().getTime() > endOfRace.getTime() + waitTimeAfterEndOfRace
|
||||
&& raceboardTimer.getPlayMode() == PlayModes.Live) {
|
||||
updateTvView(TVViews.Leaderboard);
|
||||
}
|
||||
} else {
|
||||
currentLiveRace = checkForLiveRace();
|
||||
if (currentLiveRace != null) {
|
||||
updateTvView(TVViews.Raceboard);
|
||||
} else {
|
||||
updateTvView(TVViews.Leaderboard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RegattaAndRaceIdentifier checkForLiveRace() {
|
||||
RegattaAndRaceIdentifier result = null;
|
||||
Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos = raceTimesInfoProvider.getRaceTimesInfos();
|
||||
for (RaceColumnDTO race : leaderboard.getRaceList()) {
|
||||
for (FleetDTO fleet : race.getFleets()) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleet);
|
||||
if (raceIdentifier != null) {
|
||||
RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier);
|
||||
if (raceTimes != null && raceTimes.startOfTracking != null && raceTimes.endOfRace == null) {
|
||||
return raceIdentifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.tv;
|
||||
|
||||
public enum TVViews {
|
||||
Leaderboard, Raceboard;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
<?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'/>
|
||||
|
||||
<stylesheet src="../AdminConsole.css" />
|
||||
|
||||
<!-- Highcharts API -->
|
||||
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
|
||||
|
||||
<!-- Google Maps API -->
|
||||
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
|
||||
<inherits name='com.google.gwt.maps.Maps' />
|
||||
|
||||
<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.sse.SSECommon" />
|
||||
<inherits name="com.sap.sse.security.ui.LoginPanel" />
|
||||
<inherits name="com.sap.sailing.domain.SailingDomain" />
|
||||
|
||||
<!-- 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' />
|
||||
|
||||
<!-- Fancy Progressbar (without the rest of Bootstrap!) -->
|
||||
<!-- GWT-Bootstrap License: Apache License, Version 2.0 -->
|
||||
<stylesheet src="../AdminConsoleDateTimePicker.css" />
|
||||
<stylesheet src="../AdminConsoleProgressBar.css" />
|
||||
|
||||
<super-source path="jre" />
|
||||
|
||||
<entry-point class='com.sap.sailing.gwt.ui.client.search.SearchEntryPoint'/>
|
||||
|
||||
<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" />
|
||||
|
||||
<extend-property name="locale" values="de"/>
|
||||
<extend-property name="locale" values="ru"/>
|
||||
|
||||
<source path='common'/>
|
||||
<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>
|
||||
@@ -1,50 +0,0 @@
|
||||
<?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'/>
|
||||
|
||||
<stylesheet src="../Leaderboard.css" />
|
||||
<stylesheet src="../RaceBoard.css" />
|
||||
|
||||
<!-- Other module inherits -->
|
||||
<inherits name="com.sap.sailing.gwt.ui.EmulatedJRE" />
|
||||
<inherits name="com.sap.sse.gwt.SSESharedGWT" />
|
||||
<inherits name="com.sap.sse.SSECommon" />
|
||||
<inherits name="com.sap.sailing.domain.SailingDomain" />
|
||||
<inherits name="com.sap.sse.security.ui.LoginPanel" />
|
||||
|
||||
<!-- Highcharts API -->
|
||||
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
|
||||
|
||||
<!-- Google Maps API -->
|
||||
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
|
||||
<inherits name='com.google.gwt.maps.Maps' />
|
||||
|
||||
<!-- Bootstrap API -->
|
||||
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
|
||||
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
|
||||
|
||||
<!-- 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"/>
|
||||
<extend-property name="locale" values="ru"/>
|
||||
|
||||
<source path='common'/>
|
||||
<source path='client'/>
|
||||
<source path='tv'/>
|
||||
<source path='leaderboard'/>
|
||||
<source path='raceboard'/>
|
||||
<source path='adminconsole'/>
|
||||
<source path='usermanagement'/>
|
||||
<source path='shared'/>
|
||||
<source path='actions'/>
|
||||
<source path='masterdataimport'/>
|
||||
<source path='simulator'/>
|
||||
</module>
|
||||
+14
-25
@@ -9,16 +9,13 @@ import org.openqa.selenium.WebElement;
|
||||
|
||||
import com.sap.sailing.selenium.core.BySeleniumId;
|
||||
import com.sap.sailing.selenium.core.FindBy;
|
||||
|
||||
import com.sap.sailing.selenium.pages.PageArea;
|
||||
|
||||
import com.sap.sailing.selenium.pages.adminconsole.ActionsHelper;
|
||||
|
||||
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor;
|
||||
|
||||
import com.sap.sailing.selenium.pages.gwt.CellTablePO;
|
||||
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
|
||||
import com.sap.sailing.selenium.pages.gwt.GenericCellTablePO;
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class LeaderboardDetailsPanelPO extends PageArea {
|
||||
public static class RaceDescriptor {
|
||||
@@ -124,22 +121,22 @@ public class LeaderboardDetailsPanelPO extends PageArea {
|
||||
|
||||
public List<RaceDescriptor> getRaces() {
|
||||
List<RaceDescriptor> result = new ArrayList<>();
|
||||
|
||||
CellTablePO<DataEntryPO> racesTable = getRacesTable();
|
||||
|
||||
for(DataEntryPO entry : racesTable.getEntries()) {
|
||||
String name = entry.getColumnContent("Race");
|
||||
String fleet = entry.getColumnContent("Fleet");
|
||||
//String medalRace = entry.getColumnContent("Medal Race");
|
||||
//String linked = entry.getColumnContent("Is linked");
|
||||
//String factor = entry.getColumnContent("Factor");
|
||||
|
||||
result.add(new RaceDescriptor(name, fleet, false, false, 0.0));
|
||||
result.add(createRaceDescriptor(entry));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private RaceDescriptor createRaceDescriptor(DataEntryPO entry) {
|
||||
String name = entry.getColumnContent("Race");
|
||||
String fleet = entry.getColumnContent("Fleet");
|
||||
String medalRace = entry.getColumnContent("Medal Race");
|
||||
String linked = entry.getColumnContent("Is linked");
|
||||
String factorColumnContent = entry.getColumnContent("Factor");
|
||||
double factor = factorColumnContent.trim().isEmpty() ? 0.0 : Double.valueOf(factorColumnContent);
|
||||
return new RaceDescriptor(name, fleet, Util.equalsWithNull("x", medalRace), Util.equalsWithNull("Yes", linked), factor);
|
||||
}
|
||||
|
||||
|
||||
// public RaceEditDialog editRace(RaceDescriptor race) {
|
||||
@@ -183,20 +180,12 @@ public class LeaderboardDetailsPanelPO extends PageArea {
|
||||
|
||||
private DataEntryPO findRace(RaceDescriptor race) {
|
||||
CellTablePO<DataEntryPO> racesTable = getRacesTable();
|
||||
|
||||
for(DataEntryPO entry : racesTable.getEntries()) {
|
||||
String name = entry.getColumnContent("Race");
|
||||
String fleet = entry.getColumnContent("Fleet");
|
||||
//String medalRace = entry.getColumnContent("Medal Race");
|
||||
//String linked = entry.getColumnContent("Is linked");
|
||||
//String factor = entry.getColumnContent("Factor");
|
||||
|
||||
RaceDescriptor descriptor = new RaceDescriptor(name, fleet, false, false, 0.0);
|
||||
|
||||
if(descriptor.equals(race))
|
||||
RaceDescriptor descriptor = createRaceDescriptor(entry);
|
||||
if (descriptor.equals(race)) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+1
-15
@@ -249,11 +249,8 @@ public class TrackedRacesListPO extends PageArea {
|
||||
|
||||
public void stopTracking(List<TrackedRaceDescriptor> races, boolean waitForFinished) {
|
||||
selectRaces(races);
|
||||
|
||||
this.stopTrackingButton.click();
|
||||
|
||||
waitForAjaxRequests();
|
||||
|
||||
if(waitForFinished) {
|
||||
waitForTrackedRaces(races, Status.FINISHED);
|
||||
}
|
||||
@@ -292,18 +289,7 @@ public class TrackedRacesListPO extends PageArea {
|
||||
}
|
||||
|
||||
private void selectRaces(List<TrackedRaceDescriptor> races) {
|
||||
List<DataEntryPO> trackedRaces = getTrackedRaces(races);
|
||||
Iterator<DataEntryPO> iterator = trackedRaces.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
DataEntryPO trackedRace = iterator.next();
|
||||
|
||||
if(trackedRace == null) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
CellTablePO<DataEntryPO> table = getTrackedRacesTable();
|
||||
table.selectEntries(trackedRaces);
|
||||
table.selectEntries(() -> getTrackedRaces(races).stream().filter(tr -> tr != null));
|
||||
}
|
||||
}
|
||||
+4
-16
@@ -2,7 +2,6 @@ package com.sap.sailing.selenium.pages.adminconsole.tractrac;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -15,13 +14,13 @@ import org.openqa.selenium.support.ui.ExpectedCondition;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
|
||||
import com.sap.sailing.selenium.core.FindBy;
|
||||
import com.sap.sailing.selenium.core.BySeleniumId;
|
||||
import com.sap.sailing.selenium.core.FindBy;
|
||||
import com.sap.sailing.selenium.pages.PageArea;
|
||||
import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor;
|
||||
import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO;
|
||||
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
|
||||
import com.sap.sailing.selenium.pages.gwt.CellTablePO;
|
||||
import com.sap.sailing.selenium.pages.gwt.DataEntryPO;
|
||||
import com.sap.sailing.selenium.pages.gwt.GenericCellTablePO;
|
||||
|
||||
/**
|
||||
@@ -235,19 +234,8 @@ public class TracTracEventManagementPanelPO extends PageArea {
|
||||
|
||||
public void startTrackingForRaces(List<TrackableRaceDescriptor> races) {
|
||||
CellTablePO<DataEntryPO> table = getTrackableRacesTable();
|
||||
List<DataEntryPO> entries = table.getEntries();
|
||||
Iterator<DataEntryPO> iterator = entries.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
DataEntryPO entry = iterator.next();
|
||||
String event = entry.getColumnContent("Event");
|
||||
String race = entry.getColumnContent("Race");
|
||||
String boatClass = entry.getColumnContent("Boat Class");
|
||||
TrackableRaceDescriptor descriptor = new TrackableRaceDescriptor(event, race, boatClass);
|
||||
if (!races.contains(descriptor)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
table.selectEntries(entries);
|
||||
table.selectEntries(() -> table.getEntries().stream().filter(e -> races.contains(
|
||||
new TrackableRaceDescriptor(e.getColumnContent("Event"), e.getColumnContent("Race"), e.getColumnContent("Boat Class")))));
|
||||
this.startTrackingButton.click();
|
||||
ExpectedCondition<Alert> condition = ExpectedConditions.alertIsPresent();
|
||||
if (condition.apply(this.driver) == null) {
|
||||
|
||||
+7
-7
@@ -4,6 +4,8 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
@@ -226,22 +228,20 @@ public abstract class CellTablePO<T extends DataEntryPO> extends PageArea {
|
||||
* <p>Selects the specified entries.</p>
|
||||
*
|
||||
* <p>Note: If an entry is not contained in the table it will not be selected.</p>
|
||||
*
|
||||
* @param entries
|
||||
* The entries to select.
|
||||
* @param entryFetcher
|
||||
* The provider to use to obtain the table entries to select
|
||||
*/
|
||||
public void selectEntries(List<T> entries) {
|
||||
public void selectEntries(Supplier<Stream<T>> entryFetcher) {
|
||||
// First deselect all selected entries
|
||||
for (T entry : getSelectedEntries()) {
|
||||
entry.deselect();
|
||||
}
|
||||
|
||||
// Select all specified entries
|
||||
for (T entry : entries) {
|
||||
entryFetcher.get().forEach(entry -> {
|
||||
if (this.getWebElement().equals(entry.table.getWebElement())) {
|
||||
entry.appendToSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-2
@@ -96,7 +96,7 @@ public class DataEntryPO extends CellTableRowPO {
|
||||
* @return
|
||||
* The element on which to click to select or deselect the data entry in the table.
|
||||
*/
|
||||
protected WebElement getElementForSelect() {
|
||||
private WebElement getElementForSelect() {
|
||||
final int columnToUseForSelection;
|
||||
if (this.columns.size() > 1) {
|
||||
// could be a selection checkbox column in the first column, so use second column to be on the safe side:
|
||||
@@ -109,11 +109,16 @@ public class DataEntryPO extends CellTableRowPO {
|
||||
|
||||
protected Action getModifiedSelectAction() {
|
||||
Actions actions = new Actions(this.driver);
|
||||
if (table.getColumnHeaders().get(0).equals("\u2713")) {
|
||||
// it's a checkbox column
|
||||
actions.moveToElement(this.columns.isEmpty() ? getWebElement() : this.columns.get(0));
|
||||
actions.click();
|
||||
} else {
|
||||
actions.keyDown(Keys.CONTROL);
|
||||
actions.moveToElement(getElementForSelect(), 1, 1);
|
||||
actions.click();
|
||||
actions.keyUp(Keys.CONTROL);
|
||||
|
||||
}
|
||||
return actions.build();
|
||||
}
|
||||
|
||||
|
||||
+44
-4
@@ -1,7 +1,10 @@
|
||||
package com.sap.sailing.selenium.test.leaderboard;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -82,6 +85,34 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
} while (stateHasChanged);
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 2425, comments 5, 6 and 7. This is testing that the leaderboard panel receives a refresh when shown.
|
||||
*/
|
||||
@Test
|
||||
public void testLeaderboardPanelRefresh() {
|
||||
// Open the admin console
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
// Remove the tracked race, expecting the column in the leaderboard configuration page to show linked=No after the refresh
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.getTrackedRacesList().remove(trackedRace);
|
||||
{
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
final List<RaceDescriptor> races = leaderboardDetails.getRaces();
|
||||
assertEquals(1, races.size());
|
||||
assertFalse(races.iterator().next().isLinked()); // removing the race must make the race column unlinked.
|
||||
}
|
||||
// now back to the TracTrac management panel, load the race again and make sure it is auto-linked to the column
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole);
|
||||
{
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
LeaderboardDetailsPanelPO details = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
final List<RaceDescriptor> races = details.getRaces();
|
||||
assertEquals(1, races.size());
|
||||
assertTrue(races.iterator().next().isLinked()); // removing the race must make the race column unlinked.
|
||||
}
|
||||
}
|
||||
|
||||
private void configureLeaderboard() {
|
||||
// Open the admin console for some configuration steps
|
||||
AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot());
|
||||
@@ -93,6 +124,17 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
seriesDialog.addRaces(1, 1);
|
||||
seriesDialog.pressOk();
|
||||
// Start the tracking for the races and wait until they are ready to use
|
||||
startTrackingRaceAndStopWhenFinished(adminConsole);
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
leaderboardConfiguration.createRegattaLeaderboard(this.regatta);
|
||||
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
leaderboardDetails.linkRace(this.raceColumn, this.trackedRace);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param adminConsole
|
||||
*/
|
||||
private void startTrackingRaceAndStopWhenFinished(AdminConsolePage adminConsole) {
|
||||
TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents();
|
||||
tracTracEvents.listTrackableRaces(KIELER_WOCHE_2013_JSON_URL);
|
||||
tracTracEvents.setReggataForTracking(this.regatta);
|
||||
@@ -101,9 +143,7 @@ public class TestColumnsInLeaderboard extends AbstractSeleniumTest {
|
||||
TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList();
|
||||
trackedRacesList.waitForTrackedRace(this.trackedRace, Status.FINISHED); // TracAPI puts REPLAY races into FINISHED mode when done loading
|
||||
trackedRacesList.stopTracking(this.trackedRace);
|
||||
LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration();
|
||||
leaderboardConfiguration.createRegattaLeaderboard(this.regatta);
|
||||
LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD);
|
||||
leaderboardDetails.linkRace(this.raceColumn, this.trackedRace);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,10 +8,10 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Fragment-Host: com.sap.sailing.server.gateway.serialization
|
||||
Require-Bundle: com.sap.sailing.domain;bundle-version="1.0.0",
|
||||
com.sap.sailing.domain.common;bundle-version="1.0.0",
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.junit4;bundle-version="4.8.2",
|
||||
com.sap.sailing.domain.shared.android,
|
||||
org.json.simple,
|
||||
org.mockito.mockito-core;bundle-version="1.9.5",
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.objenesis;bundle-version="1.3.0",
|
||||
com.sap.sse.common
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.sap.sailing.server.gateway.serialization.test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.simple.JSONValue;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest {
|
||||
@Test
|
||||
public void deserialize() throws JsonDeserializationException, ParseException {
|
||||
String json = "{\n" +
|
||||
" \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" +
|
||||
" \"fixes\" : [\n" +
|
||||
" {\n" +
|
||||
" \"timestamp\" : 14144160080000,\n" +
|
||||
" \"latitude\" : 54.325246,\n" +
|
||||
" \"longitude\" : 10.148556,\n" +
|
||||
" \"speed\" : 3.61,\n" +
|
||||
" \"course\" : 258.11,\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"timestamp\" : 14144168490000,\n" +
|
||||
" \"latitude\" : 55.12456,\n" +
|
||||
" \"longitude\" : 8.03456,\n" +
|
||||
" \"speed\" : 5.1,\n" +
|
||||
" \"course\" : 14.2,\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> deserializer =
|
||||
new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer();
|
||||
|
||||
Pair<UUID, List<GPSFixMoving>> result =
|
||||
deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json)));
|
||||
assertThat("uuid", result.getA(), equalTo(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf")));
|
||||
assertThat("number of fixes", result.getB().size(), equalTo(2));
|
||||
}
|
||||
}
|
||||
+27
-15
@@ -1,7 +1,10 @@
|
||||
package com.sap.sailing.server.gateway.deserialization.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.MeterPerSecondSpeedImpl;
|
||||
@@ -12,29 +15,38 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
/**
|
||||
* Make serialization on the smartphone easier by providing a flat structure rather
|
||||
* than nested JSON documents.
|
||||
* Make serialization on the smartphone easier by providing a flat structure rather than nested JSON documents.
|
||||
*
|
||||
* @author Fredrik Teschke
|
||||
*
|
||||
*/
|
||||
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements JsonDeserializer<Pair<UUID, GPSFixMoving>> {
|
||||
public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements
|
||||
JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> {
|
||||
public static final String DEVICE_UUID = "deviceUuid";
|
||||
public static final String LON_DEG = "lonDeg";
|
||||
public static final String LAT_DEG = "latDeg";
|
||||
public static final String TIME_MILLIS = "timeMillis";
|
||||
public static final String SPEED_M_PER_S = "speedMperS";
|
||||
public static final String BEARING_DEG = "bearingDeg";
|
||||
public static final String FIXES = "fixes";
|
||||
public static final String LON_DEG = "longitude";
|
||||
public static final String LAT_DEG = "latitude";
|
||||
public static final String TIME_MILLIS = "timestamp";
|
||||
public static final String SPEED_M_PER_S = "speed";
|
||||
public static final String BEARING_DEG = "course";
|
||||
|
||||
@Override
|
||||
public Pair<UUID, GPSFixMoving> deserialize(JSONObject object) throws JsonDeserializationException {
|
||||
public Pair<UUID, List<GPSFixMoving>> deserialize(JSONObject object) throws JsonDeserializationException {
|
||||
UUID device = UUID.fromString(object.get(DEVICE_UUID).toString());
|
||||
double lonDeg = Double.parseDouble(object.get(LON_DEG).toString());
|
||||
double latDeg = Double.parseDouble(object.get(LAT_DEG).toString());
|
||||
long timeMillis = Long.parseLong(object.get(TIME_MILLIS).toString());
|
||||
double speedMperS = Double.parseDouble(object.get(SPEED_M_PER_S).toString());
|
||||
JSONArray jsonFixes = Helpers.getNestedArraySafe(object, FIXES);
|
||||
List<GPSFixMoving> fixes = new ArrayList<GPSFixMoving>();
|
||||
for (int i = 0; i < jsonFixes.size(); i++) {
|
||||
JSONObject fixObject = Helpers.toJSONObjectSafe(jsonFixes.get(i));
|
||||
double lonDeg = Double.parseDouble(fixObject.get(LON_DEG).toString());
|
||||
double latDeg = Double.parseDouble(fixObject.get(LAT_DEG).toString());
|
||||
long timeMillis = Long.parseLong(fixObject.get(TIME_MILLIS).toString());
|
||||
double speedMperS = Double.parseDouble(fixObject.get(SPEED_M_PER_S).toString());
|
||||
double speedKnots = new MeterPerSecondSpeedImpl(speedMperS).getKnots();
|
||||
double bearingDeg = Double.parseDouble(object.get(BEARING_DEG).toString());
|
||||
double bearingDeg = Double.parseDouble(fixObject.get(BEARING_DEG).toString());
|
||||
GPSFixMoving fix = GPSFixMovingImpl.create(lonDeg, latDeg, timeMillis, speedKnots, bearingDeg);
|
||||
return new Pair<UUID, GPSFixMoving>(device, fix);
|
||||
fixes.add(fix);
|
||||
}
|
||||
|
||||
return new Pair<UUID, List<GPSFixMoving>>(device, fixes);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package com.sap.sailing.server.gateway.test.jaxrs;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneUuidServiceFinderFactory;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.gateway.jaxrs.api.GPSFixesResource;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
|
||||
public class GPSFixesResourceTest {
|
||||
private RacingEventService service;
|
||||
@Before
|
||||
public void setup() {
|
||||
service = new RacingEventServiceImpl(true, new MockSmartphoneUuidServiceFinderFactory());
|
||||
service.getMongoObjectFactory().getDatabase().dropDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deserialize() throws ParseException, TransformationException, NoCorrespondingServiceRegisteredException {
|
||||
String json = "{\n" +
|
||||
" \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" +
|
||||
" \"fixes\" : [\n" +
|
||||
" {\n" +
|
||||
" \"timestamp\" : 14144160080000,\n" +
|
||||
" \"latitude\" : 54.325246,\n" +
|
||||
" \"longitude\" : 10.148556,\n" +
|
||||
" \"speed\" : 3.61,\n" +
|
||||
" \"course\" : 258.11,\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"timestamp\" : 14144168490000,\n" +
|
||||
" \"latitude\" : 55.12456,\n" +
|
||||
" \"longitude\" : 8.03456,\n" +
|
||||
" \"speed\" : 5.1,\n" +
|
||||
" \"course\" : 14.2,\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
GPSFixesResource resource = new GPSFixesResource() {
|
||||
public RacingEventService getService() {
|
||||
return service;
|
||||
};
|
||||
};
|
||||
Response response = resource.postFixes(json);
|
||||
assertThat("response is ok", response.getStatus(), equalTo(Response.Status.OK.getStatusCode()));
|
||||
|
||||
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf"));
|
||||
assertThat("all fixes stored", service.getGPSFixStore().getNumberOfFixes(device), equalTo(2L));
|
||||
}
|
||||
}
|
||||
+19
-8
@@ -25,6 +25,7 @@ import com.sap.sailing.domain.base.racegroup.impl.RaceGroupImpl;
|
||||
import com.sap.sailing.domain.base.racegroup.impl.RaceRowImpl;
|
||||
import com.sap.sailing.domain.base.racegroup.impl.SeriesWithRowsImpl;
|
||||
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
|
||||
@@ -34,23 +35,33 @@ import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
public class RaceGroupFactory {
|
||||
|
||||
/**
|
||||
* Convert given {@link Leaderboard} to a {@link RaceGroup}.
|
||||
* Convert given {@link RegattaLeaderboard} to a {@link RaceGroup}.
|
||||
* @param leaderboard to be converted.
|
||||
* @return the {@link RaceGroup}.
|
||||
*/
|
||||
public RaceGroup convert(Leaderboard leaderboard) {
|
||||
public RaceGroup convert(RegattaLeaderboard leaderboard) {
|
||||
String name = leaderboard.getName();
|
||||
CourseArea courseArea = leaderboard.getDefaultCourseArea();
|
||||
Regatta regatta = ((RegattaLeaderboard) leaderboard).getRegatta();
|
||||
|
||||
Iterable<SeriesWithRows> series = getSeries(leaderboard);
|
||||
|
||||
return new RaceGroupImpl(name, regatta.getBoatClass(), courseArea, series,
|
||||
regatta.getRegattaConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert given {@link FlexibleLeaderboard} to a {@link RaceGroup}.
|
||||
* @param leaderboard to be converted.
|
||||
* @return the {@link RaceGroup}.
|
||||
*/
|
||||
public RaceGroup convert(FlexibleLeaderboard leaderboard) {
|
||||
String name = leaderboard.getName();
|
||||
|
||||
CourseArea courseArea = leaderboard.getDefaultCourseArea();
|
||||
BoatClass boatClass = null;
|
||||
RegattaConfiguration configuration = null;
|
||||
|
||||
if (leaderboard instanceof RegattaLeaderboard) {
|
||||
Regatta regatta = ((RegattaLeaderboard) leaderboard).getRegatta();
|
||||
boatClass = regatta.getBoatClass();
|
||||
configuration = regatta.getRegattaConfiguration();
|
||||
}
|
||||
|
||||
Iterable<SeriesWithRows> series = getSeries(leaderboard);
|
||||
|
||||
return new RaceGroupImpl(name, boatClass, courseArea, series, configuration);
|
||||
|
||||
+8
-1
@@ -13,7 +13,9 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.base.CourseArea;
|
||||
import com.sap.sailing.domain.base.racegroup.RaceGroup;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogServletConstants;
|
||||
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.BoatClassJsonSerializer;
|
||||
@@ -66,7 +68,12 @@ public class RaceGroupJsonExportServlet extends AbstractJsonHttpServlet {
|
||||
RaceGroupFactory raceGroupFactory = new RaceGroupFactory();
|
||||
for (Leaderboard leaderboard : getService().getLeaderboards().values()) {
|
||||
if (filterCourseArea.equals(leaderboard.getDefaultCourseArea())) {
|
||||
RaceGroup raceGroup = raceGroupFactory.convert(leaderboard);
|
||||
RaceGroup raceGroup = null;
|
||||
if (leaderboard instanceof RegattaLeaderboard) {
|
||||
raceGroup = raceGroupFactory.convert((RegattaLeaderboard) leaderboard);
|
||||
} else if (leaderboard instanceof FlexibleLeaderboard) {
|
||||
raceGroup = raceGroupFactory.convert((FlexibleLeaderboard) leaderboard);
|
||||
}
|
||||
result.add(serializer.serialize(raceGroup));
|
||||
}
|
||||
}
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.DeviceIdentifier;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.SmartphoneUUIDIdentifierImpl;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.NoCorrespondingServiceRegisteredException;
|
||||
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException;
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
@Path("/v1/gps_fixes")
|
||||
public class GPSFixesResource extends AbstractSailingServerResource {
|
||||
private static final Logger logger = Logger.getLogger(GPSFixesResource.class.getName());
|
||||
private final JsonDeserializer<Pair<UUID, List<GPSFixMoving>>> deserializer =
|
||||
new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer();
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response postFixes(String json) {
|
||||
Pair<UUID, List<GPSFixMoving>> data = null;
|
||||
try {
|
||||
logger.fine("Post issued to " + this.getClass().getName());
|
||||
Object requestBody = JSONValue.parseWithException(json);
|
||||
JSONObject requestObject = Helpers.toJSONObjectSafe(requestBody);
|
||||
logger.fine("JSON requestObject is: " + requestObject.toString());
|
||||
data = deserializer.deserialize(requestObject);
|
||||
} catch (ParseException | JsonDeserializationException e) {
|
||||
logger.warning(String.format("Exception while parsing post request:\n%s", e.toString()));
|
||||
return Response.status(Status.BAD_REQUEST).entity("Invalid JSON body in request").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(data.getA());
|
||||
List<GPSFixMoving> fixes = data.getB();
|
||||
|
||||
try {
|
||||
for (GPSFixMoving fix : fixes) {
|
||||
getService().getGPSFixStore().storeFix(device, fix);
|
||||
}
|
||||
logger.log(Level.INFO, "Added " + fixes.size() + " fixes for device " + device.toString() + " to store");
|
||||
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
|
||||
logger.log(Level.WARNING, "Could not store fix for device " + device);
|
||||
}
|
||||
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ public class RestApiApplication extends Application {
|
||||
classes.add(RegattasResource.class);
|
||||
classes.add(LeaderboardsResource.class);
|
||||
classes.add(SearchResource.class);
|
||||
classes.add(GPSFixesResource.class);
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
+8
-6
@@ -1904,22 +1904,24 @@ public class MasterDataImportTest {
|
||||
raceColumnNames.add("T2");
|
||||
final List<String> emptyRaceColumnNamesList = Collections.emptyList();
|
||||
|
||||
List<Series> series = new ArrayList<Series>();
|
||||
List<Series> seriesOnSource = new ArrayList<>();
|
||||
List<Series> seriesOnTarget = new ArrayList<>();
|
||||
List<Fleet> fleets = new ArrayList<Fleet>();
|
||||
String testFleet1Name = "testFleet1";
|
||||
FleetImpl testFleet1 = new FleetImpl(testFleet1Name);
|
||||
fleets.add(testFleet1);
|
||||
fleets.add(new FleetImpl("testFleet2"));
|
||||
series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService));
|
||||
seriesOnSource.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService));
|
||||
seriesOnTarget.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService));
|
||||
UUID regattaUUID = UUID.randomUUID();
|
||||
Regatta regatta = sourceService.createRegatta(
|
||||
RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, regattaUUID,
|
||||
series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true);
|
||||
seriesOnSource, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true);
|
||||
for (String name : raceColumnNames) {
|
||||
series.get(0).addRaceColumn(name, sourceService);
|
||||
seriesOnSource.get(0).addRaceColumn(name, sourceService);
|
||||
}
|
||||
double factor = 3.0;
|
||||
series.get(0).getRaceColumnByName(raceColumnName).setFactor(factor);
|
||||
seriesOnSource.get(0).getRaceColumnByName(raceColumnName).setFactor(factor);
|
||||
|
||||
int[] discardRule = { 1, 2, 3, 4 };
|
||||
ScoringScheme scoringScheme = new LowPoint();
|
||||
@@ -2044,7 +2046,7 @@ public class MasterDataImportTest {
|
||||
|
||||
Regatta regattaOnTarget = destService.createRegatta(
|
||||
RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, regattaUUID,
|
||||
series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true);
|
||||
seriesOnTarget, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true);
|
||||
|
||||
raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget,
|
||||
new DummyTrackedRace(raceId,
|
||||
|
||||
+1
-1
@@ -1201,7 +1201,7 @@ public class RacingEventServiceImpl implements RacingEventServiceWithTestSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* The regatta and all its contained {@link Regatta#getAllRaces() races} are replicated to all replica.
|
||||
* The regatta and all its contained {@link Regatta#getAllRaces() races} are replicated to all replicas.
|
||||
*
|
||||
* @param regatta
|
||||
* the series of this regatta must not have any {@link Series#getRaceColumns() race columns associated
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.see.common.test</name>
|
||||
<name>com.sap.sse.common.test</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
+25
-11
@@ -18,6 +18,7 @@ import com.google.gwt.user.client.ui.TabLayoutPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.gwt.client.AbstractEntryPoint;
|
||||
import com.sap.sse.gwt.client.BuildVersionRetriever;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
import com.sap.sse.gwt.client.panels.VerticalTabLayoutPanel;
|
||||
import com.sap.sse.security.ui.client.UserService;
|
||||
@@ -32,11 +33,11 @@ import com.sap.sse.security.ui.shared.UserDTO;
|
||||
* tab panel can be added as the content widget of a vertical tab, in turn holding widgets in horizontal tabs.<p>
|
||||
*
|
||||
* After constructing an instance of this class, there are three ways for adding widgets:<ul>
|
||||
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures) adds a widget as a content element
|
||||
* <li>{@link #addToVerticalTabPanel(RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} adds a widget as a content element
|
||||
* of a vertical tab</li>
|
||||
* <li>{@link #addVerticalTab(String, String, AdminConsoleFeatures) creates a horizontal tab panel and adds it as a content element of
|
||||
* <li>{@link #addVerticalTab(String, String, AdminConsoleFeatures)} creates a horizontal tab panel and adds it as a content element of
|
||||
* a vertical tab</li>
|
||||
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures) adds a widget as a content element
|
||||
* <li>{@link #addToTabPanel(TabLayoutPanel, RefreshableAdminConsolePanel, String, AdminConsoleFeatures)} adds a widget as a content element
|
||||
* of a horizontal tab</li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -92,16 +93,15 @@ public class AdminConsolePanel extends DockLayoutPanel {
|
||||
if (source instanceof TabLayoutPanel) {
|
||||
final TabLayoutPanel tabPanel = ((TabLayoutPanel) source);
|
||||
final Widget selectedPanel = tabPanel.getWidget(event.getSelectedItem());
|
||||
refreshDataFor(selectedPanel);
|
||||
refreshDataFor(unwrapScrollPanel(selectedPanel));
|
||||
} else if (source instanceof VerticalTabLayoutPanel) {
|
||||
final VerticalTabLayoutPanel verticalTabLayoutPanel = (VerticalTabLayoutPanel) source;
|
||||
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel
|
||||
.getSelectedIndex());
|
||||
Widget widgetAssociatedToVerticalTab = verticalTabLayoutPanel.getWidget(verticalTabLayoutPanel.getSelectedIndex());
|
||||
if (widgetAssociatedToVerticalTab instanceof TabLayoutPanel) {
|
||||
TabLayoutPanel selectedTabLayoutPanel = (TabLayoutPanel) widgetAssociatedToVerticalTab;
|
||||
final int selectedIndex = selectedTabLayoutPanel.getSelectedIndex();
|
||||
if (selectedIndex >= 0) {
|
||||
widgetAssociatedToVerticalTab = selectedTabLayoutPanel.getWidget(selectedIndex);
|
||||
widgetAssociatedToVerticalTab = unwrapScrollPanel(selectedTabLayoutPanel.getWidget(selectedIndex));
|
||||
}
|
||||
}
|
||||
refreshDataFor(widgetAssociatedToVerticalTab);
|
||||
@@ -109,12 +109,26 @@ public class AdminConsolePanel extends DockLayoutPanel {
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshDataFor(Widget widgetAssociatedToVerticalTab) {
|
||||
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(widgetAssociatedToVerticalTab);
|
||||
private void refreshDataFor(Widget target) {
|
||||
RefreshableAdminConsolePanel refreshTarget = panelsByWidget.get(target);
|
||||
if (refreshTarget != null) {
|
||||
refreshTarget.refreshAfterBecomingVisible();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the <code>widgetMaybeWrappedByScrollPanel</code> is a scroll panel, returns the content widget,
|
||||
* otherwise <code>widgetMaybeWrappedByScrollPanel</code> is returned.
|
||||
*/
|
||||
private Widget unwrapScrollPanel(Widget widgetMaybeWrappedByScrollPanel) {
|
||||
final Widget target;
|
||||
if (widgetMaybeWrappedByScrollPanel instanceof ScrollPanel) {
|
||||
target = ((ScrollPanel) widgetMaybeWrappedByScrollPanel).getWidget();
|
||||
} else {
|
||||
target = widgetMaybeWrappedByScrollPanel;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
public AdminConsolePanel(UserService userService, BuildVersionRetriever buildVersionRetriever,
|
||||
@@ -239,7 +253,7 @@ public class AdminConsolePanel extends DockLayoutPanel {
|
||||
* method can be called.
|
||||
*/
|
||||
private void addToTabPanel(VerticalOrHorizontalTabLayoutPanel tabPanel, RefreshableAdminConsolePanel panelToAdd, String tabTitle, AdminConsoleFeatures feature) {
|
||||
remeberWidgetLocationAndFeature(tabPanel, panelToAdd.getWidget(), tabTitle, feature);
|
||||
remeberWidgetLocationAndFeature(tabPanel, wrapInScrollPanel(panelToAdd.getWidget()), tabTitle, feature);
|
||||
panelsByWidget.put(panelToAdd.getWidget(), panelToAdd);
|
||||
}
|
||||
|
||||
@@ -249,7 +263,7 @@ public class AdminConsolePanel extends DockLayoutPanel {
|
||||
private void remeberWidgetLocationAndFeature(VerticalOrHorizontalTabLayoutPanel tabPanel, Widget widgetToAdd,
|
||||
String tabTitle, AdminConsoleFeatures feature) {
|
||||
roleSpecificTabs.put(new Triple<VerticalOrHorizontalTabLayoutPanel, Widget, String>(tabPanel,
|
||||
wrapInScrollPanel(widgetToAdd), tabTitle), feature);
|
||||
widgetToAdd, tabTitle), feature);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
@@ -5,6 +5,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.gwt.client.BuildVersionRetriever;
|
||||
import com.sap.sse.gwt.client.ErrorReporter;
|
||||
|
||||
public class SystemInformationPanel extends FlowPanel {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.sap.sse.gwt.adminconsole;
|
||||
package com.sap.sse.gwt.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@
|
||||
-Dfile.encoding=cp1252 -Dreplication.brokerURL=tcp://localhost:61615 -Dmongo.dbName=winddbTest -DspatialWind=true
|
||||
</parameters.common>
|
||||
<parameters.vm-settings>
|
||||
-Xmx1024m -XX:PermSize=256m -XX:-UseGCOverheadLimit -XX:+UseParallelGC
|
||||
-ea -Xmx1024m -XX:PermSize=256m -XX:+UseG1GC
|
||||
</parameters.vm-settings>
|
||||
<parameters.tractrac>
|
||||
-Dtractrac.tunnel=true -Dtractrac.tunnel.host=localhost
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# mail configuration, e.g., for password recovery
|
||||
mail.enabled = false
|
||||
# For production:
|
||||
#mail.from = noreply@sapsailing.com
|
||||
mail.from = noreply@sapsailing.com
|
||||
# For testing:
|
||||
mail.from = uhl@homemp3.dyndns.org
|
||||
#mail.from = uhl@homemp3.dyndns.org
|
||||
mail.transport.protocol = smtp
|
||||
# For production:
|
||||
#mail.smtp.host = 127.0.0.1
|
||||
mail.smtp.host = 127.0.0.1
|
||||
# For testing internally:
|
||||
#mail.smtp.host = mail.sap.corp
|
||||
# For testing externally:
|
||||
mail.smtp.host = www.axel-uhl.de
|
||||
#mail.smtp.host = www.axel-uhl.de
|
||||
mail.smtp.port = 25
|
||||
mail.smtp.auth = true
|
||||
mail.smtp.user =
|
||||
|
||||
+11
-6
@@ -2,6 +2,7 @@ package com.sap.sailing.android.tracking.app.services;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@@ -39,7 +40,7 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
|
||||
|
||||
private static final String TAG = TrackingService.class.getName();
|
||||
|
||||
public static final String WEB_SERVICE_PATH = "/tracking/recordFixesFlatJson";
|
||||
public static final String WEB_SERVICE_PATH = "/sailingserver/api/v1/gps_fixes";
|
||||
// Unique Identification Number for the Notification.
|
||||
// We use it on Notification start, and to cancel it.
|
||||
private int NOTIFICATION_ID = R.string.tracker_started;
|
||||
@@ -109,11 +110,15 @@ public class TrackingService extends Service implements ConnectionCallbacks, OnC
|
||||
try {
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.DEVICE_UUID,
|
||||
prefs.getDeviceIdentifier());
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.LAT_DEG, location.getLatitude());
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.LON_DEG, location.getLongitude());
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.TIME_MILLIS, location.getTime());
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.SPEED_M_PER_S, location.getSpeed());
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.BEARING_DEG, location.getBearing());
|
||||
JSONArray fixes = new JSONArray();
|
||||
JSONObject fix = new JSONObject();
|
||||
fix.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.LAT_DEG, location.getLatitude());
|
||||
fix.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.LON_DEG, location.getLongitude());
|
||||
fix.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.TIME_MILLIS, location.getTime());
|
||||
fix.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.SPEED_M_PER_S, location.getSpeed());
|
||||
fix.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.BEARING_DEG, location.getBearing());
|
||||
fixes.put(0, fix);
|
||||
json.put(FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.FIXES, fixes);
|
||||
} catch (JSONException e) {
|
||||
ExLog.e(this, TAG, "Error serializing fix: " + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -225,3 +225,44 @@ After you have setup s3cmd you need to retrieve data from S3.
|
||||
</pre>
|
||||
|
||||
That process can take a while. After it has finished you can proceed with the steps described in "Data has been lost or overwritten (Backup Server is available)"
|
||||
|
||||
## Details about Backups
|
||||
|
||||
In order to give you an overview over how some Backups are configured and stored this section aims to provide some details.
|
||||
|
||||
### Bugzilla
|
||||
|
||||
Bugzilla Database is being stored on the Database server in a MySQL database. The MySQL database contains everything that is needed to restore a Bugzilla that has crashed. The configuration for the backup can be found at `/opt/backup.sh` and consists of the following lines:
|
||||
|
||||
<pre>
|
||||
# Directory for temporary files
|
||||
TARGET_DIR=/var/lib/mysql/backup
|
||||
|
||||
# Configuration for MySQL
|
||||
MYSQL_DATABASES="bugs mysql"
|
||||
MYSQLEXPORT_CMD="mysqldump -u root --password=sailaway"
|
||||
|
||||
[...]
|
||||
|
||||
# Export MySQL dump for selected databases
|
||||
for MYSQL_DB in $MYSQL_DATABASES; do
|
||||
mkdir $TARGET_DIR/mysql
|
||||
echo "$MYSQLEXPORT_CMD $MYSQL_DB > $TARGET_DIR/mysql/$MYSQL_DB.sql"
|
||||
$MYSQLEXPORT_CMD $MYSQL_DB > $TARGET_DIR/mysql/$MYSQL_DB.sql
|
||||
done
|
||||
</pre>
|
||||
|
||||
As one can see a dump is taken for each database specified in the configuration and moved to `/var/lib/mysql/backup/mysql`. This directory is then indexed and pushed to the backup server.
|
||||
|
||||
If you want to check the backup or restore a Bugzilla then use the following steps:
|
||||
|
||||
<pre>
|
||||
[root@ip-172-31-25-136 ~]# su - backup
|
||||
[backup@ip-172-31-25-136 ~]$ /opt/bup/bup -d /home/backup/database/ ls
|
||||
databases dir-etc dir-var-log-mongodb
|
||||
[backup@ip-172-31-25-136 ~]$ /opt/bup/bup -d /home/backup/database/ ls databases/latest/var/lib/mysql/backup/mysql
|
||||
bugs.sql mysql.sql
|
||||
[backup@ip-172-31-25-136 ~]$ /opt/bup/bup -d /home/backup/database/ cat-file databases/latest/var/lib/mysql/backup/mysql/bugs.sql | more
|
||||
</pre>
|
||||
|
||||
Restoring can be performed as described in "Data-has-been-lost-or-overwritten-(Backup-Server-is-available)"
|
||||
+106
-156
@@ -3,186 +3,140 @@
|
||||
## General
|
||||
|
||||
This is a design for the REST API to be used by the iOS and Android tracking apps.
|
||||
We have decided to handle checkins etc. at the level of ``Leaderboard``s instead of ``Regatta``s. For most cases, such a Leaderboard is based on a Regatta (a ``RegattaLeaderboard`` in our domain model).
|
||||
|
||||
This document supplements the [documentation of the existing REST API](http://www.sapsailing.com/sailingserver/webservices/api/v1/index.html), highlighting those resources necessary for the tracking app, and specifying such resources that are not yet present in the API.
|
||||
|
||||
### URL base
|
||||
```
|
||||
http://<host>/sailingserver/api/v1/
|
||||
```
|
||||
All relative URLs given below are relative to this base URL.
|
||||
|
||||
## Push Notifications
|
||||
|
||||
Event data can be updated via push notifications. These are limited on iOS to 256 bytes (not characters). For this reason, on receiving a push notification, the app must GET the event data.
|
||||
|
||||
|
||||
## Checkin Information
|
||||
|
||||
### Path
|
||||
### URL and QRCode
|
||||
|
||||
http://kielerwoche2015.sapsailing.com:8888/api/v1/checkin_info.json?leaderboard={unique_leaderboard_name}&competitor_id={competitor_id}
|
||||
We have the following structure of domain objects (look here for [API documentation](http://www.sapsailing.com/sailingserver/webservices/api/v1/index.html) in addition to the examples):
|
||||
* Event (e.g. [Kieler Woche 2013](http://www.sapsailing.com/sailingserver/api/v1/events/3e4145a7-5473-4670-83e6-fd5ee364f7eb))
|
||||
* LeaderboardGroup (e.g. [Kieler Woche 2013](http://www.sapsailing.com/sailingserver/api/v1/leaderboardgroups/Kieler%20Woche%202013))
|
||||
* Leaderboard (e.g. [KW 2013 Olympic (2.4M)](http://www.sapsailing.com/sailingserver/api/v1/leaderboards/KW%202013%20Olympic%20(2.4M%29))
|
||||
* Race (caution: this is over-simplified)
|
||||
|
||||
### Verb
|
||||
These resources have separate life cycles, the hierarchical presentation only denotes references between the resources (e.g. an Event references some LeaderboardGroups).
|
||||
|
||||
GET
|
||||
The app has to receive the following information:
|
||||
* ``event-id`` (for description, start- and end-date)
|
||||
* ``leaderboard-name`` (so that the user can checkin for the correct leaderboard)
|
||||
* ``competitor-id`` (so the app can register the device for the correct competitor)
|
||||
|
||||
### Response
|
||||
This information is represented in a URL with the following structure:
|
||||
```
|
||||
http://<host>/tracking/checkin
|
||||
?event_id=<event-id>
|
||||
&leaderboard_name=<leaderboard-name>
|
||||
&competitor_id=<competitor-id>
|
||||
```
|
||||
|
||||
**Additional Notes:**
|
||||
* The URL is **only symbolic**. Requesting it will for now result in a 404. In the future, it might be used to redirect to the .apk, play store or app store in case the app is not installed.
|
||||
* The variable-length leaderboard name is problematic when thinking about length restrictions in QRCodes anyway. We will have to think about URL-shortening anyhow, so legible parameter names were chosen instead of short ones (e.g. ``event_id=`` instead of ``e=``)
|
||||
* The app has to get event and competitor data by performing additional REST API calls
|
||||
* The returned JSON-document for an event includes the names of the associated LeaderboardGroups. The JSON for the LeaderboardGroup in turn includes the names of the associated leaderboards. This structure of the returned resources does not follow the [REST constraints](http://en.wikipedia.org/wiki/Representational_state_transfer#Uniform_interface) in the sense that it does not use URIs to refer to associated resources. Instead, only the unique identifier is given, and one has to refer to the API documentation to construct the URI through which the related resource can be addressed.
|
||||
|
||||
### Event Information
|
||||
|
||||
see [events/{event_id}](http://www.sapsailing.com/sailingserver/webservices/api/v1/eventGetDoc.html)
|
||||
|
||||
### Leaderboard Information
|
||||
|
||||
see [leaderboards/{leaderboard_name}](http://www.sapsailing.com/sailingserver/webservices/api/v1/leaderboardGetDoc.html)
|
||||
|
||||
### Competitor Information
|
||||
|
||||
**Path:** ``competitors/{competitor-id}``
|
||||
|
||||
**Verb:** ``GET``
|
||||
|
||||
**Response:**
|
||||
```
|
||||
{
|
||||
"serverUrl" : "http://kielerwoche2015.sapsailing.com:8888",
|
||||
"event" : {
|
||||
"id" : "957fab64e36d240dd07aeed2bd5a84b6",
|
||||
"title" : "Kieler Woche",
|
||||
"startDate" : 1414414481000,
|
||||
"endDate" : 1414609200000
|
||||
},
|
||||
"regatta": {
|
||||
"id": "237fab64e36d240dd07aeed2bd5a8426",
|
||||
"title": "49ers"
|
||||
},
|
||||
"competitor":{
|
||||
"id" : "e45fab64e36d240dd07aeed2bd5a8a21",
|
||||
"name" : "Alster Segel Club",
|
||||
"registration" : "GER 13"
|
||||
}
|
||||
"name": "Heiko KRÖGER",
|
||||
"displayName": "Heiko KRÖGER",
|
||||
"id": "af855a56-9726-4a9c-a77e-da955bd289be",
|
||||
"sailID": "GER 1",
|
||||
"nationality": "GER",
|
||||
"countryCode": "DE"
|
||||
}
|
||||
```
|
||||
|
||||
**Additional Notes:**
|
||||
* The semantics of ``displayName`` are explained in the JavaDoc of ``Leaderboard#getDisplayName()``.
|
||||
* Competitor profile image left out for now.
|
||||
* No flag image included. These images are present on the server in the GWT-context only as 16x11 pngs currently. How flags are displayed in the app should probably be independent. I would suggest resolving the appropriate image within the app based on the ``countryCode``.
|
||||
|
||||
**serverUrl** This is the endpoint to be used for all following REST requests.
|
||||
|
||||
## Check-In
|
||||
|
||||
After the user has received the event data with the short URL, the smartphone is mapped to a competitor.
|
||||
|
||||
Result: fixes transmitted after the time specified in the checkin request are added to such races within the leaderboard that have a start/end time matching the fixes timestamp.
|
||||
|
||||
_Question: What should be done if a second device is mapped to competitor?_
|
||||
* _Answer:_ For now, according to our internal logic, both devices are actually mapped. If they send fixes for the same timerange, we will see some weird behaviour.
|
||||
|
||||
### Path
|
||||
**Path:** ``/leaderboards/{leaderboard-name}/device_mappings/start``
|
||||
|
||||
{serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/competitor/{competitor_id}/checkin.json
|
||||
|
||||
### Verb
|
||||
|
||||
POST
|
||||
|
||||
### Request
|
||||
**Verb:** ``POST``
|
||||
|
||||
**Request:**
|
||||
```
|
||||
{
|
||||
"deviceUdid" : "202cb962ac59075b964b07152d234b70",
|
||||
"competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
|
||||
"deviceType" : "ios",
|
||||
"pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78"
|
||||
"deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
|
||||
"pushDeviceId" : "0f744707bebcf74f9b7c25d48e3358945f6aa01da5ddb387462c7eaf61bbad78",
|
||||
"fromMillis" : 1415624564718
|
||||
}
|
||||
```
|
||||
* **competitorId** ID of the competitor to map the device to. For coming versions, using ``markId`` instead might also be valid to map the device to a mark.
|
||||
* **deviceType**: Either `android` or `ios`. Needed for selecting correct push notification service.
|
||||
* **deviceUuid**: **UUID** generated by the app on first run. **Not** an identifier that globally identifies the piece of hardware such UDID under iOS, IMEI, or other.
|
||||
* **pushDeviceId** On Android the GCM regId, on iOS the APNS push token. This is needed for sending push notifications to the device.
|
||||
* **fromMillis** Milliseconds timestamp from which to map the device to the competitor.
|
||||
|
||||
**deviceUdid** A UDID generated by device, generated on first run.
|
||||
**Response:**
|
||||
``HTTP 200``, no response body
|
||||
|
||||
**deviceType** Either `android` or `ios`. Needed for selecting correct push notification service.
|
||||
|
||||
**pushDeviceId** On Android the GCM regId, on iOS the APNS push token. This is needed for sending push notifications to the device.
|
||||
**Additional Notes:**
|
||||
For future versions, think about whether this is the right place to transmit the data for push notifications. Rather, this should ideally be done when installing the app (or starting it for the first time). Problem is, we don't know which server it will be used with then. So maybe, instead, whenever the user registers for a leaderboard on a _new_ server, the necessary information for push notifications ins transferrend _once_, instead of every time the user registers for a leaderboard on that server.
|
||||
|
||||
## Checkout
|
||||
|
||||
Needed to destroy a device coupling with leaderboard & competitor. AKA checkout.
|
||||
Ends the device to competitor coupling. Does not delete it, but rather marks the end timepoint. Fixes submitted for this device that have a timestamp which lies after the end timepoint specified in the checkout request are not added to races in the leaderboard.
|
||||
|
||||
### Path
|
||||
**Path:** ``/leaderboards/{leaderboard-name}/device_mappings/end``
|
||||
|
||||
{serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/competitor/{competitor_id}/device/{deviceUdid}.json
|
||||
|
||||
### Verb
|
||||
|
||||
DELETE
|
||||
|
||||
|
||||
## Regatta Info
|
||||
|
||||
Informations regarding a regatta. We need the list of (scheduled) races to remind the user to start tracking.
|
||||
|
||||
### Path
|
||||
|
||||
{serverUrl}/api/v1/leaderboard/{unique_leaderboard_name}/regatta.json
|
||||
|
||||
or
|
||||
|
||||
{serverUrl}/api/v1/event/{event_id}/regatta/{regatta_id}.json
|
||||
|
||||
### Verb
|
||||
|
||||
GET
|
||||
|
||||
### Response
|
||||
**Verb:** ``POST``
|
||||
|
||||
**Request:**
|
||||
```
|
||||
{
|
||||
"id": "237fab64e36d240dd07aeed2bd5a8426",
|
||||
"title": "49ers",
|
||||
"event_id" : "237fab64e36d240dd07aeed2bd5a8426"
|
||||
"leaderboard" : "Leaderboard Identifier",
|
||||
"races":[
|
||||
{
|
||||
"startTime" : 1414414481000,
|
||||
"status" : "finished",
|
||||
"fleet" : "Blue"
|
||||
"phase" : "Qualification"
|
||||
"name" : "Q1"
|
||||
},
|
||||
{
|
||||
"startTime" : 1414414481005,
|
||||
"status" : "running",
|
||||
"fleet" : "Red"
|
||||
"phase" : "Qualification"
|
||||
"name" : "Q1"
|
||||
},
|
||||
{
|
||||
"startTime" : 1414414481010,
|
||||
"status" : "scheduled",
|
||||
"fleet" : "Blue"
|
||||
"phase" : "Qualification"
|
||||
"name" : "Q2"
|
||||
},
|
||||
{
|
||||
"startTime" : "",
|
||||
"status" : "unscheduled",
|
||||
"fleet" : "Red"
|
||||
"phase" : "Qualification"
|
||||
"name" : "Q2"
|
||||
"competitorId" : "af855a56-9726-4a9c-a77e-da955bd289bg",
|
||||
"deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
|
||||
"toMillis" : 1415624564719
|
||||
}
|
||||
]
|
||||
},
|
||||
```
|
||||
* **toMillis** Milliseconds timestamp up to which to map the device to the competitor.
|
||||
|
||||
**Response:**
|
||||
``HTTP 200``, no response body
|
||||
|
||||
## Competitor Info
|
||||
|
||||
Informations for a competitor can be requested.
|
||||
|
||||
### Path
|
||||
|
||||
{serverUrl}/api/v1/competitor/{competitor_id}.json
|
||||
|
||||
### Verb
|
||||
|
||||
GET
|
||||
|
||||
### Response
|
||||
|
||||
{
|
||||
"Id" : "250cf8b51c773f3f8dc8b4be867a9a02",
|
||||
"Name" : "Alster Segel Club",
|
||||
"ProfileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg"
|
||||
"Flag": {BASE64STRING or URL},
|
||||
"Registration": "GER 14"
|
||||
}
|
||||
|
||||
## Upload Profile Image
|
||||
|
||||
An image can be uploaded per competitor.
|
||||
|
||||
### Path
|
||||
|
||||
{serverUrl}/api/v1/competitor/{competitor_id}/profile_image.json
|
||||
|
||||
### Verb
|
||||
|
||||
POST
|
||||
|
||||
### Request
|
||||
|
||||
Multipart upload with part `image` containing JPEG image 80%, max dimension 1200px.
|
||||
|
||||
### Response
|
||||
|
||||
{
|
||||
"profileImageUrl" : "http://s3.amazonaws.com/sapsailing/profile_images/68053af2923e00204c3ca7c6a3150cf7.jpeg"
|
||||
}
|
||||
|
||||
**profileImageUrl** URL of uploaded image.
|
||||
|
||||
## Send Measurements (to the Fix Store)
|
||||
|
||||
@@ -192,18 +146,15 @@ Measurements should be sent live during an event. In case of missing network, me
|
||||
|
||||
GZIP compression is a must. Bulk uploads should be chunked, e.g. per 1,000 locations.
|
||||
|
||||
### Path
|
||||
**Path:** ``gps_fixes``
|
||||
|
||||
{serverUrl}/api/v1/fix_store.json
|
||||
|
||||
### Verb
|
||||
|
||||
POST
|
||||
|
||||
### Request
|
||||
**Verb:** ``POST``
|
||||
|
||||
**Request:**
|
||||
```
|
||||
{
|
||||
"measurements" : [
|
||||
"deviceUuid" : "af855a56-9726-4a9c-a77e-da955bd289bf",
|
||||
"fixes" : [
|
||||
{
|
||||
"timestamp" : 14144160080000,
|
||||
"latitude" : 54.325246,
|
||||
@@ -217,11 +168,10 @@ GZIP compression is a must. Bulk uploads should be chunked, e.g. per 1,000 locat
|
||||
"longitude" : 8.03456,
|
||||
"speed" : 5.1,
|
||||
"course" : 14.2,
|
||||
},
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**speed** Speed over ground in meters per second.
|
||||
|
||||
**course** Heading in degrees.
|
||||
```
|
||||
* JSON array may contain one or several fixes
|
||||
* **speed** Speed over ground in meters per second.
|
||||
* **course** Bearing in degrees.
|
||||
Reference in new issue
Block a user