mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-21 19:50:01 +00:00
Merge branch 'master' into racecommittee_app
This commit is contained in:
commit
492947d2f1
141 files changed
+3045
-1033
No files matched your search
@@ -2,8 +2,6 @@
|
||||
<classpath>
|
||||
<classpathentry exported="true" kind="lib" path="lib/gwt-dev.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/gwt-user.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/validation-api-1.0.0.GA-sources.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/validation-api-1.0.0.GA.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
|
||||
@@ -7,10 +7,7 @@ Bundle-Vendor: GOOGLE
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Bundle-ClassPath: lib/gwt-dev.jar,
|
||||
lib/gwt-user.jar,
|
||||
lib/validation-api-1.0.0.GA-sources.jar,
|
||||
lib/validation-api-1.0.0.GA.jar,
|
||||
.
|
||||
Eclipse-BuddyPolicy: registered
|
||||
Export-Package: com.gargoylesoftware.htmlunit,
|
||||
com.gargoylesoftware.htmlunit.attachment,
|
||||
com.gargoylesoftware.htmlunit.gae,
|
||||
@@ -601,4 +598,6 @@ Export-Package: com.gargoylesoftware.htmlunit,
|
||||
org.mortbay.util,
|
||||
org.mortbay.util.ajax,
|
||||
org.mortbay.xml
|
||||
Require-Bundle: javax.servlet;bundle-version="2.5.0";visibility:=reexport
|
||||
Require-Bundle: javax.validation;bundle-version="1.0.0"
|
||||
Import-Package: javax.servlet;version="2.5.0",
|
||||
javax.servlet.http;version="2.5.0"
|
||||
@@ -1,6 +1,4 @@
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
lib/gwt-dev.jar,\
|
||||
lib/gwt-user.jar,\
|
||||
lib/validation-api-1.0.0.GA-sources.jar,\
|
||||
lib/validation-api-1.0.0.GA.jar
|
||||
lib/gwt-user.jar
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.google.gwt.user.osgi</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -6,8 +6,7 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Fragment-Host: com.sap.sailing.declination
|
||||
Require-Bundle: org.junit4;bundle-version="4.8.2"
|
||||
Import-Package: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.common.impl,
|
||||
com.sap.sailing.domain.common.quadtree,
|
||||
junit.framework;version="4.8.1",
|
||||
org.junit;version="4.8.1"
|
||||
com.sap.sailing.domain.common.quadtree
|
||||
+1
-4
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
|
||||
@@ -9,8 +8,6 @@ import com.sap.sailing.domain.common.TimePoint;
|
||||
public abstract class AbstractTimePoint implements TimePoint {
|
||||
private static final long serialVersionUID = 8825508619301420378L;
|
||||
|
||||
public static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
|
||||
public static Comparator<TimePoint> TIMEPOINT_COMPARATOR = new SerializableComparator<TimePoint>() {
|
||||
private static final long serialVersionUID = 7644726881387366025L;
|
||||
|
||||
@@ -68,7 +65,7 @@ public abstract class AbstractTimePoint implements TimePoint {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return TIMEPOINT_FORMATTER.format(asDate());
|
||||
return asDate().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+20
@@ -185,6 +185,26 @@ public class SwissTimingAdapterPersistenceImpl implements SwissTimingAdapterPers
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRaceStartlist(String raceID) {
|
||||
DBCollection races = database.getCollection(CollectionNames.RACES_MESSAGES.name());
|
||||
BasicDBObject query = new BasicDBObject();
|
||||
query.append(FieldNames.RACE_ID.name(), raceID);
|
||||
query.append(FieldNames.MESSAGE_COMMAND.name(), MessageType.STL.name());
|
||||
DBObject object = races.findOne(query);
|
||||
return object != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRaceCourse(String raceID) {
|
||||
DBCollection races = database.getCollection(CollectionNames.RACES_MESSAGES.name());
|
||||
BasicDBObject query = new BasicDBObject();
|
||||
query.append(FieldNames.RACE_ID.name(), raceID);
|
||||
query.append(FieldNames.MESSAGE_COMMAND.name(), MessageType.CCG.name());
|
||||
DBObject object = races.findOne(query);
|
||||
return object != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Race> getRaces() {
|
||||
DBCollection races = database.getCollection(CollectionNames.RACES_MASTERDATA.name());
|
||||
|
||||
@@ -16,9 +16,8 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.persistence,
|
||||
com.sap.sailing.domain.tractracadapter,
|
||||
com.sap.sailing.domain.swisstimingadapter.persistence;bundle-version="1.0.0",
|
||||
org.junit4;bundle-version="4.8.2",
|
||||
org.hamcrest.core;bundle-version="1.1.0"
|
||||
Bundle-ClassPath: resources/,
|
||||
.
|
||||
Import-Package: com.sap.sailing.server,
|
||||
junit.framework;version="4.8.1",
|
||||
org.junit;version="4.8.1"
|
||||
Import-Package: com.sap.sailing.server
|
||||
-8
@@ -47,14 +47,6 @@ public class DomainFactoryTest {
|
||||
assertThat(raceType.getRaceCode(), is(OlympicRaceCode._470_WOMEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGet470WomenBoatClass2() throws Exception {
|
||||
String raceID = "SAW005_xxx";
|
||||
RaceType raceType = swissTimingDomainFactory.getRaceTypeFromRaceID(raceID );
|
||||
assertThat(raceType, is(notNullValue()));
|
||||
assertThat(raceType.getRaceCode(), is(OlympicRaceCode._470_WOMEN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDontGetWrongBoatClass() throws Exception {
|
||||
String raceID = "ABC";
|
||||
|
||||
+12
@@ -208,4 +208,16 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRaceStartlist(String raceID) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRaceCourse(String raceID) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class SimpleDomainFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testExtractBoatClassFromRaceIDWithEventID() {
|
||||
String raceID = "QINSWC12013;SAW005901";
|
||||
String raceID = "QINSWC12013_SAW005901";
|
||||
RaceType raceType = DomainFactory.INSTANCE.getRaceTypeFromRaceID(raceID);
|
||||
assertEquals("470", raceType.getBoatClass().getName());
|
||||
}
|
||||
|
||||
+12
-1
@@ -7,11 +7,15 @@ public class RaceRecord {
|
||||
private String raceID;
|
||||
private String description;
|
||||
private Date startTime;
|
||||
private boolean hasCourse;
|
||||
private boolean hasStartlist;
|
||||
|
||||
public RaceRecord(String raceID, String description, Date startTime) {
|
||||
public RaceRecord(String raceID, String description, Date startTime, boolean hasCourse, boolean hasStartlist) {
|
||||
this.raceID = raceID;
|
||||
this.description = description;
|
||||
this.startTime = startTime;
|
||||
this.hasCourse = hasCourse;
|
||||
this.hasStartlist = hasStartlist;
|
||||
}
|
||||
|
||||
public String getRaceID() {
|
||||
@@ -26,4 +30,11 @@ public class RaceRecord {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public boolean hasCourse() {
|
||||
return hasCourse;
|
||||
}
|
||||
|
||||
public boolean hasStartlist() {
|
||||
return hasStartlist;
|
||||
}
|
||||
}
|
||||
+4
@@ -21,4 +21,8 @@ public interface RaceSpecificMessageLoader {
|
||||
Iterable<Race> getRaces();
|
||||
|
||||
Race getRace(String raceID);
|
||||
|
||||
boolean hasRaceStartlist(String raceID);
|
||||
|
||||
boolean hasRaceCourse(String raceID);
|
||||
}
|
||||
+3
-3
@@ -26,12 +26,12 @@ public interface RaceType {
|
||||
_470_MEN("SAM005", "470", Gender.male),
|
||||
STAR("SAM007", "Star", Gender.male),
|
||||
_49ER("SAM009", "49er", Gender.male),
|
||||
_49ERFX("SAW009", "49erFX", Gender.female),
|
||||
ELLIOTT6M("SAW007", "Elliott 6M", Gender.female),
|
||||
RSX_WOMEN("SAW102", "RS:X", Gender.female),
|
||||
RSX_MEN("SAM102", "RS:X", Gender.male),
|
||||
LASER_RADIAL("SAW103", "Laser Radial", Gender.female),
|
||||
_49ERFX_TODO("xxxxx_TODO_xxxxx", "49er FX", Gender.female),
|
||||
NACRA17_TOTO("xxxxx_TODO_xxxxx", "Nacra 17", Gender.mixed);
|
||||
NACRA17("SAX017", "Nacra 17", Gender.mixed),
|
||||
LASER_RADIAL("SAW103", "Laser Radial", Gender.female);
|
||||
|
||||
enum Gender {
|
||||
male, female, mixed, unspecified;
|
||||
|
||||
+5
-1
@@ -19,8 +19,12 @@ public interface SailMasterConnector {
|
||||
|
||||
Course getCourse(String raceID) throws UnknownHostException, IOException, InterruptedException;
|
||||
|
||||
boolean hasCourse(String raceID);
|
||||
|
||||
StartList getStartList(String raceID) throws UnknownHostException, IOException, InterruptedException;
|
||||
|
||||
|
||||
boolean hasStartlist(String raceID);
|
||||
|
||||
TimePoint getStartTime(String raceID) throws UnknownHostException, IOException, ParseException, InterruptedException;
|
||||
|
||||
Distance getDistanceToMark(String raceID, int markIndex, String boatID) throws UnknownHostException, IOException, InterruptedException;
|
||||
|
||||
+1
-1
@@ -206,7 +206,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
public RaceType getRaceTypeFromRaceID(String raceID) {
|
||||
final RaceType result;
|
||||
if (raceID != null && raceID.length() >= 6) {
|
||||
final String[] optionalEventIDAndMandatoryRaceID = raceID.split(";");
|
||||
final String[] optionalEventIDAndMandatoryRaceID = raceID.split("_");
|
||||
final String swissTimingRaceCode = optionalEventIDAndMandatoryRaceID[optionalEventIDAndMandatoryRaceID.length-1].substring(0, 6).toUpperCase();
|
||||
RaceType raceType = raceTypeByID.get(swissTimingRaceCode);
|
||||
if (raceType == null) {
|
||||
|
||||
+18
@@ -606,6 +606,24 @@ public class SailMasterConnectorImpl extends SailMasterTransceiverImpl implement
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCourse(String raceID) {
|
||||
boolean result = false;
|
||||
if (messageLoader != null) {
|
||||
result = messageLoader.hasRaceCourse(raceID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStartlist(String raceID) {
|
||||
boolean result = false;
|
||||
if (messageLoader != null) {
|
||||
result = messageLoader.hasRaceStartlist(raceID);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Race> parseAvailableRacesMessage(SailMasterMessage availableRacesMessage) {
|
||||
assertMessageType(MessageType.RAC, availableRacesMessage);
|
||||
int count = Integer.valueOf(availableRacesMessage.getSections()[1]);
|
||||
|
||||
@@ -7,6 +7,6 @@ Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Fragment-Host: com.sap.sailing.domain.swisstimingreplayadapter
|
||||
Import-Package: org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.junit;version="4.8.2"
|
||||
Require-Bundle: com.sap.sailing.domain.test
|
||||
org.json.simple.parser
|
||||
Require-Bundle: com.sap.sailing.domain.test,
|
||||
org.junit4;bundle-version="4.8.2"
|
||||
@@ -14,10 +14,8 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
org.mockito.mockito-core;bundle-version="1.9.5",
|
||||
com.sap.sailing.domain.test,
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.objenesis;bundle-version="1.3.0"
|
||||
org.objenesis;bundle-version="1.3.0",
|
||||
org.junit4;bundle-version="4.8.2",
|
||||
org.json.simple;bundle-version="1.1.0"
|
||||
Export-Package: com.sap.sailing.domain.test,
|
||||
com.sap.sailing.domain.test.mock
|
||||
Import-Package: junit.framework;version="4.8.1",
|
||||
org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.junit;version="4.8.1"
|
||||
+13
-12
@@ -179,25 +179,26 @@ public interface DomainFactory {
|
||||
/**
|
||||
* Creates a {@link RaceDefinition} from a TracTrac {@link Race} and a domain {@link Course} definition. The
|
||||
* resulting {@link RaceDefinition} is added to the {@link com.sap.sailing.domain.base.Regatta} to which
|
||||
* <code>trackedRegatta</code> belongs (see {@link TrackedRegatta#getRegatta()}). It is added to the internal race cache.
|
||||
* The corresponding {@link TrackedRace} object is also created, and the notification of threads waiting on the race
|
||||
* cache such as a blocking {@link #getAndWaitForRaceDefinition(UUID)} happens only <em>after</em> the tracked race
|
||||
* has been created and the {@link RaceDefinition} was
|
||||
* <code>trackedRegatta</code> belongs (see {@link TrackedRegatta#getRegatta()}). It is added to the internal race
|
||||
* cache. The corresponding {@link TrackedRace} object is also created, and the notification of threads waiting on
|
||||
* the race cache such as a blocking {@link #getAndWaitForRaceDefinition(UUID)} happens only <em>after</em> the
|
||||
* tracked race has been created and the {@link RaceDefinition} was
|
||||
* {@link com.sap.sailing.domain.base.Regatta#addRace(RaceDefinition) added} to the domain event. This ensures that
|
||||
* waiters for the {@link RaceDefinition} are guaranteed to obtain a valid, non- <code>null</code> tracked race
|
||||
* waiters for the {@link RaceDefinition} are guaranteed to obtain a valid, non-<code>null</code> tracked race
|
||||
* already immediately after the notification was sent, and that the {@link RaceDefinition} is already
|
||||
* {@link com.sap.sailing.domain.base.Regatta#getAllRaces() known} by its containing
|
||||
* {@link com.sap.sailing.domain.base.Regatta}.
|
||||
* @param raceName TODO
|
||||
* @param competitors TODO
|
||||
* @param boatClass TODO
|
||||
*
|
||||
* @param raceDefinitionSetToUpdate
|
||||
* if not <code>null</code>, after creating the {@link TrackedRace}, the {@link RaceDefinition} is
|
||||
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that object.
|
||||
* {@link DynamicRaceDefinitionSet#addRaceDefinition(RaceDefinition, DynamicTrackedRace) added} to that
|
||||
* object.
|
||||
*/
|
||||
DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, UUID raceId,
|
||||
String raceName, Iterable<com.sap.sailing.domain.base.Competitor> competitors, BoatClass boatClass, Course course, Iterable<Sideline> sidelines,
|
||||
WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword);
|
||||
DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId,
|
||||
String raceName, Iterable<com.sap.sailing.domain.base.Competitor> competitors, BoatClass boatClass,
|
||||
Course course, Iterable<Sideline> sidelines, WindStore windStore, long delayToLiveInMillis,
|
||||
long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate,
|
||||
URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword);
|
||||
|
||||
/**
|
||||
* The record may be for a single mark or a gate. If for a gate, the
|
||||
|
||||
+23
-21
@@ -469,7 +469,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(TrackedRegatta trackedRegatta, UUID raceId,
|
||||
public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId,
|
||||
String raceName, Iterable<Competitor> competitors, BoatClass boatClass, Course course,
|
||||
Iterable<Sideline> sidelines, WindStore windStore, long delayToLiveInMillis,
|
||||
long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate,
|
||||
@@ -479,36 +479,38 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
if (raceDefinition == null) {
|
||||
logger.info("Creating RaceDefinitionImpl for race "+raceName);
|
||||
raceDefinition = new RaceDefinitionImpl(raceName, course, boatClass, competitors, raceId);
|
||||
} else {
|
||||
logger.info("Already found RaceDefinitionImpl for race "+raceName);
|
||||
}
|
||||
DynamicTrackedRace trackedRace = trackedRegatta.getExistingTrackedRace(raceDefinition);
|
||||
if (trackedRace == null) {
|
||||
// add to existing regatta only if boat class matches
|
||||
if (raceDefinition.getBoatClass() == trackedRegatta.getRegatta().getBoatClass()) {
|
||||
trackedRegatta.getRegatta().addRace(raceDefinition);
|
||||
DynamicTrackedRace trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore,
|
||||
trackedRace = createTrackedRace(trackedRegatta, raceDefinition, sidelines, windStore,
|
||||
delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
|
||||
logger.info("Added race "+raceDefinition+" to regatta "+trackedRegatta.getRegatta());
|
||||
|
||||
TracTracCourseDesignUpdateHandler courseDesignHandler = new TracTracCourseDesignUpdateHandler(tracTracUpdateURI,
|
||||
tracTracUsername, tracTracPassword,
|
||||
tracTracEventUuid, raceDefinition.getId());
|
||||
logger.info("Added race " + raceDefinition + " to regatta " + trackedRegatta.getRegatta());
|
||||
|
||||
TracTracCourseDesignUpdateHandler courseDesignHandler = new TracTracCourseDesignUpdateHandler(
|
||||
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
|
||||
raceDefinition.getId());
|
||||
trackedRace.addCourseDesignChangedListener(courseDesignHandler);
|
||||
|
||||
TracTracStartTimeUpdateHandler startTimeHandler = new TracTracStartTimeUpdateHandler(tracTracUpdateURI,
|
||||
tracTracUsername, tracTracPassword, tracTracEventUuid, raceDefinition.getId());
|
||||
|
||||
TracTracStartTimeUpdateHandler startTimeHandler = new TracTracStartTimeUpdateHandler(
|
||||
tracTracUpdateURI, tracTracUsername, tracTracPassword, tracTracEventUuid,
|
||||
raceDefinition.getId());
|
||||
trackedRace.addStartTimeChangedListener(startTimeHandler);
|
||||
|
||||
synchronized (raceCache) {
|
||||
raceCache.put(raceId, raceDefinition);
|
||||
raceCache.notifyAll();
|
||||
}
|
||||
return trackedRace;
|
||||
raceCache.put(raceId, raceDefinition);
|
||||
raceCache.notifyAll();
|
||||
} else {
|
||||
logger.warning("Not adding race "+raceDefinition+" to regatta "+trackedRegatta.getRegatta()+
|
||||
" because boat class "+raceDefinition.getBoatClass()+" doesn't match regatta's boat class "+
|
||||
trackedRegatta.getRegatta().getBoatClass());
|
||||
return null;
|
||||
logger.warning("Not adding race " + raceDefinition + " to regatta " + trackedRegatta.getRegatta()
|
||||
+ " because boat class " + raceDefinition.getBoatClass()
|
||||
+ " doesn't match regatta's boat class " + trackedRegatta.getRegatta().getBoatClass());
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("Race "+raceName+" already exists");
|
||||
logger.info("Found existing tracked race for race "+raceName+" with ID "+raceId);
|
||||
}
|
||||
return trackedRace;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -29,17 +29,21 @@ public class Simulator {
|
||||
private static final Logger logger = Logger.getLogger(Simulator.class.getName());
|
||||
|
||||
private DynamicTrackedRace trackedRace;
|
||||
private WindStore windStore;
|
||||
private final WindStore windStore;
|
||||
private long advanceInMillis = -1;
|
||||
private Timer timer = new Timer("Timer for TracTrac Simulator");
|
||||
private boolean stopped;
|
||||
|
||||
public Simulator(WindStore windStore) {
|
||||
super();
|
||||
assert windStore != null;
|
||||
this.windStore = windStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wind store which replays the wind store events against a tracked race, correcting the wind fixes with
|
||||
* the simulation delay. The wind store returned is an {@link EmptyWindStore}.
|
||||
* The wind store returned is an {@link EmptyWindStore}.
|
||||
*/
|
||||
public WindStore simulatingWindStore(WindStore windStore) {
|
||||
this.windStore = windStore;
|
||||
return EmptyWindStore.INSTANCE;
|
||||
}
|
||||
|
||||
@@ -63,7 +67,6 @@ public class Simulator {
|
||||
*/
|
||||
private void startWindPlayer() {
|
||||
assert this.trackedRace != null;
|
||||
assert this.windStore != null;
|
||||
for (final Map.Entry<? extends WindSource, ? extends WindTrack> windSourceAndTrack : windStore.loadWindTracks(
|
||||
trackedRace.getTrackedRegatta(), trackedRace,
|
||||
/* millisecondsOverWhichToAverageWind doesn't matter because we only use raw fixes */ 10000).entrySet()) {
|
||||
|
||||
+24
-29
@@ -192,7 +192,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
this.domainFactory = domainFactory;
|
||||
final Simulator simulator;
|
||||
if (simulateWithStartTimeNow) {
|
||||
simulator = new Simulator();
|
||||
simulator = new Simulator(windStore);
|
||||
} else {
|
||||
simulator = null;
|
||||
}
|
||||
@@ -225,8 +225,6 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
// in this case, create a default regatta based on the TracTrac event data
|
||||
this.regatta = effectiveRegatta == null ? domainFactory.getOrCreateDefaultRegatta(raceLogStore, tractracEvent, trackedRegattaRegistry) : effectiveRegatta;
|
||||
trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(this.regatta);
|
||||
// Read event data from configuration file
|
||||
controlPointPositionPoller = scheduleClientParamsPHPPoller(paramURL, simulator, tracTracUpdateURI, delayToLiveInMillis, tracTracUsername, tracTracPassword);
|
||||
receivers = new HashSet<Receiver>();
|
||||
Set<TypeController> typeControllers = new HashSet<TypeController>();
|
||||
for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedRegatta(), tractracEvent, startOfTracking,
|
||||
@@ -237,6 +235,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
}
|
||||
}
|
||||
addListenersForStoredDataAndStartController(typeControllers);
|
||||
// Read event data from configuration file
|
||||
controlPointPositionPoller = scheduleClientParamsPHPPoller(paramURL, simulator, tracTracUpdateURI, delayToLiveInMillis, tracTracUsername, tracTracPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -550,6 +550,25 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
logger.info("stopped TracTrac tracking for "+getRaces());
|
||||
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.FINISHED, 1.0);
|
||||
updateStatusOfTrackedRaces();
|
||||
for (final RaceDefinition race : getRaces()) {
|
||||
// Ask RacingEventService to cleanly stop and unregister this tracker
|
||||
// if the race has all data loaded. Doing this asynchronously because
|
||||
// stopping can take longer and if you're loading many races in parallel
|
||||
// this can slow down loading extremely because this call-back seems to be
|
||||
// called by TTCM synchronously.
|
||||
Thread raceStopper = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
trackedRegattaRegistry.stopTracking(regatta, race);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error trying to stop tracker for race " + race.getName()
|
||||
+ " in regatta " + getRegatta().getName(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
raceStopper.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatusOfTrackedRaces() {
|
||||
@@ -562,7 +581,8 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
}
|
||||
|
||||
private void updateStatusOfTrackedRace(DynamicTrackedRace trackedRace) {
|
||||
if (lastStatus != null) {
|
||||
// can't update a race status once it has been set to FINISHED
|
||||
if (lastStatus != null && trackedRace.getStatus() != null && trackedRace.getStatus().getStatus() != TrackedRaceStatusEnum.FINISHED) {
|
||||
trackedRace.setStatus(lastStatus);
|
||||
}
|
||||
}
|
||||
@@ -580,31 +600,6 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
|
||||
if (isLiveTracking) {
|
||||
lastStatus = new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 1);
|
||||
updateStatusOfTrackedRaces();
|
||||
} else {
|
||||
// ask RacingEventService to cleanly stop and unregister this tracker
|
||||
// if the race has all data loaded. Doing this asynchronously because
|
||||
// stopping can take longer and if you're loading many races in parallel
|
||||
// this can slow down loading extremely
|
||||
for (final RaceDefinition race : getRaces()) {
|
||||
DynamicTrackedRace trackedRace = getTrackedRegatta().getExistingTrackedRace(race);
|
||||
final Regatta regatta = getRegatta();
|
||||
if (trackedRace.getStatus().getLoadingProgress() == 1.0) {
|
||||
Thread raceStopper = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
trackedRegattaRegistry.stopTracking(regatta, race);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error trying to stop tracker for race "+race.getName()+
|
||||
" in regatta "+getRegatta().getName(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
raceStopper.start();
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Not stopping race "+race.getName()+" because it has not all data loaded! Progress: " + trackedRace.getStatus().getLoadingProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -31,7 +31,7 @@ import com.sap.sailing.domain.tracking.Wind;
|
||||
|
||||
public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
|
||||
|
||||
public static final Logger log = Logger.getLogger(DynamicTrackedRaceLogListener.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(DynamicTrackedRaceLogListener.class.getName());
|
||||
|
||||
private DynamicTrackedRace trackedRace;
|
||||
|
||||
@@ -112,7 +112,7 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
|
||||
// ... onCourseDesignChangedByRaceCommittee() might be called more than once.
|
||||
trackedRace.onCourseDesignChangedByRaceCommittee(courseDesign);
|
||||
} else {
|
||||
log.info("Could not find any course design update on race log of " + trackedRace.getRace().getName() + "! Not sending out any events.");
|
||||
logger.info("Could not find any course design update on race log of " + trackedRace.getRace().getName() + "! Not sending out any events.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public class DynamicTrackedRaceLogListener implements RaceLogEventVisitor {
|
||||
/* invoke listeners with received start time, this will also trigger tractrac update */
|
||||
trackedRace.onStartTimeChangedByRaceCommittee(startTime);
|
||||
} else {
|
||||
log.info("Could not find any valid start time on race log of " + trackedRace.getRace().getName() + "! Not sending out any events.");
|
||||
logger.info("Could not find any valid start time on race log of " + trackedRace.getRace().getName() + "! Not sending out any events.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,5 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Fragment-Host: com.sap.sailing.expeditionconnector
|
||||
Require-Bundle: com.sap.sailing.server,
|
||||
com.sap.sailing.domain.test,
|
||||
com.sap.sailing.udpconnector
|
||||
Import-Package: junit.framework;version="4.8.1",
|
||||
org.junit;version="4.8.1",
|
||||
org.osgi.framework;version="1.6.0"
|
||||
com.sap.sailing.udpconnector,
|
||||
org.junit4;bundle-version="4.8.2"
|
||||
@@ -34,10 +34,10 @@
|
||||
<plugin id="com.sap.sailing.barbados.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.ess40.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.freg.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.gwt.ui" autoStart="true" startLevel="4" />
|
||||
<plugin id="com.sap.sailing.gwt.ui" autoStart="true" startLevel="5" />
|
||||
<plugin id="com.sap.sailing.kiworesultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.manage2sail.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.monitoring" autoStart="true" startLevel="5" />
|
||||
<plugin id="com.sap.sailing.monitoring" autoStart="true" startLevel="6" />
|
||||
<plugin id="com.sap.sailing.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.sailwave.resultimport" autoStart="true" startLevel="3" />
|
||||
<plugin id="com.sap.sailing.server" autoStart="true" startLevel="4" />
|
||||
|
||||
@@ -27,17 +27,15 @@
|
||||
<import plugin="org.eclipse.osgi"/>
|
||||
<import plugin="org.eclipse.osgi.services"/>
|
||||
<import plugin="slf4j.api"/>
|
||||
<import plugin="javax.el"/>
|
||||
<import plugin="javax.servlet.jsp"/>
|
||||
<import plugin="javax.servlet.jsp.jstl"/>
|
||||
<import plugin="org.apache.jasper.glassfish"/>
|
||||
<import plugin="org.apache.taglibs.standard.glassfish"/>
|
||||
<import plugin="org.eclipse.jetty.osgi.boot"/>
|
||||
<import plugin="org.eclipse.jetty.websocket.api"/>
|
||||
<import plugin="org.eclipse.jetty.websocket.client"/>
|
||||
<import plugin="org.eclipse.jetty.websocket.common"/>
|
||||
<import plugin="org.eclipse.jetty.websocket.server"/>
|
||||
<import plugin="org.eclipse.jetty.websocket.servlet"/>
|
||||
<import plugin="org.apache.felix.gogo.command"/>
|
||||
<import plugin="org.apache.felix.gogo.runtime"/>
|
||||
<import plugin="org.apache.felix.gogo.shell"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
@@ -47,14 +45,6 @@
|
||||
version="9.0.4.v20130625"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="org.eclipse.jetty.osgi.boot.jsp"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="9.0.4.v20130625"
|
||||
fragment="true"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="jul.to.slf4j"
|
||||
download-size="0"
|
||||
@@ -98,4 +88,11 @@
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="org.eclipse.equinox.console"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
@@ -22,20 +22,38 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
|
||||
<requires>
|
||||
<import plugin="com.googlecode.java-diff-utils" version="1.3.0" match="greaterOrEqual"/>
|
||||
<import plugin="org.eclipse.osgi"/>
|
||||
<import plugin="org.eclipse.osgi" version="3.9.0" match="greaterOrEqual"/>
|
||||
<import plugin="javax.servlet" version="2.6.0" match="greaterOrEqual"/>
|
||||
<import plugin="com.mongodb.driver" version="2.6.2" match="greaterOrEqual"/>
|
||||
<import plugin="com.google.gwt.osgi" version="2.4.0" match="greaterOrEqual"/>
|
||||
<import plugin="com.sap.sailing.domain.common"/>
|
||||
<import plugin="com.google.gwt.osgi" version="2.5.1" match="greaterOrEqual"/>
|
||||
<import plugin="org.json.simple" version="1.1.0" match="greaterOrEqual"/>
|
||||
<import plugin="com.sap.sailing.operationaltransformation"/>
|
||||
<import plugin="org.moxieapps.gwt.highcharts" version="1.1.4" match="greaterOrEqual"/>
|
||||
<import plugin="com.sap.sailing.geocoding"/>
|
||||
<import plugin="org.apache.geronimo.specs.geronimo-jms_1.1_spec"/>
|
||||
<import plugin="com.rabbitmq.client"/>
|
||||
<import plugin="org.apache.geronimo.specs.geronimo-j2ee-management_1.1_spec"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.geocoding"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.operationaltransformation"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.domain.common"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.domain"
|
||||
download-size="0"
|
||||
@@ -85,13 +103,6 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="org.json.simple"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.declination"
|
||||
download-size="0"
|
||||
@@ -99,13 +110,6 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.mongodb.driver"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.mongodb"
|
||||
download-size="0"
|
||||
@@ -176,20 +180,6 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.google.gwt.osgi"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.googlecode.java-diff-utils"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sailing.www"
|
||||
download-size="0"
|
||||
|
||||
@@ -6,6 +6,5 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Fragment-Host: com.sap.sailing.geocoding
|
||||
Import-Package: junit.framework;version="4.8.2",
|
||||
org.json.simple.parser,
|
||||
org.junit;version="4.8.2"
|
||||
Require-Bundle: org.junit4;bundle-version="4.8.2"
|
||||
Import-Package: org.json.simple.parser
|
||||
@@ -3,8 +3,8 @@
|
||||
<classpathentry kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry exported="true" kind="lib" path="WEB-INF/classes/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="lib" path="WEB-INF/lib/gwt-servlet.jar" sourcepath="/com.google.gwt.osgi/lib/gwt-user.jar"/>
|
||||
<classpathentry kind="lib" path="WEB-INF/lib/gwt-maps.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
|
||||
@@ -16,7 +16,6 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.persistence,
|
||||
com.sap.sailing.domain.swisstimingadapter.persistence,
|
||||
com.sap.sailing.domain.tractracadapter.persistence,
|
||||
com.google.gwt.osgi;bundle-version="2.4.0",
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sailing.resultimport,
|
||||
org.moxieapps.gwt.highcharts;bundle-version="1.5.0",
|
||||
@@ -27,12 +26,14 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.swisstimingreplayadapter,
|
||||
com.sap.sailing.simulator;bundle-version="1.0.0",
|
||||
com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0",
|
||||
de.csenk.gwt.ws
|
||||
de.csenk.gwt.ws,
|
||||
com.google.gwt.osgi;bundle-version="2.5.1"
|
||||
Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: javax.jms;version="1.1.0",
|
||||
javax.servlet;version="2.6.0",
|
||||
javax.servlet.http;version="2.6.0",
|
||||
javax.servlet.descriptor;version="2.6.0",
|
||||
org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework,
|
||||
|
||||
+29
-25
@@ -816,32 +816,36 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
|
||||
|
||||
private void selectTrackedRaceInRaceList() {
|
||||
final String selectedLeaderboardName = getSelectedLeaderboardName();
|
||||
final RaceColumnDTOAndFleetDTOWithNameBasedEquality selectedRaceColumnAndFleetNameInLeaderboard = getSelectedRaceColumnWithFleet();
|
||||
final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA().getRaceColumnName();
|
||||
final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().getName();
|
||||
sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName,
|
||||
selectedRaceColumnName, new AsyncCallback<Map<String, RegattaAndRaceIdentifier>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to determine tracked race linked to race column "
|
||||
+ selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": "
|
||||
+ t.getMessage());
|
||||
}
|
||||
if (selectedLeaderboardName != null) {
|
||||
final RaceColumnDTOAndFleetDTOWithNameBasedEquality selectedRaceColumnAndFleetNameInLeaderboard = getSelectedRaceColumnWithFleet();
|
||||
final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA()
|
||||
.getRaceColumnName();
|
||||
final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().getName();
|
||||
sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName,
|
||||
selectedRaceColumnName, new AsyncCallback<Map<String, RegattaAndRaceIdentifier>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to determine tracked race linked to race column "
|
||||
+ selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": "
|
||||
+ t.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Map<String, RegattaAndRaceIdentifier> regattaAndRaceNamesPerFleet) {
|
||||
if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet.get(selectedFleetName);
|
||||
if (raceIdentifier != null) {
|
||||
selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName());
|
||||
} else {
|
||||
trackedRacesListComposite.clearSelection();
|
||||
}
|
||||
} else {
|
||||
trackedRacesListComposite.clearSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onSuccess(Map<String, RegattaAndRaceIdentifier> regattaAndRaceNamesPerFleet) {
|
||||
if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet
|
||||
.get(selectedFleetName);
|
||||
if (raceIdentifier != null) {
|
||||
selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName());
|
||||
} else {
|
||||
trackedRacesListComposite.clearSelection();
|
||||
}
|
||||
} else {
|
||||
trackedRacesListComposite.clearSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void selectRaceInList(String regattaName, String raceName) {
|
||||
|
||||
+16
-11
@@ -46,14 +46,9 @@ import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
|
||||
|
||||
/**
|
||||
* Allows the user to start and stop tracking of events, regattas and races using the TracTrac connector. In particular,
|
||||
* Allows the user to start and stop tracking of races using the SwissTiming connector. In particular,
|
||||
* previously configured connections can be retrieved from a drop-down list which then pre-populates all connection
|
||||
* parameters. The user can also choose to enter connection information manually. Using a "hierarchical" entry system
|
||||
* comparable to that of, e.g., the Eclipse CVS connection setup wizard, components entered will be used to
|
||||
* automatically assemble the full URL which can still be overwritten manually. There is a propagation order across the
|
||||
* fields. Hostname propagates to JSON URL, Live URI and Stored URI. Port Live Data propagates to Port Stored Data,
|
||||
* incremented by one. The ports propagate to Live URI and Stored URI, respectively. The event name propagates to the
|
||||
* JSON URL.
|
||||
* parameters. The user can also choose to enter connection information manually.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
@@ -166,7 +161,16 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceStartTrackingColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceStateColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
String result = object.hasCourse ? "C" : "";
|
||||
result += object.hasStartlist ? "S" : "";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<SwissTimingRaceRecordDTO> raceStartTimeColumn = new TextColumn<SwissTimingRaceRecordDTO>() {
|
||||
@Override
|
||||
public String getValue(SwissTimingRaceRecordDTO object) {
|
||||
return object.raceStartTime==null?"":dateFormatter.render(object.raceStartTime) + " " + timeFormatter.render(object.raceStartTime);
|
||||
@@ -228,14 +232,15 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
trackPanel.setStyleName("paddedPanel");
|
||||
|
||||
raceNameColumn.setSortable(true);
|
||||
raceStartTrackingColumn.setSortable(true);
|
||||
raceStartTimeColumn.setSortable(true);
|
||||
|
||||
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
|
||||
raceTable = new CellTable<SwissTimingRaceRecordDTO>(/* pageSize */ 10000, tableRes);
|
||||
raceTable.addColumn(raceNameColumn, stringConstants.name());
|
||||
raceTable.addColumn(raceDescriptionColumn, stringConstants.description());
|
||||
raceTable.addColumn(boatClassColumn, stringConstants.boatClass());
|
||||
raceTable.addColumn(raceStartTrackingColumn, stringConstants.raceStartTimeColumn());
|
||||
raceTable.addColumn(raceStateColumn, stringConstants.status());
|
||||
raceTable.addColumn(raceStartTimeColumn, stringConstants.startTime());
|
||||
raceTable.setWidth("300px");
|
||||
raceTable.setSelectionModel(new MultiSelectionModel<SwissTimingRaceRecordDTO>() {});
|
||||
|
||||
@@ -244,7 +249,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane
|
||||
|
||||
raceList = new ListDataProvider<SwissTimingRaceRecordDTO>();
|
||||
raceList.addDataDisplay(raceTable);
|
||||
Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTrackingColumn);
|
||||
Handler columnSortHandler = getRaceTableColumnSortHandler(raceList.getList(), raceNameColumn, raceStartTimeColumn);
|
||||
raceTable.addColumnSortHandler(columnSortHandler);
|
||||
|
||||
Label lblTrackSettings = new Label(stringConstants.trackSettings());
|
||||
|
||||
+8
-2
@@ -65,6 +65,7 @@ public class MediaSelector implements PlayStateListener, TimeListener,
|
||||
private StringMessages stringMessages;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final UserDTO user;
|
||||
private boolean autoSelectMedia;
|
||||
|
||||
private MediaPlayer activeAudioPlayer;
|
||||
private Date currentRaceTime;
|
||||
@@ -73,7 +74,7 @@ public class MediaSelector implements PlayStateListener, TimeListener,
|
||||
|
||||
public MediaSelector(RegattaAndRaceIdentifier selectedRaceIdentifier, RaceTimesInfoProvider raceTimesInfoProvider,
|
||||
Timer raceTimer, MediaServiceAsync mediaService, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, UserDTO user) {
|
||||
ErrorReporter errorReporter, UserDTO user, boolean autoSelectMedia) {
|
||||
this.raceIdentifier = selectedRaceIdentifier;
|
||||
this.raceTimesInfoProvider = raceTimesInfoProvider;
|
||||
this.raceTimer = raceTimer;
|
||||
@@ -81,6 +82,7 @@ public class MediaSelector implements PlayStateListener, TimeListener,
|
||||
this.stringMessages = stringMessages;
|
||||
this.errorReporter = errorReporter;
|
||||
this.user = user;
|
||||
this.autoSelectMedia = autoSelectMedia;
|
||||
|
||||
Window.addCloseHandler(this);
|
||||
Window.addWindowClosingHandler(this);
|
||||
@@ -120,7 +122,6 @@ public class MediaSelector implements PlayStateListener, TimeListener,
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
setWidgetsVisible(false);
|
||||
|
||||
}
|
||||
@@ -286,6 +287,11 @@ public class MediaSelector implements PlayStateListener, TimeListener,
|
||||
setStatus(mediaTrack);
|
||||
}
|
||||
setWidgetsVisible((this.mediaTracks.size() > 0) || (this.user != null));
|
||||
|
||||
toggleMediaButton.setValue(autoSelectMedia);
|
||||
if (autoSelectMedia) {
|
||||
playDefault();
|
||||
}
|
||||
}
|
||||
|
||||
private void setWidgetsVisible(boolean isVisible) {
|
||||
|
||||
+3
-2
@@ -82,8 +82,9 @@ public class RaceBoardEntryPoint extends AbstractEntryPoint {
|
||||
boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default*/);
|
||||
String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/);
|
||||
final boolean canReplayWhileLiveIsPossible = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, false);
|
||||
final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, false);
|
||||
raceboardViewConfig = new RaceBoardViewConfiguration(viewMode, activeCompetitorsFilterSetName, showLeaderboard,
|
||||
showWindChart, showCompetitorsChart, canReplayWhileLiveIsPossible);
|
||||
showWindChart, showCompetitorsChart, canReplayWhileLiveIsPossible, autoSelectMedia);
|
||||
|
||||
final ParallelExecutionCallback<List<String>> getLeaderboardNamesCallback = new ParallelExecutionCallback<List<String>>();
|
||||
final ParallelExecutionCallback<List<RegattaDTO>> getRegattasCallback = new ParallelExecutionCallback<List<RegattaDTO>>();
|
||||
@@ -221,7 +222,7 @@ public class RaceBoardEntryPoint extends AbstractEntryPoint {
|
||||
}
|
||||
FlowPanel logoAndTitlePanel = createLogoAndTitlePanel(raceBoardPanel);
|
||||
FlowPanel timePanel = createTimePanel(raceBoardPanel);
|
||||
p.addNorth(logoAndTitlePanel, 68);
|
||||
p.addNorth(logoAndTitlePanel, 68);
|
||||
p.addNorth(toolbarPanel, 40);
|
||||
p.addSouth(timePanel, 90);
|
||||
p.add(raceBoardPanel);
|
||||
|
||||
+7
-8
@@ -160,7 +160,6 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
|
||||
toolbarPanel = new FlowPanel();
|
||||
toolbarPanel.setWidth("100%");
|
||||
mainPanel.add(toolbarPanel);
|
||||
componentControlsPanel = new FlowPanel();
|
||||
componentControlsPanel.addStyleName("raceBoardNavigation");
|
||||
toolbarPanel.add(componentControlsPanel);
|
||||
@@ -181,7 +180,7 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
}
|
||||
|
||||
CompetitorsFilterSets loadedCompetitorsFilterSets = loadCompetitorsFilterSets();
|
||||
if(loadedCompetitorsFilterSets != null) {
|
||||
if (loadedCompetitorsFilterSets != null) {
|
||||
competitorsFilterSets = loadedCompetitorsFilterSets;
|
||||
insertSelectedCompetitorsFilter(competitorsFilterSets);
|
||||
} else {
|
||||
@@ -190,9 +189,9 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
}
|
||||
|
||||
// in case the URL configuration contains the name of a competitors filter set we try to activate it
|
||||
if(raceboardViewConfiguration.getActiveCompetitorsFilterSetName() != null) {
|
||||
for(FilterSet<CompetitorDTO, FilterWithUI<CompetitorDTO>> filterSet: competitorsFilterSets.getFilterSets()) {
|
||||
if(filterSet.getName().equals(raceboardViewConfiguration.getActiveCompetitorsFilterSetName())) {
|
||||
if (raceboardViewConfiguration.getActiveCompetitorsFilterSetName() != null) {
|
||||
for (FilterSet<CompetitorDTO, FilterWithUI<CompetitorDTO>> filterSet: competitorsFilterSets.getFilterSets()) {
|
||||
if (filterSet.getName().equals(raceboardViewConfiguration.getActiveCompetitorsFilterSetName())) {
|
||||
competitorsFilterSets.setActiveFilterSet(filterSet);
|
||||
break;
|
||||
}
|
||||
@@ -277,7 +276,7 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
}
|
||||
|
||||
private void addMediaSelectorToNavigationMenu() {
|
||||
MediaSelector mediaSelector = new MediaSelector(selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, stringMessages, errorReporter, this.user);
|
||||
MediaSelector mediaSelector = new MediaSelector(selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, stringMessages, errorReporter, this.user, getConfiguration().isAutoSelectMedia());
|
||||
// raceTimesInfoProvider.addRaceTimesInfoProviderListener(mediaSelector);
|
||||
timer.addPlayStateListener(mediaSelector);
|
||||
timer.addTimeListener(mediaSelector);
|
||||
@@ -461,7 +460,7 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
|
||||
private <SettingsType> void addComponentToNavigationMenu(final ComponentViewer componentViewer,
|
||||
final Component<SettingsType> component, boolean isToogleCheckboxEnabled) {
|
||||
final CheckBox checkBox= new CheckBox(component.getLocalizedShortName());
|
||||
final CheckBox checkBox = new CheckBox(component.getLocalizedShortName());
|
||||
checkBox.getElement().getStyle().setFloat(Style.Float.LEFT);
|
||||
|
||||
checkBox.setEnabled(isToogleCheckboxEnabled);
|
||||
@@ -489,7 +488,7 @@ public class RaceBoardPanel extends SimplePanel implements RegattaDisplayer, Rac
|
||||
|
||||
componentControlsPanel.add(checkBox);
|
||||
|
||||
if(component.hasSettings()) {
|
||||
if (component.hasSettings()) {
|
||||
Button settingsButton = new Button("");
|
||||
settingsButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
|
||||
+12
-3
@@ -12,14 +12,16 @@ public class RaceBoardViewConfiguration {
|
||||
private ViewModes viewMode;
|
||||
private String activeCompetitorsFilterSetName;
|
||||
private boolean canReplayDuringLiveRaces;
|
||||
private final boolean autoSelectMedia;
|
||||
|
||||
public static final String PARAM_VIEW_MODE = "viewMode";
|
||||
public static final String PARAM_VIEW_MODE = "viewMode";
|
||||
public static final String PARAM_VIEW_SHOW_LEADERBOARD = "viewShowLeaderboard";
|
||||
public static final String PARAM_VIEW_SHOW_NAVIGATION_PANEL = "viewShowNavigationPanel";
|
||||
public static final String PARAM_VIEW_SHOW_WINDCHART = "viewShowWindChart";
|
||||
public static final String PARAM_VIEW_SHOW_COMPETITORSCHART = "viewShowCompetitorsChart";
|
||||
public static final String PARAM_VIEW_COMPETITOR_FILTER = "viewCompetitorFilter";
|
||||
public static final String PARAM_CAN_REPLAY_DURING_LIVE_RACES = "canReplayDuringLiveRaces";
|
||||
public static final String PARAM_AUTOSELECT_MEDIA = "autoSelectMedia";
|
||||
|
||||
public static enum ViewModes { ONESCREEN };
|
||||
|
||||
@@ -28,16 +30,18 @@ public class RaceBoardViewConfiguration {
|
||||
showLeaderboard = true;
|
||||
showWindChart = false;
|
||||
showCompetitorsChart = false;
|
||||
}
|
||||
autoSelectMedia = false;
|
||||
}
|
||||
|
||||
public RaceBoardViewConfiguration(ViewModes viewMode, String activeCompetitorsFilterSetName,
|
||||
boolean showLeaderboard, boolean showWindChart, boolean showCompetitorsChart, boolean canReplayDuringLiveRaces) {
|
||||
boolean showLeaderboard, boolean showWindChart, boolean showCompetitorsChart, boolean canReplayDuringLiveRaces, boolean autoSelectMedia) {
|
||||
this.viewMode = viewMode;
|
||||
this.activeCompetitorsFilterSetName = activeCompetitorsFilterSetName;
|
||||
this.showLeaderboard = showLeaderboard;
|
||||
this.showWindChart = showWindChart;
|
||||
this.showCompetitorsChart = showCompetitorsChart;
|
||||
this.canReplayDuringLiveRaces = canReplayDuringLiveRaces;
|
||||
this.autoSelectMedia = autoSelectMedia;
|
||||
}
|
||||
|
||||
public boolean isShowLeaderboard() {
|
||||
@@ -63,4 +67,9 @@ public class RaceBoardViewConfiguration {
|
||||
public boolean isCanReplayDuringLiveRaces() {
|
||||
return canReplayDuringLiveRaces;
|
||||
}
|
||||
|
||||
public boolean isAutoSelectMedia() {
|
||||
return autoSelectMedia;
|
||||
}
|
||||
|
||||
}
|
||||
+16
-4
@@ -1256,13 +1256,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
GPSFixMoving fix = fixIter.next();
|
||||
while (fix != null && (fix.getTimePoint().compareTo(toTimePointExcluding) < 0 ||
|
||||
(fix.getTimePoint().equals(toTimePointExcluding) && toTimePointExcluding.equals(fromTimePoint)))) {
|
||||
Tack tack = trackedRace.getTack(competitor, fix.getTimePoint());
|
||||
Tack tack;
|
||||
try {
|
||||
tack = trackedRace.getTack(competitor, fix.getTimePoint());
|
||||
} catch (NoWindException nwe) {
|
||||
tack = null;
|
||||
}
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLeg(competitor,
|
||||
fix.getTimePoint());
|
||||
LegType legType = trackedLegOfCompetitor == null ? null : trackedRace.getTrackedLeg(
|
||||
trackedLegOfCompetitor.getLeg()).getLegType(fix.getTimePoint());
|
||||
Wind wind = trackedRace.getWind(fix.getPosition(),toTimePointExcluding);
|
||||
WindDTO windDTO = createWindDTOFromAlreadyAveraged(wind, toTimePointExcluding);
|
||||
WindDTO windDTO = wind == null ? null : createWindDTOFromAlreadyAveraged(wind, toTimePointExcluding);
|
||||
GPSFixDTO fixDTO = createGPSFixDTO(fix, fix.getSpeed(), windDTO, tack, legType, /* extrapolate */
|
||||
false);
|
||||
fixesForCompetitor.add(fixDTO);
|
||||
@@ -1272,13 +1277,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
// check if fix was at date and if extrapolation is requested
|
||||
if (!fix.getTimePoint().equals(toTimePointExcluding) && extrapolate) {
|
||||
Position position = track.getEstimatedPosition(toTimePointExcluding, extrapolate);
|
||||
Tack tack2 = trackedRace.getTack(competitor, toTimePointExcluding);
|
||||
Tack tack2;
|
||||
try {
|
||||
tack2 = trackedRace.getTack(competitor, toTimePointExcluding);
|
||||
} catch (NoWindException nwe) {
|
||||
tack2 = null;
|
||||
}
|
||||
LegType legType2 = trackedLegOfCompetitor == null ? null : trackedRace
|
||||
.getTrackedLeg(trackedLegOfCompetitor.getLeg()).getLegType(
|
||||
fix.getTimePoint());
|
||||
SpeedWithBearing speedWithBearing = track.getEstimatedSpeed(toTimePointExcluding);
|
||||
Wind wind2 = trackedRace.getWind(position, toTimePointExcluding);
|
||||
WindDTO windDTO2 = createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding);
|
||||
WindDTO windDTO2 = wind2 == null ? null : createWindDTOFromAlreadyAveraged(wind2, toTimePointExcluding);
|
||||
GPSFixDTO extrapolated = new GPSFixDTO(
|
||||
toPerCompetitorIdAsString.get(competitorDTO.getIdAsString()),
|
||||
position==null?null:new PositionDTO(position.getLatDeg(), position.getLngDeg()),
|
||||
@@ -2028,6 +2038,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
BoatClass boatClass = com.sap.sailing.domain.swisstimingadapter.DomainFactory.INSTANCE.getRaceTypeFromRaceID(rr.getRaceID()).getBoatClass();
|
||||
swissTimingRaceRecordDTO.boatClass = boatClass != null ? boatClass.getName() : null;
|
||||
swissTimingRaceRecordDTO.discipline = rr.getRaceID().length() >= 3 ? rr.getRaceID().substring(2, 3) : null;
|
||||
swissTimingRaceRecordDTO.hasCourse = rr.hasCourse();
|
||||
swissTimingRaceRecordDTO.hasStartlist = rr.hasStartlist();
|
||||
result.add(swissTimingRaceRecordDTO);
|
||||
}
|
||||
return result;
|
||||
|
||||
+3
@@ -13,6 +13,9 @@ public class SwissTimingRaceRecordDTO implements IsSerializable {
|
||||
public String boatClass;
|
||||
public String discipline;
|
||||
|
||||
public boolean hasCourse;
|
||||
public boolean hasStartlist;
|
||||
|
||||
public SwissTimingRaceRecordDTO() {}
|
||||
|
||||
public SwissTimingRaceRecordDTO(String id, String description, Date raceStartTime) {
|
||||
|
||||
+2
-1
@@ -43,8 +43,9 @@ public class TVEntryPoint extends AbstractEntryPoint {
|
||||
final boolean showCompetitorsChart = GwtHttpRequestUtils.getBooleanParameter(
|
||||
RaceBoardViewConfiguration.PARAM_VIEW_SHOW_COMPETITORSCHART, false /* default */);
|
||||
String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/);
|
||||
final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, false);
|
||||
raceboardViewConfig = new RaceBoardViewConfiguration(RaceBoardViewConfiguration.ViewModes.ONESCREEN,
|
||||
activeCompetitorsFilterSetName, showLeaderboard, showWindChart, showCompetitorsChart, /* canReplayWhileLiveIsPossible */ false);
|
||||
activeCompetitorsFilterSetName, showLeaderboard, showWindChart, showCompetitorsChart, /* canReplayWhileLiveIsPossible */ false, autoSelectMedia);
|
||||
|
||||
sailingService.getLeaderboardNames(new AsyncCallback<List<String>>() {
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -169,7 +169,7 @@ public class TVViewController implements RaceTimesInfoProviderListener {
|
||||
ScrollPanel leaderboardContentPanel = new ScrollPanel();
|
||||
leaderboardContentPanel.add(leaderboardPanel);
|
||||
dockPanel.add(leaderboardContentPanel);
|
||||
if(logoAndTitlePanel != null) {
|
||||
if (logoAndTitlePanel != null) {
|
||||
logoAndTitlePanel.setSubTitle(leaderboardName);
|
||||
}
|
||||
currentLiveRace = null;
|
||||
@@ -180,7 +180,7 @@ public class TVViewController implements RaceTimesInfoProviderListener {
|
||||
}
|
||||
|
||||
private void showRaceBoard() {
|
||||
if(activeTvView != TVViews.Raceboard) {
|
||||
if (activeTvView != TVViews.Raceboard) {
|
||||
clearContentPanels();
|
||||
RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace);
|
||||
raceBoardPanel.setSize("100%", "100%");
|
||||
|
||||
@@ -17,9 +17,8 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
org.json.simple;bundle-version="1.1.0",
|
||||
com.sap.sailing.domain.swisstimingadapter,
|
||||
org.objenesis;bundle-version="1.3.0",
|
||||
org.junit4;bundle-version="4.8.2",
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.mockito.mockito-core;bundle-version="1.9.5"
|
||||
Import-Package: com.sap.sailing.domain.common.impl,
|
||||
junit.framework;version="4.8.2",
|
||||
org.junit;version="4.8.2"
|
||||
Import-Package: com.sap.sailing.domain.common.impl
|
||||
|
||||
@@ -5,5 +5,5 @@ Bundle-SymbolicName: com.sap.sailing.operationaltransformation.test
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Require-Bundle: org.junit4;bundle-version="4.8.2"
|
||||
Fragment-Host: com.sap.sailing.operationaltransformation
|
||||
Import-Package: org.junit;version="4.8.2"
|
||||
+11
-3
@@ -24,6 +24,12 @@ import com.sap.sailing.selenium.test.PageArea;
|
||||
public class TracTracEventManagementPanel extends PageArea {
|
||||
@FindBy(how = BySeleniumId.class, using = "JSONURL")
|
||||
private WebElement jsonURLField;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "LiveURI")
|
||||
private WebElement liveURIField;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "StoredURI")
|
||||
private WebElement storedURIField;
|
||||
|
||||
@FindBy(how = BySeleniumId.class, using = "ListRaces")
|
||||
private WebElement listRacesButton;
|
||||
@@ -55,9 +61,11 @@ public class TracTracEventManagementPanel extends PageArea {
|
||||
* The URL for which the races are to list.
|
||||
*/
|
||||
public void listRaces(String url) {
|
||||
this.jsonURLField.clear();
|
||||
this.jsonURLField.sendKeys(url);
|
||||
this.listRacesButton.click();
|
||||
liveURIField.clear();
|
||||
storedURIField.clear();
|
||||
jsonURLField.clear();
|
||||
jsonURLField.sendKeys(url);
|
||||
listRacesButton.click();
|
||||
|
||||
waitForAjaxRequests();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ Bundle-SymbolicName: com.sap.sailing.server.gateway.ess40
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Import-Package: org.apache.jasper.servlet,
|
||||
org.osgi.framework;version="1.3.0",
|
||||
Import-Package: org.osgi.framework;version="1.3.0",
|
||||
org.osgi.util.tracker;version="1.3.1",
|
||||
com.sap.sailing.server
|
||||
Bundle-ActivationPolicy: lazy
|
||||
@@ -17,9 +16,6 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.mongodb.driver;bundle-version="2.6.2",
|
||||
javax.servlet;bundle-version="2.6.0",
|
||||
com.sap.sailing.domain.common,
|
||||
javax.servlet.jsp.jstl;bundle-version="1.2.0",
|
||||
javax.servlet.jsp;bundle-version="2.2.0",
|
||||
javax.el;bundle-version="2.2.0",
|
||||
com.sap.sailing.server.gateway
|
||||
Bundle-ClassPath: .
|
||||
Web-ContextPath: /gateway-ess40
|
||||
@@ -1,120 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@ page import="java.text.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.leaderboard.Leaderboard" %>
|
||||
<%@ page import="com.sap.sailing.domain.base.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.base.impl.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.common.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.tracking.*" %>
|
||||
<%@ page pageEncoding="UTF-8" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<title>SAP Sailing Analytics Leaderboard</title>
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/leaderboard.css" type="text/css"></link>
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/tablesorter.css" type="text/css"></link>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery-latest.js"></script>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery.tablesorter.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#leaderboardTable").tablesorter();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%
|
||||
TimePoint timePoint = MillisecondsTimePoint.now();
|
||||
Leaderboard leaderboard = (Leaderboard) request.getAttribute("leaderboard");
|
||||
|
||||
// competitors are ordered according to total rank
|
||||
List<Competitor> competitorsFromBestToWorst = leaderboard.getCompetitorsFromBestToWorst(timePoint);
|
||||
Map<RaceColumn, List<Competitor>> rankedCompetitorsPerColumn = new HashMap<RaceColumn, List<Competitor>>();
|
||||
Iterable<RaceColumn> raceColumns = leaderboard.getRaceColumns();
|
||||
|
||||
NumberFormat scoreFormat = NumberFormat.getNumberInstance();
|
||||
int digitPresicion = 1;
|
||||
scoreFormat.setMinimumFractionDigits(digitPresicion);
|
||||
scoreFormat.setMaximumFractionDigits(digitPresicion);
|
||||
|
||||
String imgFlagPath = "/gwt/images/flags/";
|
||||
%>
|
||||
<h3>Leaderboard: <%= leaderboard.getName() %></h3>
|
||||
<table id="leaderboardTable" class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Rank</th>
|
||||
<th>Team</th>
|
||||
<% for (RaceColumn raceColumn : raceColumns) { %>
|
||||
<th><%= raceColumn.getName() %></th>
|
||||
<% } %>
|
||||
<th>Points</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%
|
||||
for (Competitor competitor : competitorsFromBestToWorst) {
|
||||
int totalRank = competitorsFromBestToWorst.indexOf(competitor) + 1;
|
||||
Nationality nationality = competitor.getTeam().getNationality();
|
||||
Double totalPoints = leaderboard.getTotalPoints(competitor, timePoint);
|
||||
if(leaderboard.hasCarriedPoints(competitor)) {
|
||||
Double carriedPoints = leaderboard.getCarriedPoints(competitor);
|
||||
if(carriedPoints != null) {
|
||||
totalPoints = totalPoints != null ? totalPoints += carriedPoints : carriedPoints;
|
||||
}
|
||||
}
|
||||
%>
|
||||
<tr>
|
||||
<td><%= totalRank %></td>
|
||||
<td style="white-space:nowrap;"><img src="<%= imgFlagPath + nationality.getCountryCode().getTwoLetterISOCode().toLowerCase() + ".png"%>" /> <%= competitor.getName() %></td>
|
||||
<% for (RaceColumn raceColumn : raceColumns) {
|
||||
List<Competitor> rankedCompetitorsForColumn = rankedCompetitorsPerColumn.get(raceColumn);
|
||||
if (rankedCompetitorsForColumn == null) {
|
||||
rankedCompetitorsForColumn = leaderboard.getCompetitorsFromBestToWorst(raceColumn, timePoint);
|
||||
rankedCompetitorsPerColumn.put(raceColumn, rankedCompetitorsForColumn);
|
||||
}
|
||||
Double netRacePoints = leaderboard.getNetPoints(competitor, raceColumn, timePoint);
|
||||
Double totalRacePoints = leaderboard.getTotalPoints(competitor, raceColumn, timePoint);
|
||||
MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint);
|
||||
int rank = rankedCompetitorsForColumn.indexOf(competitor)+1;
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(competitor);
|
||||
if (trackedRace != null) {
|
||||
int raceRank = trackedRace.getRank(competitor, timePoint);
|
||||
}
|
||||
boolean isDiscarded = leaderboard.isDiscarded(competitor, raceColumn, timePoint);
|
||||
boolean isCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn);
|
||||
|
||||
String racePointsStyleClasses = "";
|
||||
|
||||
String racePoints = " ";
|
||||
if (maxPointsReason == null || maxPointsReason == MaxPointsReason.NONE) {
|
||||
if (!isDiscarded) {
|
||||
racePointsStyleClasses = "leaderboard-points-TotalPoints-NotDiscarded";
|
||||
if(totalRacePoints != null) {
|
||||
racePoints = scoreFormat.format(totalRacePoints);
|
||||
}
|
||||
} else {
|
||||
racePointsStyleClasses = "leaderboard-points-TotalPoints-Discarded";
|
||||
if(netRacePoints != null) {
|
||||
racePoints = scoreFormat.format(netRacePoints);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isDiscarded) {
|
||||
racePointsStyleClasses = "leaderboard-points-MaxPoints-NotDiscarded";
|
||||
} else {
|
||||
racePointsStyleClasses = "leaderboard-points-MaxPoints-Discarded";
|
||||
}
|
||||
racePoints = maxPointsReason.name();
|
||||
}
|
||||
%>
|
||||
<td class="<%= racePointsStyleClasses %>"><%= racePoints %></td>
|
||||
<% } %>
|
||||
<td><%= totalPoints %></td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,135 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@ page import="java.text.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.leaderboard.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.leaderboard.meta.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.base.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.base.impl.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.common.*" %>
|
||||
<%@ page import="com.sap.sailing.domain.tracking.*" %>
|
||||
<%@ page pageEncoding="UTF-8" %>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<title>SAP Sailing Analytics Leaderboard</title>
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/leaderboard.css" type="text/css"></link>
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/tablesorter.css" type="text/css"></link>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery-latest.js"></script>
|
||||
<script type="text/javascript" src="<%= request.getContextPath() %>/js/jquery.tablesorter.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#leaderboardTable").tablesorter();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<%
|
||||
TimePoint timePoint = MillisecondsTimePoint.now();
|
||||
LeaderboardGroupMetaLeaderboard leaderboard = (LeaderboardGroupMetaLeaderboard) request.getAttribute("leaderboard");
|
||||
Boolean showRaceDetails = (Boolean) request.getAttribute("showRaceDetails");
|
||||
|
||||
// competitors are ordered according to total rank
|
||||
List<Competitor> competitorsFromBestToWorst = leaderboard.getCompetitorsFromBestToWorst(timePoint);
|
||||
Map<RaceColumn, List<Competitor>> rankedCompetitorsPerColumn = new HashMap<RaceColumn, List<Competitor>>();
|
||||
Iterable<RaceColumn> raceColumns = leaderboard.getRaceColumns();
|
||||
List<Competitor> suppressedCompetitors = new ArrayList<Competitor>();
|
||||
for(Competitor c: leaderboard.getSuppressedCompetitors()) {
|
||||
suppressedCompetitors.add(c);
|
||||
}
|
||||
|
||||
NumberFormat scoreFormat = NumberFormat.getNumberInstance();
|
||||
int digitPresicion = 1;
|
||||
scoreFormat.setMinimumFractionDigits(digitPresicion);
|
||||
scoreFormat.setMaximumFractionDigits(digitPresicion);
|
||||
|
||||
String imgFlagPath = "/gwt/images/flags/";
|
||||
%>
|
||||
<h3>Overall Leaderboard: <%= leaderboard.getName() %></h3>
|
||||
<table id="leaderboardTable" class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Rank</th>
|
||||
<th>Team</th>
|
||||
<% if(showRaceDetails) {
|
||||
for (RaceColumn raceColumn : raceColumns) { %>
|
||||
<th><%
|
||||
String raceColumnName = raceColumn.getName();
|
||||
String prefixToCut = "Extreme 40 ";
|
||||
if(raceColumnName.startsWith(prefixToCut)) {
|
||||
raceColumnName = raceColumnName.substring(prefixToCut.length(), raceColumnName.length());
|
||||
}
|
||||
%><%= raceColumnName %></th>
|
||||
<% } } %>
|
||||
<th>Points</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%
|
||||
for (Competitor competitor : competitorsFromBestToWorst) {
|
||||
int totalRank = competitorsFromBestToWorst.indexOf(competitor) + 1;
|
||||
Nationality nationality = competitor.getTeam().getNationality();
|
||||
Double totalPoints = leaderboard.getTotalPoints(competitor, timePoint);
|
||||
if(leaderboard.hasCarriedPoints(competitor)) {
|
||||
Double carriedPoints = leaderboard.getCarriedPoints(competitor);
|
||||
if(carriedPoints != null) {
|
||||
totalPoints = totalPoints != null ? totalPoints += carriedPoints : carriedPoints;
|
||||
}
|
||||
}
|
||||
if(!suppressedCompetitors.contains(competitor)) {
|
||||
%>
|
||||
<tr>
|
||||
<td><%= totalRank %></td>
|
||||
<td style="white-space:nowrap;"><img src="<%= imgFlagPath + nationality.getCountryCode().getTwoLetterISOCode().toLowerCase() + ".png"%>" /> <%= competitor.getName() %></td>
|
||||
<% if(showRaceDetails) {
|
||||
for (RaceColumn raceColumn : raceColumns) {
|
||||
List<Competitor> rankedCompetitorsForColumn = rankedCompetitorsPerColumn.get(raceColumn);
|
||||
if (rankedCompetitorsForColumn == null) {
|
||||
rankedCompetitorsForColumn = leaderboard.getCompetitorsFromBestToWorst(raceColumn, timePoint);
|
||||
rankedCompetitorsPerColumn.put(raceColumn, rankedCompetitorsForColumn);
|
||||
}
|
||||
Double netRacePoints = leaderboard.getNetPoints(competitor, raceColumn, timePoint);
|
||||
Double totalRacePoints = leaderboard.getTotalPoints(competitor, raceColumn, timePoint);
|
||||
MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumn, timePoint);
|
||||
int rank = rankedCompetitorsForColumn.indexOf(competitor)+1;
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(competitor);
|
||||
if (trackedRace != null) {
|
||||
int raceRank = trackedRace.getRank(competitor, timePoint);
|
||||
}
|
||||
boolean isDiscarded = leaderboard.isDiscarded(competitor, raceColumn, timePoint);
|
||||
boolean isCorrected = leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumn);
|
||||
|
||||
String racePointsStyleClasses = "";
|
||||
|
||||
String racePoints = " ";
|
||||
if (maxPointsReason == null || maxPointsReason == MaxPointsReason.NONE) {
|
||||
if (!isDiscarded) {
|
||||
racePointsStyleClasses = "leaderboard-points-TotalPoints-NotDiscarded";
|
||||
if(totalRacePoints != null) {
|
||||
racePoints = scoreFormat.format(totalRacePoints);
|
||||
}
|
||||
} else {
|
||||
racePointsStyleClasses = "leaderboard-points-TotalPoints-Discarded";
|
||||
if(netRacePoints != null) {
|
||||
racePoints = scoreFormat.format(netRacePoints);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isDiscarded) {
|
||||
racePointsStyleClasses = "leaderboard-points-MaxPoints-NotDiscarded";
|
||||
} else {
|
||||
racePointsStyleClasses = "leaderboard-points-MaxPoints-Discarded";
|
||||
}
|
||||
racePoints = maxPointsReason.name();
|
||||
}
|
||||
%>
|
||||
<td class="<%= racePointsStyleClasses %>"><%= racePoints %></td>
|
||||
<% } } %>
|
||||
<td><%= totalPoints %></td>
|
||||
</tr>
|
||||
<% } } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,39 +4,6 @@
|
||||
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">
|
||||
|
||||
<servlet id="jsp">
|
||||
<servlet-name>jspServlet</servlet-name>
|
||||
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>logVerbosityLevel</param-name>
|
||||
<param-value>DEBUG</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>fork</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>keepgenerated</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
|
||||
<load-on-startup>0</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>jspServlet</servlet-name>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ESS40JspForwardServlet</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.ess40.ESS40JspForwardServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>ESS40JspForwardServlet</servlet-name>
|
||||
<url-pattern>/html/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ESS40ResultsAsCSVServlet</servlet-name>
|
||||
|
||||
-58
@@ -1,58 +0,0 @@
|
||||
package com.sap.sailing.server.gateway.ess40;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.gateway.SailingServerHttpServlet;
|
||||
|
||||
public class ESS40JspForwardServlet extends SailingServerHttpServlet {
|
||||
private static final long serialVersionUID = -1017961881555515288L;
|
||||
|
||||
private static final String PARAM_NAME_LEADERBOARDNAME = "leaderboardName";
|
||||
private static final String PARAM_NAME_SHOWDETAILS = "showDetails";
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
RacingEventService racingEventService = getService();
|
||||
String pathInfo = request.getPathInfo();
|
||||
String jspPath = "/WEB-INF/jsp";
|
||||
String leaderboardNameParam = request.getParameter(PARAM_NAME_LEADERBOARDNAME);
|
||||
String showDetailsParam = request.getParameter(PARAM_NAME_SHOWDETAILS);
|
||||
Boolean showRaceDetails = showDetailsParam != null && showDetailsParam.equalsIgnoreCase("true");
|
||||
|
||||
if (leaderboardNameParam == null) {
|
||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "You need to specify a leaderboard name using the "+
|
||||
PARAM_NAME_LEADERBOARDNAME+" parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardNameParam);
|
||||
|
||||
if(pathInfo.equals("/leaderboard") && racingEventService != null && leaderboard != null) {
|
||||
String jspFile = null;
|
||||
if(leaderboard instanceof LeaderboardGroupMetaLeaderboard) {
|
||||
jspFile = "overallLeaderboard.jsp";
|
||||
} else {
|
||||
jspFile = "leaderboard.jsp";
|
||||
}
|
||||
request.setAttribute("showRaceDetails", showRaceDetails);
|
||||
request.setAttribute("leaderboard", leaderboard);
|
||||
request.setAttribute("racingEventService", racingEventService);
|
||||
|
||||
ServletContext sc = getServletContext();
|
||||
RequestDispatcher requestDispatcher = sc.getRequestDispatcher(jspPath + "/" + jspFile);
|
||||
requestDispatcher.forward(request, response);
|
||||
} else {
|
||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error during leaderboard export.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,8 @@ Bundle-SymbolicName: com.sap.sailing.server.gateway.serialization.test
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Require-Bundle: com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0",
|
||||
com.sap.sailing.domain;bundle-version="1.0.0",
|
||||
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.junit4;bundle-version="4.8.2",
|
||||
com.sap.sailing.domain.shared.android,
|
||||
@@ -14,5 +14,3 @@ Require-Bundle: com.sap.sailing.server.gateway.serialization;bundle-version="1.0
|
||||
org.mockito.mockito-core;bundle-version="1.9.5",
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.objenesis;bundle-version="1.3.0"
|
||||
Import-Package: org.json.simple
|
||||
Bundle-ClassPath: .
|
||||
+1
-1
@@ -13,7 +13,7 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
public class SeriesJsonSerializer implements JsonSerializer<Series> {
|
||||
public static final String FIELD_NAME = "name";
|
||||
public static final String FIELD_FLEETS = "fleets";
|
||||
public static final String FIELD_RACES = "races";
|
||||
public static final String FIELD_RACES = "races"; // TODO: 'races' is wrong here... it's actually 'raceColumns'
|
||||
public static final String FIELD_TRACKED_RACES = "trackedRaces";
|
||||
public static final String FIELD_STARTS_WITH_ZERO_SCORE = "startsWithZeroScore";
|
||||
public static final String FIELD_IS_MEDAL_SERIES = "isMedalSeries";
|
||||
|
||||
@@ -9,6 +9,6 @@ Fragment-Host: com.sap.sailing.server.gateway
|
||||
Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
|
||||
com.sap.sailing.domain.test,
|
||||
org.hamcrest;bundle-version="1.1.0",
|
||||
org.objenesis;bundle-version="1.3.0"
|
||||
Import-Package: com.sap.sailing.server.impl,
|
||||
org.junit;version="4.8.2"
|
||||
org.objenesis;bundle-version="1.3.0",
|
||||
org.junit4;bundle-version="4.8.2"
|
||||
Import-Package: com.sap.sailing.server.impl
|
||||
+4
-2
@@ -8,6 +8,7 @@ import static org.mockito.Mockito.when;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@@ -26,7 +27,6 @@ import com.sap.sailing.domain.base.impl.NationalityImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.AbstractTimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
@@ -37,6 +37,8 @@ import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
public abstract class AbstractJsonExportTest {
|
||||
protected RacingEventService racingEventService;
|
||||
protected MongoDBService service;
|
||||
|
||||
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
|
||||
public void setUp() {
|
||||
service = MongoDBService.INSTANCE;
|
||||
@@ -75,7 +77,7 @@ public abstract class AbstractJsonExportTest {
|
||||
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
|
||||
TimePoint result = null;
|
||||
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
|
||||
Date date = AbstractTimePoint.TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
|
||||
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
|
||||
result = new MillisecondsTimePoint(date);
|
||||
}
|
||||
return result;
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.sap.sailing.server.gateway.test.jaxrs;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.base.impl.NationalityImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.mongodb.MongoDBConfiguration;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.impl.RacingEventServiceImpl;
|
||||
|
||||
public abstract class AbstractJaxRsApiTest {
|
||||
protected RacingEventService racingEventService;
|
||||
protected MongoDBService service;
|
||||
|
||||
protected static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
|
||||
public void setUp() {
|
||||
service = MongoDBService.INSTANCE;
|
||||
service.setConfiguration(MongoDBConfiguration.getDefaultTestConfiguration());
|
||||
service.getDB().dropDatabase();
|
||||
|
||||
racingEventService = new RacingEventServiceImpl();
|
||||
}
|
||||
|
||||
protected <T extends AbstractSailingServerResource> T spyResource(T resource) {
|
||||
T spyResource = spy(resource);
|
||||
|
||||
doReturn(racingEventService).when(spyResource).getService();
|
||||
return spyResource;
|
||||
}
|
||||
|
||||
protected String decodeResponseFromByteArray(Response response) throws UnsupportedEncodingException {
|
||||
byte[] entity = (byte[]) response.getEntity();
|
||||
|
||||
return new String(entity, "UTF-8");
|
||||
}
|
||||
|
||||
protected TimePoint parseTimepointFromJsonString(String timePointAsJsonString) throws ParseException {
|
||||
TimePoint result = null;
|
||||
if(timePointAsJsonString != null && !timePointAsJsonString.isEmpty()) {
|
||||
Date date = TIMEPOINT_FORMATTER.parse(timePointAsJsonString);
|
||||
result = new MillisecondsTimePoint(date);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<Competitor> createCompetitors(int numberOfCompetitorsToCreate) {
|
||||
List<Competitor> result = new ArrayList<Competitor>();
|
||||
BoatClass boatClass = new BoatClassImpl("505", /* typicallyStartsUpwind */ true);
|
||||
for (int i = 1; i <= numberOfCompetitorsToCreate; i++) {
|
||||
String competitorName = "C" + i;
|
||||
Competitor competitor = new CompetitorImpl(123, competitorName, new TeamImpl("STG", Collections.singleton(
|
||||
new PersonImpl(competitorName, new NationalityImpl("GER"),
|
||||
/* dateOfBirth */ null, "This is famous "+competitorName)),
|
||||
new PersonImpl("Rigo van Maas", new NationalityImpl("NED"),
|
||||
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl(competitorName + "'s boat",
|
||||
boatClass, null));
|
||||
result.add(competitor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.sap.sailing.server.gateway.test.jaxrs;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.Series;
|
||||
import com.sap.sailing.domain.base.impl.FleetImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.SeriesImpl;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.server.gateway.jaxrs.api.RegattasResource;
|
||||
|
||||
public class RegattasResourceTest extends AbstractJaxRsApiTest {
|
||||
private String boatClassName = "49er";
|
||||
private String regattaName = "TestRegatta";
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
super.setUp();
|
||||
List<Series> series = new ArrayList<Series>();
|
||||
List<Fleet> fleets = new ArrayList<Fleet>();
|
||||
List<String> raceColumnNames = new ArrayList<String>();
|
||||
fleets.add(new FleetImpl("Fleet1"));
|
||||
fleets.add(new FleetImpl("Fleet2"));
|
||||
Series testSeries = new SeriesImpl("TestSeries", /* isMedal */false, fleets,
|
||||
raceColumnNames, /* trackedRegattaRegistry */null);
|
||||
series.add(testSeries);
|
||||
racingEventService.createRegatta(regattaName, boatClassName, UUID.randomUUID(), series, /*persistent*/ true,
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null);
|
||||
testSeries.addRaceColumn("R1", /* trackedRegattaRegistry */ null);
|
||||
testSeries.addRaceColumn("R2", /* trackedRegattaRegistry */ null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRegattas() throws Exception {
|
||||
RegattasResource resource = new RegattasResource();
|
||||
RegattasResource spyResource = spyResource(resource);
|
||||
|
||||
Response regattasResponse = spyResource.getRegattas();
|
||||
|
||||
String jsonString = decodeResponseFromByteArray(regattasResponse);
|
||||
Object obj= JSONValue.parse(jsonString);
|
||||
JSONArray array= (JSONArray) obj;
|
||||
|
||||
assertTrue(array.size() == 1);
|
||||
|
||||
JSONObject firstElement = (JSONObject) array.get(0);
|
||||
String jsonName = (String) firstElement.get("name");
|
||||
String jsonBoatClass = (String) firstElement.get("boatclass");
|
||||
|
||||
assertTrue(RegattaImpl.getDefaultName(regattaName, boatClassName).equals(jsonName));
|
||||
assertTrue(boatClassName.equals(jsonBoatClass));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,9 @@ Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Import-Package: com.sap.sailing.server,
|
||||
com.sap.sailing.server.operationaltransformation,
|
||||
org.apache.jasper.servlet,
|
||||
javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;version="1.1.1",
|
||||
javax.ws.rs.ext;version="1.1.1",
|
||||
org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.3.0",
|
||||
@@ -25,17 +27,16 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.udpconnector,
|
||||
org.jdom;bundle-version="1.0.0",
|
||||
com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0",
|
||||
javax.servlet.jsp.jstl;bundle-version="1.2.0",
|
||||
javax.servlet.jsp;bundle-version="2.2.0",
|
||||
javax.el;bundle-version="2.1.0",
|
||||
rome;bundle-version="1.0.0",
|
||||
com.sap.sailing.domain.shared.android;bundle-version="1.0.0",
|
||||
com.sap.sailing.server.trackfiles;bundle-version="1.0.0",
|
||||
org.eclipse.jetty.websocket.api;bundle-version="9.0.4",
|
||||
org.eclipse.jetty.websocket.server;bundle-version="9.0.4",
|
||||
org.eclipse.jetty.websocket.servlet;bundle-version="9.0.4",
|
||||
org.eclipse.jetty.websocket.client;bundle-version="9.0.4",
|
||||
org.eclipse.jetty.websocket.common;bundle-version="9.0.4"
|
||||
org.eclipse.jetty.websocket.common;bundle-version="9.0.4",
|
||||
javax.validation;bundle-version="1.0.0",
|
||||
com.sun.jersey;bundle-version="1.17.0",
|
||||
org.objectweb.asm;bundle-version="3.3.1"
|
||||
Bundle-ClassPath: .
|
||||
Web-ContextPath: /sailingserver
|
||||
Export-Package: com.sap.sailing.server.gateway
|
||||
@@ -177,15 +177,6 @@
|
||||
<url-pattern>/expeditionWindStatus</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>LiveRaceRankingRssGetServlet</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.impl.LiveRaceRankingRssGetServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>LiveRaceRankingRssGetServlet</servlet-name>
|
||||
<url-pattern>/rss/liveRaceRanking</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>MasterDataByLeaderboardGroupJsonGetServlet</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.impl.MasterDataByLeaderboardGroupJsonGetServlet</servlet-class>
|
||||
@@ -203,26 +194,6 @@
|
||||
<servlet-name>TrackFilesExportPostServlet</servlet-name>
|
||||
<url-pattern>/trackfiles</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
<servlet id="jsp">
|
||||
<servlet-name>jspServet</servlet-name>
|
||||
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>logVerbosityLevel</param-name>
|
||||
<param-value>DEBUG</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>fork</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>keepgenerated</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
|
||||
<load-on-startup>0</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>websockettest</servlet-name>
|
||||
@@ -234,10 +205,32 @@
|
||||
<url-pattern>/websockettest</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
<servlet-mapping>
|
||||
<servlet-name>jspServet</servlet-name>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
</servlet-mapping>
|
||||
-->
|
||||
<servlet>
|
||||
<servlet-name>Jersey REST API</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>com.sap.sailing.server.gateway.jaxrs.api.RestApiApplication</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Jersey REST API</servlet-name>
|
||||
<url-pattern>/api/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Jersey REST SPI</servlet-name>
|
||||
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>com.sap.sailing.server.gateway.jaxrs.spi.RestSpiApplication</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Jersey REST SPI</servlet-name>
|
||||
<url-pattern>/spi/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
Whitespace-only changes.
@@ -26,7 +26,7 @@ body {
|
||||
font-size: 14px;
|
||||
font-family: OpenSansRegular, Arial, Verdana, sans-serif;
|
||||
font-weight: normal;
|
||||
margin: 0px;
|
||||
margin: 10px;
|
||||
padding: 0px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
+10
-4
@@ -2,6 +2,7 @@ package com.sap.sailing.server.gateway.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -59,6 +60,7 @@ public class LeaderboardJsonGetServlet extends AbstractJsonHttpServlet implement
|
||||
|
||||
// for backward compatibility the default result state is live
|
||||
private final ResultStates DEFAULT_RESULT_STATE = ResultStates.Live;
|
||||
private static SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
|
||||
private static final int MAX_TOTAL_NUMBER_OF_CACHE_ENTRIES = 1000;
|
||||
|
||||
@@ -220,7 +222,7 @@ public class LeaderboardJsonGetServlet extends AbstractJsonHttpServlet implement
|
||||
setJsonResponseHeader(resp);
|
||||
synchronized (jsonLeaderboardAsString) {
|
||||
int indexOfFirstOpeningBrace = jsonLeaderboardAsString.indexOf("{");
|
||||
final String requestTimePointAsJson = "\"requestTimepoint\": \""+requestTimePoint.toString()+"\", ";
|
||||
final String requestTimePointAsJson = "\"requestTimepoint\": \"" + formatTimePoint(requestTimePoint) + "\", ";
|
||||
if (indexOfFirstOpeningBrace >= 0) {
|
||||
jsonLeaderboardAsString.insert(indexOfFirstOpeningBrace+1, requestTimePointAsJson);
|
||||
}
|
||||
@@ -319,6 +321,10 @@ public class LeaderboardJsonGetServlet extends AbstractJsonHttpServlet implement
|
||||
return jsonLeaderboard;
|
||||
}
|
||||
|
||||
private String formatTimePoint(TimePoint timepoint) {
|
||||
return timepoint == null ? null : TIMEPOINT_FORMATTER.format(timepoint.asDate());
|
||||
}
|
||||
|
||||
private JSONObject createEmptyLeaderboardJson(Leaderboard leaderboard,
|
||||
ResultStates resultState, TimePoint requestTimePoint, Integer maxCompetitorsCount) throws NoWindException {
|
||||
JSONObject jsonLeaderboard = new JSONObject();
|
||||
@@ -365,9 +371,9 @@ public class LeaderboardJsonGetServlet extends AbstractJsonHttpServlet implement
|
||||
jsonLeaderboard.put("name", leaderboard.getName());
|
||||
|
||||
// for backward compatibility
|
||||
jsonLeaderboard.put("timepoint", resultTimePoint != null ? resultTimePoint.toString() : null);
|
||||
jsonLeaderboard.put("timepoint", formatTimePoint(resultTimePoint));
|
||||
|
||||
jsonLeaderboard.put("resultTimepoint", resultTimePoint != null ? resultTimePoint.toString() : null);
|
||||
jsonLeaderboard.put("resultTimepoint", formatTimePoint(resultTimePoint));
|
||||
jsonLeaderboard.put("resultState", resultState.name());
|
||||
jsonLeaderboard.put("maxCompetitorsCount", maxCompetitorsCount);
|
||||
|
||||
@@ -375,7 +381,7 @@ public class LeaderboardJsonGetServlet extends AbstractJsonHttpServlet implement
|
||||
if (scoreCorrection != null) {
|
||||
jsonLeaderboard.put("scoringComment", scoreCorrection.getComment());
|
||||
TimePoint lastUpdateTimepoint = scoreCorrection.getTimePointOfLastCorrectionsValidity();
|
||||
jsonLeaderboard.put("lastScoringUpdate", lastUpdateTimepoint != null ? lastUpdateTimepoint.asDate().toString(): null);
|
||||
jsonLeaderboard.put("lastScoringUpdate", formatTimePoint(lastUpdateTimepoint));
|
||||
} else {
|
||||
jsonLeaderboard.put("scoringComment", null);
|
||||
jsonLeaderboard.put("lastScoringUpdate", null);
|
||||
|
||||
-158
@@ -1,158 +0,0 @@
|
||||
package com.sap.sailing.server.gateway.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.gateway.SailingServerHttpServlet;
|
||||
import com.sun.syndication.feed.synd.SyndContent;
|
||||
import com.sun.syndication.feed.synd.SyndContentImpl;
|
||||
import com.sun.syndication.feed.synd.SyndEntry;
|
||||
import com.sun.syndication.feed.synd.SyndEntryImpl;
|
||||
import com.sun.syndication.feed.synd.SyndFeed;
|
||||
import com.sun.syndication.feed.synd.SyndFeedImpl;
|
||||
import com.sun.syndication.io.SyndFeedOutput;
|
||||
|
||||
public class LiveRaceRankingRssGetServlet extends SailingServerHttpServlet {
|
||||
private static final long serialVersionUID = -508373964426868319L;
|
||||
private static final String PARAM_NAME_LEADERBOARDNAME = "leaderboardName";
|
||||
private static final String PARAM_MAX_COMPETITORS = "max";
|
||||
private String charEncoding = "UTF-8";
|
||||
private int maxCompetitorsToShow = 1000;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
// to allow access to the rss feed directly from a client side javascript
|
||||
resp.setHeader("Access-Control-Allow-Origin", "*");
|
||||
resp.setContentType("application/rss+xml");
|
||||
resp.setCharacterEncoding(charEncoding);
|
||||
|
||||
TimePoint timePoint = MillisecondsTimePoint.now();
|
||||
String leaderboardName = req.getParameter(PARAM_NAME_LEADERBOARDNAME);
|
||||
String maxCompetitorsParam = req.getParameter(PARAM_MAX_COMPETITORS);
|
||||
if(maxCompetitorsParam != null) {
|
||||
try {
|
||||
maxCompetitorsToShow = Integer.parseInt(maxCompetitorsParam);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (leaderboardName == null) {
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Need to specify a leaderboard name using the "+
|
||||
PARAM_NAME_LEADERBOARDNAME+" parameter");
|
||||
} else {
|
||||
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||
if (leaderboard == null) {
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Leaderboard "+leaderboardName+" not found");
|
||||
} else {
|
||||
try {
|
||||
RaceColumn raceColumnToShow = null;
|
||||
TrackedRace liveTrackedRace = null;
|
||||
|
||||
// find a live race in the leaderboard
|
||||
Iterable<RaceColumn> races = leaderboard.getRaceColumns();
|
||||
for (RaceColumn raceInLeaderboard : races) {
|
||||
for (Fleet fleet : raceInLeaderboard.getFleets()) {
|
||||
TrackedRace trackedRaceOfFleet = raceInLeaderboard.getTrackedRace(fleet);
|
||||
if(trackedRaceOfFleet != null && isLive(trackedRaceOfFleet)) {
|
||||
raceColumnToShow = raceInLeaderboard;
|
||||
liveTrackedRace = trackedRaceOfFleet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SyndFeed feed = new SyndFeedImpl();
|
||||
String title = leaderboard.getName();
|
||||
feed.setTitle(title);
|
||||
feed.setFeedType("rss_2.0");
|
||||
feed.setLink("http://www.sapsaling.com");
|
||||
feed.setDescription("SAP Sailing Analytics");
|
||||
feed.setPublishedDate(new Date());
|
||||
feed.setEncoding(charEncoding);
|
||||
|
||||
List<SyndEntry> entries = new ArrayList<SyndEntry>();
|
||||
SyndContent description = new SyndContentImpl();
|
||||
SyndEntry entry = new SyndEntryImpl();
|
||||
entry.setLink("http://www.sapsailing.com");
|
||||
description.setType("text/plain");
|
||||
|
||||
if(raceColumnToShow != null && liveTrackedRace != null) {
|
||||
String entryTitle = "Live ranking of race '" + raceColumnToShow.getName() + "'";
|
||||
entry.setTitle(entryTitle);
|
||||
|
||||
|
||||
|
||||
List<Competitor> competitorsFromBestToWorst = leaderboard.getCompetitorsFromBestToWorst(raceColumnToShow, timePoint);
|
||||
int currentCompetitorCounter = 0;
|
||||
String feedText = "";
|
||||
|
||||
for (Competitor competitor : competitorsFromBestToWorst) {
|
||||
if(currentCompetitorCounter == maxCompetitorsToShow) {
|
||||
break;
|
||||
}
|
||||
currentCompetitorCounter++;
|
||||
String sailID = competitor.getBoat().getSailID();
|
||||
feedText += currentCompetitorCounter + ". " + sailID + "\n";
|
||||
|
||||
// String competitorName = competitor.getName();
|
||||
// final String displayName = leaderboard.getDisplayName(competitor);
|
||||
// String id = competitor.getId().toString();
|
||||
// Nationality nationality = competitor.getTeam().getNationality();
|
||||
// String nat = nationality != null ? nationality.getThreeLetterIOCAcronym(): null;
|
||||
// String countryCode = nationality != null ? nationality.getCountryCode().getTwoLetterISOCode(): null;
|
||||
// String totalRank = "" +competitorsFromBestToWorst.indexOf(competitor) + 1;
|
||||
// String totalPoints = "" + leaderboard.getTotalPoints(competitor, timePoint);
|
||||
// String raceColumnName = raceColumnToShow.getName();
|
||||
// final Fleet fleetOfCompetitor = raceColumnToShow.getFleetOfCompetitor(competitor);
|
||||
// String fleet = fleetOfCompetitor==null?"":fleetOfCompetitor.getName();
|
||||
// String netpoints = String.valueOf(leaderboard.getNetPoints(competitor, raceColumnToShow, timePoint));
|
||||
// String totalPointsRaceColumn = String.valueOf(leaderboard.getTotalPoints(competitor, raceColumnToShow, timePoint));
|
||||
// MaxPointsReason maxPointsReason = leaderboard.getMaxPointsReason(competitor, raceColumnToShow, timePoint);
|
||||
// String maxPoints = maxPointsReason != null ? maxPointsReason.toString(): null;
|
||||
// String isDiscarded = String.valueOf(leaderboard.isDiscarded(competitor, raceColumnToShow, timePoint));
|
||||
// String isCorrected = String.valueOf(leaderboard.getScoreCorrection().isScoreCorrected(competitor, raceColumnToShow));
|
||||
|
||||
}
|
||||
description.setValue(feedText);
|
||||
} else {
|
||||
String entryTitle = "No live race right now";
|
||||
entry.setTitle(entryTitle);
|
||||
description.setValue("");
|
||||
}
|
||||
|
||||
entry.setDescription(description);
|
||||
entries.add(entry);
|
||||
feed.setEntries(entries);
|
||||
|
||||
PrintWriter writer = resp.getWriter();
|
||||
SyndFeedOutput feedOutput = new SyndFeedOutput();
|
||||
feedOutput.output(feed, writer);
|
||||
} catch (Exception e) {
|
||||
resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the startOfTracking is after the current date and there's no end of the race
|
||||
*/
|
||||
private boolean isLive(TrackedRace trackedRace) {
|
||||
return trackedRace.getEndOfRace() == null && (trackedRace.getStartOfTracking() != null ? new Date().after(trackedRace.getStartOfTracking().asDate()) : false);
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.core.Context;
|
||||
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.util.DateParser;
|
||||
import com.sap.sailing.util.InvalidDateException;
|
||||
|
||||
public abstract class AbstractSailingServerResource {
|
||||
@Context ServletContext servletContext;
|
||||
|
||||
public RacingEventService getService() {
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceTracker<RacingEventService, RacingEventService> tracker = (ServiceTracker<RacingEventService, RacingEventService>) servletContext.getAttribute(RestServletContainer.RACING_EVENT_SERVICE_TRACKER_NAME);
|
||||
return tracker.getService();
|
||||
}
|
||||
|
||||
protected Regatta findRegattaByName(String regattaName) {
|
||||
return getService().getRegattaByName(regattaName);
|
||||
}
|
||||
|
||||
protected RaceDefinition findRaceByName(Regatta regatta, String raceName) {
|
||||
RaceDefinition result = null;
|
||||
if(regatta != null) {
|
||||
for (RaceDefinition race : regatta.getAllRaces()) {
|
||||
if (race.getName().equals(raceName)) {
|
||||
result = race;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected TimePoint parseTimePoint(String isoTime, Long timeAsMillis, TimePoint defaultTime) throws InvalidDateException {
|
||||
TimePoint timePoint;
|
||||
if (isoTime != null && isoTime.length() > 0) {
|
||||
timePoint = new MillisecondsTimePoint(DateParser.parse(isoTime).getTime());
|
||||
} else {
|
||||
timePoint = timeAsMillis != null ? new MillisecondsTimePoint(timeAsMillis) : defaultTime;
|
||||
}
|
||||
return timePoint;
|
||||
}
|
||||
|
||||
protected TrackedRace findTrackedRace(String regattaName, String raceName) {
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
TrackedRace trackedRace = null;
|
||||
if (regatta != null && race != null) {
|
||||
DynamicTrackedRegatta trackedRegatta = getService().getTrackedRegatta(regatta);
|
||||
if(trackedRegatta != null) {
|
||||
trackedRace = trackedRegatta.getTrackedRace(race);
|
||||
}
|
||||
}
|
||||
return trackedRace;
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sun.jersey.spi.container.servlet.ServletContainer;
|
||||
|
||||
public class RestServletContainer extends ServletContainer {
|
||||
private static final long serialVersionUID = -3132655822281021061L;
|
||||
|
||||
private static final String OSGI_RFC66_WEBBUNDLE_BUNDLECONTEXT_NAME = "osgi-bundlecontext";
|
||||
|
||||
public static final String RACING_EVENT_SERVICE_TRACKER_NAME = "racingEventServiceTracker";
|
||||
|
||||
private ServiceTracker<RacingEventService, RacingEventService> racingEventServiceTracker;
|
||||
|
||||
public RestServletContainer() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RestServletContainer(Application app) {
|
||||
super(app);
|
||||
}
|
||||
|
||||
public RestServletContainer(Class<? extends Application> appClass) {
|
||||
super(appClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
|
||||
BundleContext context = (BundleContext) config.getServletContext().getAttribute(OSGI_RFC66_WEBBUNDLE_BUNDLECONTEXT_NAME);
|
||||
racingEventServiceTracker = new ServiceTracker<RacingEventService, RacingEventService>(context, RacingEventService.class.getName(), null);
|
||||
racingEventServiceTracker.open();
|
||||
|
||||
config.getServletContext().setAttribute(RACING_EVENT_SERVICE_TRACKER_NAME, racingEventServiceTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
|
||||
if(racingEventServiceTracker != null) {
|
||||
racingEventServiceTracker.close();
|
||||
}
|
||||
}
|
||||
|
||||
public RacingEventService getService() {
|
||||
return racingEventServiceTracker.getService();
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
|
||||
public class UnitSerializationUtil {
|
||||
public static final DecimalFormat distanceDecimalFormatter = new DecimalFormat("#.##");
|
||||
public static final DecimalFormat knotsDecimalFormatter = new DecimalFormat("#.##");
|
||||
public static final DecimalFormat bearingDecimalFormatter = new DecimalFormat("#.#");
|
||||
public static final DecimalFormat speedDecimalFormatter = new DecimalFormat("#.#");
|
||||
public static final DecimalFormat latLngDecimalFormatter = new DecimalFormat("#.######");
|
||||
|
||||
static {
|
||||
DecimalFormatSymbols symbol = DecimalFormatSymbols.getInstance();
|
||||
symbol.setDecimalSeparator('.');
|
||||
distanceDecimalFormatter.setDecimalFormatSymbols(symbol);
|
||||
knotsDecimalFormatter.setDecimalFormatSymbols(symbol);
|
||||
bearingDecimalFormatter.setDecimalFormatSymbols(symbol);
|
||||
speedDecimalFormatter.setDecimalFormatSymbols(symbol);
|
||||
latLngDecimalFormatter.setDecimalFormatSymbols(symbol);
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.server.gateway.jaxrs.UnitSerializationUtil;
|
||||
|
||||
public class DefaultWindTrackJsonSerializer implements WindTrackJsonSerializer {
|
||||
public static final String FIELD_ID = "id";
|
||||
public static final String FIELD_NAME = "name";
|
||||
public static final String FIELD_PUBLICATION_URL = "publicationUrl";
|
||||
public static final String FIELD_VENUE = "venue";
|
||||
|
||||
private TimePoint fromTime;
|
||||
private TimePoint toTime;
|
||||
private WindSource windSource;
|
||||
|
||||
public JSONObject serialize(WindTrack windTrack) {
|
||||
JSONObject result = new JSONObject();
|
||||
JSONArray jsonWindFixes = new JSONArray();
|
||||
|
||||
// quickly extract relevant fixes to hold locks as shortly as possible; process later
|
||||
ArrayList<Wind> fixes = new ArrayList<>();
|
||||
windTrack.lockForRead();
|
||||
try {
|
||||
Iterator<Wind> windIter = windTrack.getFixesIterator(fromTime, /* inclusive */true);
|
||||
while (windIter.hasNext()) {
|
||||
Wind wind = windIter.next();
|
||||
if (wind.getTimePoint().compareTo(toTime) > 0) {
|
||||
break;
|
||||
} else {
|
||||
fixes.add(wind);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
windTrack.unlockAfterRead();
|
||||
}
|
||||
|
||||
for (Wind wind : fixes) {
|
||||
JSONObject jsonWind = new JSONObject();
|
||||
jsonWind.put("trueBearing-deg", UnitSerializationUtil.bearingDecimalFormatter.format(wind.getBearing().getDegrees()));
|
||||
jsonWind.put("speed-kts", UnitSerializationUtil.speedDecimalFormatter.format(wind.getKnots()));
|
||||
jsonWind.put("speed-m/s", UnitSerializationUtil.speedDecimalFormatter.format(wind.getMetersPerSecond()));
|
||||
if (wind.getTimePoint() != null) {
|
||||
jsonWind.put("timepoint-ms", wind.getTimePoint().asMillis());
|
||||
final Wind averagedWind = windTrack.getAveragedWind(wind.getPosition(), wind.getTimePoint());
|
||||
jsonWind.put("dampenedTrueBearing-deg", UnitSerializationUtil.bearingDecimalFormatter.format(averagedWind.getBearing().getDegrees()));
|
||||
jsonWind.put("dampenedSpeed-kts", UnitSerializationUtil.speedDecimalFormatter.format(averagedWind.getKnots()));
|
||||
jsonWind.put("dampenedSpeed-m/s", UnitSerializationUtil.speedDecimalFormatter.format(averagedWind.getMetersPerSecond()));
|
||||
}
|
||||
if (wind.getPosition() != null) {
|
||||
jsonWind.put("lat-deg", UnitSerializationUtil.latLngDecimalFormatter.format(wind.getPosition().getLatDeg()));
|
||||
jsonWind.put("lng-deg", UnitSerializationUtil.latLngDecimalFormatter.format(wind.getPosition().getLngDeg()));
|
||||
}
|
||||
jsonWindFixes.add(jsonWind);
|
||||
}
|
||||
result.put(windSource.name(), jsonWindFixes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setFromTime(TimePoint fromTime) {
|
||||
this.fromTime = fromTime;
|
||||
}
|
||||
|
||||
public void setToTime(TimePoint toTime) {
|
||||
this.toTime = toTime;
|
||||
}
|
||||
|
||||
public void setWindSource(WindSource windSource) {
|
||||
this.windSource = windSource;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
|
||||
import com.sap.sailing.domain.base.EventBase;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.CourseAreaJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.EventJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer;
|
||||
|
||||
@Path("/v1/events")
|
||||
public class EventsResource extends AbstractSailingServerResource {
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getEvents() {
|
||||
JsonSerializer<EventBase> eventSerializer = new EventJsonSerializer(new VenueJsonSerializer(new CourseAreaJsonSerializer()));
|
||||
JSONArray result = new JSONArray();
|
||||
for (EventBase event : getService().getAllEvents()) {
|
||||
result.add(eventSerializer.serialize(event));
|
||||
}
|
||||
byte[] json = result.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{eventId}")
|
||||
public Response getEvent(@PathParam("eventId") String eventId) {
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{eventId}/racestates")
|
||||
public Response getRaceStates(@PathParam("eventId") String eventId) {
|
||||
return Response.noContent().build();
|
||||
}
|
||||
}
|
||||
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.leaderboard.MetaLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.RegattaLeaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
|
||||
@Path("/v1/leaderboardgroups")
|
||||
public class LeaderboardGroupsResource extends AbstractSailingServerResource {
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getLeaderboardGroups() {
|
||||
JSONArray jsonLeaderboardGroups = new JSONArray();
|
||||
Map<String, LeaderboardGroup> leaderboardGroups = getService().getLeaderboardGroups();
|
||||
for (String leaderboardGroupName : leaderboardGroups.keySet()) {
|
||||
jsonLeaderboardGroups.add(leaderboardGroupName);
|
||||
}
|
||||
|
||||
byte[] json = jsonLeaderboardGroups.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{name}")
|
||||
public Response getLeaderboardGroup(@PathParam("name") String leaderboardGroupName) {
|
||||
Response response;
|
||||
LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByName(leaderboardGroupName);
|
||||
if (leaderboardGroup == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a leaderboard group with name '"+leaderboardGroupName+"'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
TimePoint timePoint = MillisecondsTimePoint.now();
|
||||
JSONObject jsonLeaderboardGroup = new JSONObject();
|
||||
jsonLeaderboardGroup.put("name", leaderboardGroup.getName());
|
||||
jsonLeaderboardGroup.put("description", leaderboardGroup.getDescription());
|
||||
jsonLeaderboardGroup.put("timepoint", timePoint.toString());
|
||||
JSONArray jsonLeaderboardEntries = new JSONArray();
|
||||
jsonLeaderboardGroup.put("leaderboards", jsonLeaderboardEntries);
|
||||
for (Leaderboard leaderboard: leaderboardGroup.getLeaderboards()) {
|
||||
boolean isMetaLeaderboard = leaderboard instanceof MetaLeaderboard ? true : false;
|
||||
boolean isRegattaLeaderboard = leaderboard instanceof RegattaLeaderboard ? true : false;
|
||||
|
||||
JSONObject jsonLeaderboard = new JSONObject();
|
||||
jsonLeaderboard.put("name", leaderboard.getName());
|
||||
jsonLeaderboard.put("displayName", leaderboard.getDisplayName());
|
||||
jsonLeaderboard.put("isMetaLeaderboard", isMetaLeaderboard);
|
||||
jsonLeaderboard.put("isRegattaLeaderboard", isRegattaLeaderboard);
|
||||
jsonLeaderboardEntries.add(jsonLeaderboard);
|
||||
|
||||
SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection();
|
||||
if (scoreCorrection != null) {
|
||||
jsonLeaderboard.put("scoringComment", scoreCorrection.getComment());
|
||||
TimePoint lastUpdateTimepoint = scoreCorrection.getTimePointOfLastCorrectionsValidity();
|
||||
jsonLeaderboard.put("lastScoringUpdate", lastUpdateTimepoint != null ? lastUpdateTimepoint.asDate().toString(): null);
|
||||
} else {
|
||||
jsonLeaderboard.put("scoringComment", null);
|
||||
jsonLeaderboard.put("lastScoringUpdate", null);
|
||||
}
|
||||
|
||||
if (isRegattaLeaderboard) {
|
||||
RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard;
|
||||
Regatta regatta = regattaLeaderboard.getRegatta();
|
||||
jsonLeaderboard.put("scoringScheme", leaderboard.getScoringScheme().getType());
|
||||
jsonLeaderboard.put("regattaName", regatta.getName());
|
||||
} else {
|
||||
jsonLeaderboard.put("scoringScheme", leaderboard.getScoringScheme().getType());
|
||||
jsonLeaderboard.put("regattaName", null);
|
||||
JSONArray jsonSeriesEntries = new JSONArray();
|
||||
jsonLeaderboard.put("series", jsonSeriesEntries);
|
||||
|
||||
// write a 'default' series to be conform with our common regatta structure
|
||||
JSONObject jsonSeries = new JSONObject();
|
||||
jsonSeriesEntries.add(jsonSeries);
|
||||
jsonSeries.put("name", LeaderboardNameConstants.DEFAULT_SERIES_NAME);
|
||||
jsonSeries.put("isMedalSeries", null);
|
||||
JSONArray jsonFleetsEntries = new JSONArray();
|
||||
jsonSeries.put("fleets", jsonFleetsEntries);
|
||||
Fleet fleet = leaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME);
|
||||
if (fleet != null) {
|
||||
JSONObject jsonFleet = new JSONObject();
|
||||
jsonFleet.put("name", fleet.getName());
|
||||
jsonFleet.put("color", fleet.getColor() != null ? fleet.getColor().getAsHtml() : null);
|
||||
jsonFleet.put("ordering", fleet.getOrdering());
|
||||
jsonFleetsEntries.add(jsonFleet);
|
||||
JSONArray jsonRacesEntries = new JSONArray();
|
||||
jsonFleet.put("races", jsonRacesEntries);
|
||||
for (RaceColumn raceColumn: leaderboard.getRaceColumns()) {
|
||||
JSONObject jsonRaceColumn = new JSONObject();
|
||||
jsonRaceColumn.put("name", raceColumn.getName());
|
||||
jsonRaceColumn.put("isMedalRace" , raceColumn.isMedalRace());
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
jsonRaceColumn.put("isTracked", true);
|
||||
jsonRaceColumn.put("regattaName", trackedRace.getTrackedRegatta().getRegatta().getName());
|
||||
jsonRaceColumn.put("trackedRaceName", trackedRace.getRace().getName());
|
||||
jsonRaceColumn.put("hasGpsData", trackedRace.hasGPSData());
|
||||
jsonRaceColumn.put("hasWindData", trackedRace.hasWindData());
|
||||
} else {
|
||||
jsonRaceColumn.put("isTracked", false);
|
||||
jsonRaceColumn.put("trackedRaceName", null);
|
||||
jsonRaceColumn.put("hasGpsData", false);
|
||||
jsonRaceColumn.put("hasWindData", false);
|
||||
}
|
||||
jsonRacesEntries.add(jsonRaceColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] json = jsonLeaderboardGroup.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.LeaderboardNameConstants;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.domain.common.dto.FleetDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO;
|
||||
import com.sap.sailing.domain.common.dto.LeaderboardRowDTO;
|
||||
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
|
||||
@Path("/v1/leaderboards")
|
||||
public class LeaderboardsResource extends AbstractSailingServerResource {
|
||||
|
||||
public enum ResultStates { Live, Preliminary, Final };
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getLeaderboards() {
|
||||
JSONArray jsonLeaderboards = new JSONArray();
|
||||
Map<String, Leaderboard> leaderboards = getService().getLeaderboards();
|
||||
for (String leaderboardName : leaderboards.keySet()) {
|
||||
if(!leaderboardName.equals(LeaderboardNameConstants.DEFAULT_LEADERBOARD_NAME))
|
||||
jsonLeaderboards.add(leaderboardName);
|
||||
}
|
||||
|
||||
byte[] json = jsonLeaderboards.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{name}")
|
||||
public Response getLeaderboard(@PathParam("name") String leaderboardName,
|
||||
@DefaultValue("Live") @QueryParam("resultState") ResultStates resultState,
|
||||
@DefaultValue("true") @QueryParam("useCache") boolean useCache,
|
||||
@DefaultValue("1000") @QueryParam("maxCompetitorsCount") int maxCompetitorsCount) {
|
||||
Response response;
|
||||
|
||||
TimePoint requestTimePoint = MillisecondsTimePoint.now();
|
||||
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
|
||||
if (leaderboard == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a leaderboard with name '" + leaderboardName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
try {
|
||||
TimePoint resultTimePoint = calculateTimePointForResultState(leaderboard, resultState);
|
||||
JSONObject jsonLeaderboard;
|
||||
if (resultTimePoint != null) {
|
||||
Triple<TimePoint, ResultStates, Integer> resultStateAndTimePoint = new Triple<>(resultTimePoint, resultState, maxCompetitorsCount);
|
||||
jsonLeaderboard = getLeaderboardJson(leaderboard, resultStateAndTimePoint);
|
||||
} else {
|
||||
jsonLeaderboard = createEmptyLeaderboardJson(leaderboard, resultState, requestTimePoint, maxCompetitorsCount);
|
||||
}
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
jsonLeaderboard.writeJSONString(sw);
|
||||
|
||||
byte[] json = sw.getBuffer().toString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
} catch (NoWindException | InterruptedException | ExecutionException | IOException e) {
|
||||
response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private JSONObject getLeaderboardJson(Leaderboard leaderboard, Triple<TimePoint, ResultStates, Integer> timePointAndResultStateAndMaxCompetitorsCount)
|
||||
throws NoWindException, InterruptedException, ExecutionException {
|
||||
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(timePointAndResultStateAndMaxCompetitorsCount.getA(),
|
||||
Collections.<String> emptyList(), getService(), getService().getBaseDomainFactory());
|
||||
|
||||
TimePoint resultTimePoint = timePointAndResultStateAndMaxCompetitorsCount.getA();
|
||||
ResultStates resultState = timePointAndResultStateAndMaxCompetitorsCount.getB();
|
||||
Integer maxCompetitorsCount = timePointAndResultStateAndMaxCompetitorsCount.getC();
|
||||
JSONObject jsonLeaderboard = new JSONObject();
|
||||
|
||||
writeCommonLeaderboardData(jsonLeaderboard, leaderboardDTO, resultState, resultTimePoint, maxCompetitorsCount);
|
||||
|
||||
JSONArray jsonCompetitorEntries = new JSONArray();
|
||||
jsonLeaderboard.put("competitors", jsonCompetitorEntries);
|
||||
int counter = 1;
|
||||
for (CompetitorDTO competitor : leaderboardDTO.competitors) {
|
||||
LeaderboardRowDTO leaderboardRowDTO = leaderboardDTO.rows.get(competitor);
|
||||
|
||||
if(maxCompetitorsCount != null && counter > maxCompetitorsCount) {
|
||||
break;
|
||||
}
|
||||
JSONObject jsonCompetitor = new JSONObject();
|
||||
jsonCompetitor.put("name", competitor.getName());
|
||||
final String displayName = leaderboardDTO.getDisplayName(competitor);
|
||||
jsonCompetitor.put("displayName", displayName==null?competitor.getName():displayName);
|
||||
jsonCompetitor.put("id", competitor.getIdAsString());
|
||||
jsonCompetitor.put("sailID", competitor.getSailID());
|
||||
jsonCompetitor.put("nationality", competitor.getThreeLetterIocCountryCode());
|
||||
jsonCompetitor.put("countryCode", competitor.getTwoLetterIsoCountryCode());
|
||||
|
||||
jsonCompetitor.put("rank", counter);
|
||||
jsonCompetitor.put("carriedPoints", leaderboardRowDTO.carriedPoints);
|
||||
jsonCompetitor.put("totalPoints", leaderboardRowDTO.totalPoints);
|
||||
jsonCompetitorEntries.add(jsonCompetitor);
|
||||
JSONObject jsonRaceColumns = new JSONObject();
|
||||
jsonCompetitor.put("raceScores", jsonRaceColumns);
|
||||
for (RaceColumnDTO raceColumn : leaderboardDTO.getRaceList()) {
|
||||
List<CompetitorDTO> rankedCompetitorsForColumn = leaderboardDTO.getCompetitorOrderingPerRaceColumnName().get(raceColumn.getName());
|
||||
JSONObject jsonEntry = new JSONObject();
|
||||
jsonRaceColumns.put(raceColumn.getName(), jsonEntry);
|
||||
LeaderboardEntryDTO leaderboardEntry = leaderboardRowDTO.fieldsByRaceColumnName.get(raceColumn.getName());
|
||||
|
||||
final FleetDTO fleetOfCompetitor = leaderboardEntry.fleet;
|
||||
jsonEntry.put("fleet", fleetOfCompetitor==null?"":fleetOfCompetitor.getName());
|
||||
jsonEntry.put("netPoints", leaderboardEntry.netPointsCorrected);
|
||||
jsonEntry.put("uncorrectedNetPoints", leaderboardEntry.netPoints);
|
||||
jsonEntry.put("totalPoints", leaderboardEntry.totalPoints);
|
||||
MaxPointsReason maxPointsReason = leaderboardEntry.reasonForMaxPoints;
|
||||
jsonEntry.put("maxPointsReason", maxPointsReason != null ? maxPointsReason.toString(): null);
|
||||
jsonEntry.put("rank", rankedCompetitorsForColumn.indexOf(competitor)+1);
|
||||
// final TrackedRace trackedRace = raceColumn.getTrackedRace(competitor);
|
||||
// if (trackedRace != null) {
|
||||
// jsonEntry.put("raceRank", trackedRace.getRank(competitor, resultTimePoint));
|
||||
// }
|
||||
jsonEntry.put("isDiscarded", leaderboardEntry.discarded);
|
||||
jsonEntry.put("isCorrected", leaderboardEntry.hasScoreCorrection());
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
return jsonLeaderboard;
|
||||
}
|
||||
|
||||
private JSONObject createEmptyLeaderboardJson(Leaderboard leaderboard,
|
||||
ResultStates resultState, TimePoint requestTimePoint, Integer maxCompetitorsCount) throws NoWindException {
|
||||
JSONObject jsonLeaderboard = new JSONObject();
|
||||
|
||||
writeCommonLeaderboardData(jsonLeaderboard, leaderboard, resultState, null, maxCompetitorsCount);
|
||||
|
||||
JSONArray jsonCompetitorEntries = new JSONArray();
|
||||
jsonLeaderboard.put("competitors", jsonCompetitorEntries);
|
||||
for (Competitor competitor : leaderboard.getCompetitors()) {
|
||||
JSONObject jsonCompetitor = new JSONObject();
|
||||
jsonCompetitor.put("name", competitor.getName());
|
||||
final String displayName = leaderboard.getDisplayName(competitor);
|
||||
jsonCompetitor.put("displayName", displayName==null?competitor.getName():displayName);
|
||||
jsonCompetitor.put("id", competitor.getId().toString());
|
||||
jsonCompetitor.put("sailID", competitor.getBoat().getSailID());
|
||||
Nationality nationality = competitor.getTeam().getNationality();
|
||||
jsonCompetitor.put("nationality", nationality != null ? nationality.getThreeLetterIOCAcronym(): null);
|
||||
jsonCompetitor.put("countryCode", nationality != null ? (nationality.getCountryCode() != null ? nationality.getCountryCode().getTwoLetterISOCode(): null) : null);
|
||||
|
||||
jsonCompetitor.put("rank", 0);
|
||||
jsonCompetitor.put("carriedPoints", null);
|
||||
jsonCompetitor.put("totalPoints", null);
|
||||
jsonCompetitorEntries.add(jsonCompetitor);
|
||||
JSONObject jsonRaceColumns = new JSONObject();
|
||||
jsonCompetitor.put("raceScores", jsonRaceColumns);
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
JSONObject jsonEntry = new JSONObject();
|
||||
jsonRaceColumns.put(raceColumn.getName(), jsonEntry);
|
||||
final Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor);
|
||||
jsonEntry.put("fleet", fleetOfCompetitor==null?"":fleetOfCompetitor.getName());
|
||||
jsonEntry.put("netPoints", null);
|
||||
jsonEntry.put("totalPoints", null);
|
||||
jsonEntry.put("maxPointsReason", "");
|
||||
jsonEntry.put("rank", 0);
|
||||
jsonEntry.put("isDiscarded", false);
|
||||
jsonEntry.put("isCorrected", false);
|
||||
}
|
||||
}
|
||||
return jsonLeaderboard;
|
||||
}
|
||||
|
||||
private void writeCommonLeaderboardData(JSONObject jsonLeaderboard, LeaderboardDTO leaderboard, ResultStates resultState,
|
||||
TimePoint resultTimePoint, Integer maxCompetitorsCount) {
|
||||
jsonLeaderboard.put("name", leaderboard.name);
|
||||
|
||||
jsonLeaderboard.put("resultTimepoint", resultTimePoint != null ? resultTimePoint.asMillis() : null);
|
||||
jsonLeaderboard.put("resultState", resultState.name());
|
||||
jsonLeaderboard.put("maxCompetitorsCount", maxCompetitorsCount);
|
||||
|
||||
jsonLeaderboard.put("scoringComment", leaderboard.getComment());
|
||||
Date lastUpdateTimepoint = leaderboard.getTimePointOfLastCorrectionsValidity();
|
||||
jsonLeaderboard.put("lastScoringUpdate", lastUpdateTimepoint != null ? lastUpdateTimepoint.getTime(): null);
|
||||
|
||||
JSONArray jsonColumnNames = new JSONArray();
|
||||
jsonLeaderboard.put("columnNames", jsonColumnNames);
|
||||
for (RaceColumnDTO raceColumn : leaderboard.getRaceList()) {
|
||||
jsonColumnNames.add(raceColumn.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCommonLeaderboardData(JSONObject jsonLeaderboard, Leaderboard leaderboard, ResultStates resultState,
|
||||
TimePoint resultTimePoint, Integer maxCompetitorsCount) {
|
||||
jsonLeaderboard.put("name", leaderboard.getName());
|
||||
|
||||
jsonLeaderboard.put("resultTimepoint", resultTimePoint != null ? resultTimePoint.asMillis() : null);
|
||||
jsonLeaderboard.put("resultState", resultState.name());
|
||||
jsonLeaderboard.put("maxCompetitorsCount", maxCompetitorsCount);
|
||||
|
||||
SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection();
|
||||
if (scoreCorrection != null) {
|
||||
jsonLeaderboard.put("scoringComment", scoreCorrection.getComment());
|
||||
TimePoint lastUpdateTimepoint = scoreCorrection.getTimePointOfLastCorrectionsValidity();
|
||||
jsonLeaderboard.put("lastScoringUpdate", lastUpdateTimepoint != null ? lastUpdateTimepoint.asMillis(): null);
|
||||
} else {
|
||||
jsonLeaderboard.put("scoringComment", null);
|
||||
jsonLeaderboard.put("lastScoringUpdate", null);
|
||||
}
|
||||
|
||||
JSONArray jsonColumnNames = new JSONArray();
|
||||
jsonLeaderboard.put("columnNames", jsonColumnNames);
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
jsonColumnNames.add(raceColumn.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private TimePoint calculateTimePointForResultState(Leaderboard leaderboard, ResultStates resultState) {
|
||||
TimePoint result = null;
|
||||
switch (resultState) {
|
||||
case Live:
|
||||
result = leaderboard.getTimePointOfLatestModification();
|
||||
if (result == null) {
|
||||
result = MillisecondsTimePoint.now();
|
||||
}
|
||||
break;
|
||||
case Preliminary:
|
||||
case Final:
|
||||
if (leaderboard.getScoreCorrection() != null && leaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity() != null) {
|
||||
result = leaderboard.getScoreCorrection().getTimePointOfLastCorrectionsValidity();
|
||||
// As we don't have implemented bug 1246 (Define a clear result state for races and leaderboards) so far
|
||||
// we need to make sure that the timpoint for the final state is not determined in the middle of a running race,
|
||||
// because this would deliver not only final results but also some "mixed-in" live results.
|
||||
// Therefore, if there is a race that hasn't finished yet and whose first start mark passing is before
|
||||
// the current result, move result to before the start mark passing.
|
||||
for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) {
|
||||
TimePoint endOfRace = trackedRace.getEndOfRace();
|
||||
if (endOfRace == null) {
|
||||
Waypoint firstWaypoint = trackedRace.getRace().getCourse().getFirstWaypoint();
|
||||
if (firstWaypoint != null) {
|
||||
Iterable<MarkPassing> markPassingsForFirstWaypoint = trackedRace.getMarkPassingsInOrder(firstWaypoint);
|
||||
if (markPassingsForFirstWaypoint != null) {
|
||||
trackedRace.lockForRead(markPassingsForFirstWaypoint);
|
||||
try {
|
||||
Iterator<MarkPassing> i = markPassingsForFirstWaypoint.iterator();
|
||||
if (i.hasNext()) {
|
||||
TimePoint earliestMarkPassingTimePoint = i.next().getTimePoint();
|
||||
if (result == null || earliestMarkPassingTimePoint.before(result)) {
|
||||
result = earliestMarkPassingTimePoint.minus(1);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
trackedRace.unlockAfterRead(markPassingsForFirstWaypoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+571
@@ -0,0 +1,571 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.Distance;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.Tack;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.TrackedLeg;
|
||||
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.gateway.jaxrs.UnitSerializationUtil;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.ControlPointJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.CourseBaseJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.ColorJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.FleetJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.RegattaJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.SeriesJsonSerializer;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer;
|
||||
import com.sap.sailing.util.InvalidDateException;
|
||||
|
||||
@Path("/v1/regattas")
|
||||
public class RegattasResource extends AbstractSailingServerResource {
|
||||
|
||||
private Response getBadRegattaErrorResponse(String regattaName) {
|
||||
return Response.status(Status.NOT_FOUND).entity("Could not find a regatta with name '" + regattaName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
private Response getBadRaceErrorResponse(String regattaName, String raceName) {
|
||||
return Response.status(Status.NOT_FOUND).entity("Could not find a race with name '" + raceName + "' in regatta '" + regattaName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getRegattas() {
|
||||
RegattaJsonSerializer regattaJsonSerializer = new RegattaJsonSerializer();
|
||||
|
||||
JSONArray regattasJson = new JSONArray();
|
||||
for (Regatta regatta : getService().getAllRegattas()) {
|
||||
regattasJson.add(regattaJsonSerializer.serialize(regatta));
|
||||
}
|
||||
byte[] json = regattasJson.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}")
|
||||
public Response getRegatta(@PathParam("regattaname") String regattaName) {
|
||||
Response response;
|
||||
Regatta regatta = getService().getRegatta(new RegattaName(regattaName));
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
SeriesJsonSerializer seriesJsonSerializer = new SeriesJsonSerializer(new FleetJsonSerializer(new ColorJsonSerializer()));
|
||||
JsonSerializer<Regatta> regattaSerializer = new RegattaJsonSerializer(seriesJsonSerializer, null);
|
||||
JSONObject serializedRegatta = regattaSerializer.serialize(regatta);
|
||||
|
||||
byte[] json = serializedRegatta.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all entries for a regatta.
|
||||
* @param regattaName the name of the regatta
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/entries")
|
||||
public Response getEntries(@PathParam("regattaname") String regattaName) {
|
||||
Response response;
|
||||
Regatta regatta = getService().getRegatta(new RegattaName(regattaName));
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
NationalityJsonSerializer nationalityJsonSerializer = new NationalityJsonSerializer();
|
||||
CompetitorJsonSerializer competitorJsonSerializer = new CompetitorJsonSerializer(
|
||||
new TeamJsonSerializer(new PersonJsonSerializer(nationalityJsonSerializer)));
|
||||
JsonSerializer<Regatta> regattaSerializer = new RegattaJsonSerializer(null, competitorJsonSerializer);
|
||||
JSONObject serializedRegatta = regattaSerializer.serialize(regatta);
|
||||
|
||||
byte[] json = serializedRegatta.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all GPS positions of the competitors for a given race.
|
||||
* @param regattaName the name of the regatta
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/competitors/positions")
|
||||
public Response getCompetitorPositions(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName,
|
||||
@QueryParam("fromtime") String fromtime, @QueryParam("fromtimeasmillis") Long fromtimeasmillis,
|
||||
@QueryParam("totime") String totime, @QueryParam("totimeasmillis") Long totimeasmillis) {
|
||||
Response response;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = getBadRaceErrorResponse(regattaName, raceName);
|
||||
} else {
|
||||
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
|
||||
|
||||
TimePoint from;
|
||||
TimePoint to;
|
||||
try {
|
||||
from = parseTimePoint(fromtime, fromtimeasmillis,
|
||||
trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) :
|
||||
/* 24h before race start */ new MillisecondsTimePoint(trackedRace.getStartOfRace().asMillis()-24*3600*1000));
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
try {
|
||||
to = parseTimePoint(totime, totimeasmillis, MillisecondsTimePoint.now());
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'to' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
JSONObject jsonRace = new JSONObject();
|
||||
jsonRace.put("name", trackedRace.getRace().getName());
|
||||
jsonRace.put("regatta", regatta.getName());
|
||||
JSONArray jsonCompetitors = new JSONArray();
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
JSONObject jsonCompetitor = new JSONObject();
|
||||
jsonCompetitor.put("id", competitor.getId() != null ? competitor.getId().toString() : null);
|
||||
jsonCompetitor.put("name", competitor.getName());
|
||||
jsonCompetitor.put("sailNumber", competitor.getBoat().getSailID());
|
||||
|
||||
GPSFixTrack<Competitor, GPSFixMoving> track = trackedRace.getTrack(competitor);
|
||||
JSONArray jsonFixes = new JSONArray();
|
||||
track.lockForRead();
|
||||
try {
|
||||
Iterator<GPSFixMoving> fixIter;
|
||||
if (from == null) {
|
||||
fixIter = track.getFixes().iterator();
|
||||
} else {
|
||||
fixIter = track.getFixesIterator(from, /* inclusive */true);
|
||||
}
|
||||
while (fixIter.hasNext()) {
|
||||
GPSFixMoving fix = fixIter.next();
|
||||
if (to != null && fix.getTimePoint() != null && to.compareTo(fix.getTimePoint()) < 0) {
|
||||
break;
|
||||
}
|
||||
JSONObject jsonFix = new JSONObject();
|
||||
jsonFix.put("timepoint-ms", fix.getTimePoint().asMillis());
|
||||
jsonFix.put("lat-deg", UnitSerializationUtil.latLngDecimalFormatter.format(fix.getPosition().getLatDeg()));
|
||||
jsonFix.put("lng-deg", UnitSerializationUtil.latLngDecimalFormatter.format(fix.getPosition().getLngDeg()));
|
||||
jsonFix.put("truebearing-deg", fix.getSpeed().getBearing().getDegrees());
|
||||
jsonFix.put("speed-kts", UnitSerializationUtil.knotsDecimalFormatter.format(fix.getSpeed().getKnots()));
|
||||
String tackName;
|
||||
try {
|
||||
final Tack tack = trackedRace.getTack(competitor, fix.getTimePoint());
|
||||
if (tack != null) {
|
||||
tackName = tack.name();
|
||||
jsonFix.put("tack", tackName);
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
// don't output tack
|
||||
}
|
||||
jsonFixes.add(jsonFix);
|
||||
}
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
jsonCompetitor.put("track", jsonFixes);
|
||||
jsonCompetitors.add(jsonCompetitor);
|
||||
}
|
||||
jsonRace.put("competitors", jsonCompetitors);
|
||||
|
||||
byte[] json = jsonRace.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all GPS positions of the course marks for a given race.
|
||||
* @param regattaName the name of the regatta
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/marks/positions")
|
||||
public Response getMarkPositions(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName,
|
||||
@QueryParam("fromtime") String fromtime, @QueryParam("fromtimeasmillis") Long fromtimeasmillis,
|
||||
@QueryParam("totime") String totime, @QueryParam("totimeasmillis") Long totimeasmillis) {
|
||||
Response response;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = getBadRaceErrorResponse(regattaName, raceName);
|
||||
} else {
|
||||
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
|
||||
|
||||
TimePoint from;
|
||||
TimePoint to;
|
||||
try {
|
||||
from = parseTimePoint(fromtime, fromtimeasmillis,
|
||||
trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) :
|
||||
/* 24h before race start */ new MillisecondsTimePoint(trackedRace.getStartOfRace().asMillis()-24*3600*1000));
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
try {
|
||||
to = parseTimePoint(totime, totimeasmillis, MillisecondsTimePoint.now());
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'to' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
JSONObject jsonRace = new JSONObject();
|
||||
jsonRace.put("name", trackedRace.getRace().getName());
|
||||
jsonRace.put("regatta", regatta.getName());
|
||||
JSONArray jsonMarks = new JSONArray();
|
||||
Set<Mark> marks = new HashSet<Mark>();
|
||||
Course course = trackedRace.getRace().getCourse();
|
||||
for (Waypoint waypoint : course.getWaypoints()) {
|
||||
for (Mark mark : waypoint.getMarks()) {
|
||||
marks.add(mark);
|
||||
}
|
||||
}
|
||||
|
||||
for (Mark mark : marks) {
|
||||
JSONObject jsonMark = new JSONObject();
|
||||
jsonMark.put("name", mark.getName());
|
||||
jsonMark.put("id", mark.getId() != null ? mark.getId().toString() : null);
|
||||
GPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
|
||||
JSONArray jsonFixes = new JSONArray();
|
||||
track.lockForRead();
|
||||
try {
|
||||
Iterator<GPSFix> fixIter;
|
||||
if (from == null) {
|
||||
fixIter = track.getFixes().iterator();
|
||||
} else {
|
||||
fixIter = track.getFixesIterator(from, /* inclusive */true);
|
||||
}
|
||||
while (fixIter.hasNext()) {
|
||||
GPSFix fix = fixIter.next();
|
||||
if (to != null && fix.getTimePoint() != null && to.compareTo(fix.getTimePoint()) < 0) {
|
||||
break;
|
||||
}
|
||||
JSONObject jsonFix = new JSONObject();
|
||||
jsonFix.put("timepoint-ms", fix.getTimePoint().asMillis());
|
||||
jsonFix.put("lat-deg", UnitSerializationUtil.latLngDecimalFormatter.format(fix.getPosition().getLatDeg()));
|
||||
jsonFix.put("lng-deg", UnitSerializationUtil.latLngDecimalFormatter.format(fix.getPosition().getLngDeg()));
|
||||
jsonFixes.add(jsonFix);
|
||||
}
|
||||
} finally {
|
||||
track.unlockAfterRead();
|
||||
}
|
||||
jsonMark.put("track", jsonFixes);
|
||||
jsonMarks.add(jsonMark);
|
||||
}
|
||||
jsonRace.put("marks", jsonMarks);
|
||||
|
||||
byte[] json = jsonRace.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the course of the race.
|
||||
* @param regattaName the name of the regatta
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/course")
|
||||
public Response getCourse(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
|
||||
Response response;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = getBadRaceErrorResponse(regattaName, raceName);
|
||||
} else {
|
||||
Course course = race.getCourse();
|
||||
CourseBaseJsonSerializer serializer = new CourseBaseJsonSerializer(
|
||||
new WaypointJsonSerializer(
|
||||
new ControlPointJsonSerializer(
|
||||
new MarkJsonSerializer(),
|
||||
new GateJsonSerializer(new MarkJsonSerializer()))));
|
||||
|
||||
JSONObject jsonCourse = serializer.serialize(course);
|
||||
byte[] json = jsonCourse.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relevant times of the race.
|
||||
* @param regattaName the name of the regatta
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/times")
|
||||
public Response getTimes(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
|
||||
Response response = null;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = getBadRegattaErrorResponse(regattaName);
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = getBadRaceErrorResponse(regattaName, raceName);
|
||||
} else {
|
||||
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
|
||||
|
||||
JSONObject jsonRaceTimes = new JSONObject();
|
||||
jsonRaceTimes.put("name", trackedRace.getRace().getName());
|
||||
jsonRaceTimes.put("regatta", regatta.getName());
|
||||
|
||||
jsonRaceTimes.put("startOfRace-ms", trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asMillis());
|
||||
jsonRaceTimes.put("startOfTracking-ms", trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asMillis());
|
||||
jsonRaceTimes.put("newestTrackingEvent-ms", trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asMillis());
|
||||
jsonRaceTimes.put("endOfTracking-ms", trackedRace.getEndOfTracking() == null ? null : trackedRace.getEndOfTracking().asMillis());
|
||||
jsonRaceTimes.put("endOfRace-ms", trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asMillis());
|
||||
jsonRaceTimes.put("delayToLive-ms", trackedRace.getDelayToLiveInMillis());
|
||||
|
||||
JSONArray jsonMarkPassingTimes = new JSONArray();
|
||||
List<TimePoint> firstPassingTimepoints = new ArrayList<>();
|
||||
Iterable<Pair<Waypoint, Pair<TimePoint, TimePoint>>> markPassingsTimes = trackedRace.getMarkPassingsTimes();
|
||||
synchronized (markPassingsTimes) {
|
||||
int numberOfWaypoints = Util.size(markPassingsTimes);
|
||||
int wayPointNumber = 1;
|
||||
for (Pair<Waypoint, Pair<TimePoint, TimePoint>> markPassingTimes : markPassingsTimes) {
|
||||
JSONObject jsonMarkPassing = new JSONObject();
|
||||
String name = "M" + (wayPointNumber - 1);
|
||||
if (wayPointNumber == numberOfWaypoints) {
|
||||
name = "F";
|
||||
}
|
||||
jsonMarkPassing.put("name", name);
|
||||
Pair<TimePoint, TimePoint> timesPair = markPassingTimes.getB();
|
||||
TimePoint firstPassingTime = timesPair.getA();
|
||||
TimePoint lastPassingTime = timesPair.getB();
|
||||
jsonMarkPassing.put("firstPassing-ms", firstPassingTime == null ? null : firstPassingTime.asMillis());
|
||||
jsonMarkPassing.put("lastPassing-ms", lastPassingTime == null ? null : lastPassingTime.asMillis());
|
||||
|
||||
firstPassingTimepoints.add(firstPassingTime);
|
||||
|
||||
jsonMarkPassingTimes.add(jsonMarkPassing);
|
||||
wayPointNumber++;
|
||||
}
|
||||
}
|
||||
jsonRaceTimes.put("markPassings", jsonMarkPassingTimes);
|
||||
|
||||
JSONArray jsonLegInfos = new JSONArray();
|
||||
trackedRace.getRace().getCourse().lockForRead();
|
||||
try {
|
||||
Iterable<TrackedLeg> trackedLegs = trackedRace.getTrackedLegs();
|
||||
int legNumber = 1;
|
||||
for (TrackedLeg trackedLeg : trackedLegs) {
|
||||
JSONObject jsonLegInfo = new JSONObject();
|
||||
jsonLegInfo.put("name", "L" + legNumber);
|
||||
|
||||
try {
|
||||
TimePoint firstPassingTime = firstPassingTimepoints.get(legNumber - 1);
|
||||
if (firstPassingTime != null) {
|
||||
jsonLegInfo.put("type", trackedLeg.getLegType(firstPassingTime));
|
||||
jsonLegInfo.put("bearing-deg", UnitSerializationUtil.bearingDecimalFormatter.format(trackedLeg.getLegBearing(firstPassingTime).getDegrees()));
|
||||
}
|
||||
} catch (NoWindException e) {
|
||||
// do nothing
|
||||
}
|
||||
jsonLegInfos.add(jsonLegInfo);
|
||||
|
||||
legNumber++;
|
||||
}
|
||||
} finally {
|
||||
trackedRace.getRace().getCourse().unlockAfterRead();
|
||||
}
|
||||
jsonRaceTimes.put("legs", jsonLegInfos);
|
||||
|
||||
Date now = new Date();
|
||||
jsonRaceTimes.put("currentServerTime-ms", now.getTime());
|
||||
|
||||
byte[] json = jsonRaceTimes.toJSONString().getBytes();
|
||||
response = Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/wind")
|
||||
public Response getWind(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName,
|
||||
@DefaultValue("COMBINED") @QueryParam("windsource") String windSource,
|
||||
@QueryParam("fromtime") String fromtime, @QueryParam("fromtimeasmillis") Long fromtimeasmillis,
|
||||
@QueryParam("totime") String totime, @QueryParam("totimeasmillis") Long totimeasmillis) {
|
||||
Response response;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a regatta with name '" + regattaName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a race with name '" + raceName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
|
||||
|
||||
TimePoint from;
|
||||
TimePoint to;
|
||||
try {
|
||||
from = parseTimePoint(fromtime, fromtimeasmillis,
|
||||
trackedRace.getStartOfRace() == null ? new MillisecondsTimePoint(0) :
|
||||
/* 24h before race start */ new MillisecondsTimePoint(trackedRace.getStartOfRace().asMillis()-24*3600*1000));
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'from' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
try {
|
||||
to = parseTimePoint(totime, totimeasmillis, MillisecondsTimePoint.now());
|
||||
} catch (InvalidDateException e1) {
|
||||
return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not parse the 'to' time.").type(MediaType.TEXT_PLAIN).build();
|
||||
}
|
||||
|
||||
TrackedRaceJsonSerializer serializer = new TrackedRaceJsonSerializer(new DefaultWindTrackJsonSerializer());
|
||||
serializer.setWindSource(windSource);
|
||||
serializer.setFromTime(from);
|
||||
serializer.setToTime(to);
|
||||
|
||||
JSONObject jsonWindTracks = serializer.serialize(trackedRace);
|
||||
byte[] json = jsonWindTracks.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("{regattaname}/races/{racename}/competitors/legs")
|
||||
public Response getCompetitorRanks(@PathParam("regattaname") String regattaName, @PathParam("racename") String raceName) {
|
||||
Response response;
|
||||
Regatta regatta = findRegattaByName(regattaName);
|
||||
if (regatta == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a regatta with name '" + regattaName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
RaceDefinition race = findRaceByName(regatta, raceName);
|
||||
if (race == null) {
|
||||
response = Response.status(Status.NOT_FOUND).entity("Could not find a race with name '" + raceName + "'.").type(MediaType.TEXT_PLAIN).build();
|
||||
} else {
|
||||
TrackedRace trackedRace = findTrackedRace(regattaName, raceName);
|
||||
TimePoint timePoint = trackedRace.getTimePointOfNewestEvent() == null ? MillisecondsTimePoint.now()
|
||||
: trackedRace.getTimePointOfNewestEvent();
|
||||
|
||||
JSONObject jsonRaceResults = new JSONObject();
|
||||
jsonRaceResults.put("name", trackedRace.getRace().getName());
|
||||
jsonRaceResults.put("regatta", regatta.getName());
|
||||
|
||||
JSONArray jsonLegs = new JSONArray();
|
||||
for (TrackedLeg leg : trackedRace.getTrackedLegs()) {
|
||||
JSONObject jsonLeg = new JSONObject();
|
||||
jsonLeg.put("from", leg.getLeg().getFrom().getName());
|
||||
jsonLeg.put("fromWaypointId", leg.getLeg().getFrom().getId());
|
||||
jsonLeg.put("to", leg.getLeg().getTo().getName());
|
||||
jsonLeg.put("toWaypointId", leg.getLeg().getTo().getId());
|
||||
try {
|
||||
jsonLeg.put("upOrDownwindLeg", leg.isUpOrDownwindLeg(timePoint));
|
||||
} catch (NoWindException e) {
|
||||
// no wind, then it's simply no upwind or downwind leg
|
||||
jsonLeg.put("upOrDownwindLeg", "false");
|
||||
}
|
||||
JSONArray jsonCompetitors = new JSONArray();
|
||||
Map<Competitor, Integer> ranks = leg.getRanks(timePoint);
|
||||
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
|
||||
JSONObject jsonCompetitorInLeg = new JSONObject();
|
||||
TrackedLegOfCompetitor trackedLegOfCompetitor = leg.getTrackedLeg(competitor);
|
||||
if (trackedLegOfCompetitor != null) {
|
||||
jsonCompetitorInLeg.put("id", competitor.getId() != null ? competitor.getId().toString() : null);
|
||||
jsonCompetitorInLeg.put("name", competitor.getName());
|
||||
jsonCompetitorInLeg.put("sailNumber", competitor.getBoat().getSailID());
|
||||
|
||||
Distance distanceTraveled = trackedLegOfCompetitor.getDistanceTraveled(timePoint);
|
||||
if (distanceTraveled != null) {
|
||||
jsonCompetitorInLeg.put("distanceTraveled-m", UnitSerializationUtil.distanceDecimalFormatter.format(distanceTraveled.getMeters()));
|
||||
}
|
||||
try {
|
||||
Integer rank = ranks.get(competitor);
|
||||
jsonCompetitorInLeg.put("rank", rank);
|
||||
} catch (RuntimeException re) {
|
||||
if (re.getCause() != null && re.getCause() instanceof NoWindException) {
|
||||
// well, we don't know the wind direction, so we can't compute a ranking
|
||||
} else {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
try {
|
||||
jsonCompetitorInLeg.put("gapToLeader-s",
|
||||
trackedLegOfCompetitor.getGapToLeaderInSeconds(timePoint));
|
||||
} catch (NoWindException e1) {
|
||||
// well, we don't know the wind direction... then no gap to leader will be shown...
|
||||
}
|
||||
jsonCompetitorInLeg.put("started", trackedLegOfCompetitor.hasStartedLeg(timePoint));
|
||||
jsonCompetitorInLeg.put("finished", trackedLegOfCompetitor.hasFinishedLeg(timePoint));
|
||||
jsonCompetitors.add(jsonCompetitorInLeg);
|
||||
}
|
||||
}
|
||||
jsonLeg.put("competitors", jsonCompetitors);
|
||||
jsonLegs.add(jsonLeg);
|
||||
}
|
||||
jsonRaceResults.put("legs", jsonLegs);
|
||||
|
||||
byte[] json = jsonRaceResults.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
|
||||
public class RestApiApplication extends Application {
|
||||
public Set<Class<?>> getClasses() {
|
||||
HashSet<Class<?>> classes = new HashSet<>();
|
||||
classes.add(LeaderboardGroupsResource.class);
|
||||
classes.add(EventsResource.class);
|
||||
classes.add(RegattasResource.class);
|
||||
classes.add(LeaderboardsResource.class);
|
||||
// classes.add(WindResource.class);
|
||||
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.domain.common.impl.WindSourceImpl;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
|
||||
public class TrackedRaceJsonSerializer implements JsonSerializer<TrackedRace> {
|
||||
public static final String FIELD_ID = "id";
|
||||
public static final String FIELD_NAME = "name";
|
||||
public static final String FIELD_REGATTA = "regatta";
|
||||
public static final String FIELD_WINDSOURCES = "windSources";
|
||||
|
||||
public static final String ALL_WINDSOURCES = "ALL";
|
||||
|
||||
private String windSourceToSerialize;
|
||||
private TimePoint fromTime;
|
||||
private TimePoint toTime;
|
||||
private final WindTrackJsonSerializer windTrackSerializer;
|
||||
|
||||
public TrackedRaceJsonSerializer(WindTrackJsonSerializer windTrackSerializer) {
|
||||
this.windTrackSerializer = windTrackSerializer;
|
||||
windSourceToSerialize = WindSourceType.COMBINED.name();
|
||||
}
|
||||
|
||||
public JSONObject serialize(TrackedRace trackedRace) {
|
||||
JSONObject jsonRace = new JSONObject();
|
||||
|
||||
jsonRace.put(FIELD_NAME, trackedRace.getRace().getName());
|
||||
jsonRace.put(FIELD_REGATTA, trackedRace.getRaceIdentifier().getRegattaName());
|
||||
|
||||
if(windTrackSerializer != null) {
|
||||
JSONArray windTracks = new JSONArray();
|
||||
|
||||
List<WindSource> windSources = getAvailableWindSources(trackedRace);
|
||||
for (WindSource windSource : windSources) {
|
||||
if (ALL_WINDSOURCES.equals(windSourceToSerialize) || windSource.getType().name().equalsIgnoreCase(windSourceToSerialize)) {
|
||||
windTrackSerializer.setFromTime(fromTime);
|
||||
windTrackSerializer.setToTime(toTime);
|
||||
windTrackSerializer.setWindSource(windSource);
|
||||
|
||||
WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource);
|
||||
JSONObject jsonWindTrack = windTrackSerializer.serialize(windTrack);
|
||||
windTracks.add(jsonWindTrack);
|
||||
}
|
||||
}
|
||||
jsonRace.put(FIELD_WINDSOURCES, windTracks);
|
||||
}
|
||||
|
||||
return jsonRace;
|
||||
}
|
||||
|
||||
public void setWindSource(String windSourceToSerialize) {
|
||||
this.windSourceToSerialize = windSourceToSerialize;
|
||||
}
|
||||
|
||||
public void setFromTime(TimePoint fromTime) {
|
||||
this.fromTime = fromTime;
|
||||
}
|
||||
|
||||
public void setToTime(TimePoint toTime) {
|
||||
this.toTime = toTime;
|
||||
}
|
||||
|
||||
private List<WindSource> getAvailableWindSources(TrackedRace trackedRace) {
|
||||
List<WindSource> windSources = new ArrayList<WindSource>();
|
||||
for (WindSource windSource : trackedRace.getWindSources()) {
|
||||
windSources.add(windSource);
|
||||
}
|
||||
for (WindSource windSourceToExclude : trackedRace.getWindSourcesToExclude()) {
|
||||
windSources.remove(windSourceToExclude);
|
||||
}
|
||||
windSources.add(new WindSourceImpl(WindSourceType.COMBINED));
|
||||
return windSources;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.api;
|
||||
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.server.gateway.serialization.JsonSerializer;
|
||||
|
||||
public interface WindTrackJsonSerializer extends JsonSerializer<WindTrack> {
|
||||
void setFromTime(TimePoint fromTime);
|
||||
void setToTime(TimePoint toTime);
|
||||
void setWindSource(WindSource windSource);
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.spi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource;
|
||||
import com.sap.sailing.server.gateway.serialization.masterdata.impl.TopLevelMasterDataSerializer;
|
||||
|
||||
@Path("/v1/leaderboardgroups/structure")
|
||||
public class LeaderboardGroupsStructureResource extends AbstractSailingServerResource {
|
||||
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
public Response getStructureOfLeaderboardGroups(@QueryParam("names") List<String> leaderboardGroupNames) {
|
||||
Map<String, LeaderboardGroup> leaderboardGroups = getService().getLeaderboardGroups();
|
||||
Set<String> requestedLeaderboardGroupNames = new HashSet<String>();
|
||||
|
||||
if (leaderboardGroupNames != null && !leaderboardGroupNames.isEmpty()) {
|
||||
requestedLeaderboardGroupNames.addAll(leaderboardGroupNames);
|
||||
} else {
|
||||
// No range supplied. Export all for now
|
||||
requestedLeaderboardGroupNames.addAll(leaderboardGroups.keySet());
|
||||
}
|
||||
|
||||
TopLevelMasterDataSerializer masterSerializer = new TopLevelMasterDataSerializer(leaderboardGroups,
|
||||
getService().getAllEvents(), getService().getPersistentRegattasForRaceIDs(), getService().getAllMediaTracks());
|
||||
|
||||
JSONObject masterData = masterSerializer.serialize(requestedLeaderboardGroupNames);
|
||||
|
||||
byte[] json = masterData.toJSONString().getBytes();
|
||||
return Response.ok(json).build();
|
||||
}
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.sap.sailing.server.gateway.jaxrs.spi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
|
||||
public class RestSpiApplication extends Application {
|
||||
public Set<Class<?>> getClasses() {
|
||||
HashSet<Class<?>> classes = new HashSet<>();
|
||||
classes.add(LeaderboardGroupsStructureResource.class);
|
||||
|
||||
return classes;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics Deprecated Web Services API - Overview</h1>
|
||||
|
||||
<p>
|
||||
The best entry point to navigating the contents of a server is usually the <b>leaderboardgroups</b> service,
|
||||
listing the leaderboard groups offered by the server. For example,
|
||||
<a href="http://www.sapsailing.com/sailingserver/leaderboardgroups">http://www.sapsailing.com/sailingserver/leaderboardgroups</a>
|
||||
lists the names of the leaderboard groups that the server instance knows. The names returned in the list can then be used
|
||||
as parameter for the <b>leaderboardgroup</b> service, e.g., as follows:
|
||||
<a href="http://www.sapsailing.com/sailingserver/leaderboardgroup?leaderboardGroupName=Star%20IDM%202013">http://www.sapsailing.com/sailingserver/leaderboardgroup?leaderboardGroupName=Star%20IDM%202013</a>.
|
||||
Note, of course, that the name needs to be URL-encoded with special characters and white spaces correctly
|
||||
translated into URL format.
|
||||
</p>
|
||||
<div style="height: 1em;"></div>
|
||||
<p>
|
||||
The leaderboard group service list the leaderboards in the group. There are essentially two types of leaderboard:
|
||||
flexible leaderboards and regatta leaderboards. For flexible leaderboards, the service tells the list of races
|
||||
in the leaderboard, and for each race in particular the regatta name and the tracked race name. These two attributes
|
||||
can, in turn, be used as parameters for further services to identify the race for which information shall be retrieved and
|
||||
to fetch information about the regatta with its structure such as series and fleets.
|
||||
Again, note that those names need to be URL-encoded accordingly when used as parameter to a service call.
|
||||
</p>
|
||||
<div style="height: 1em;"></div>
|
||||
<p>
|
||||
When a service takes a time point as a parameter, there are usually two ways of specifying it: either as an
|
||||
ISO time stamp, e.g., 2013-05-08T10:12:59Z or as Unix time stamp (milliseconds since 1970-01-01T00:00:00Z). The parameters
|
||||
in the latter format are usually called <b>...asmillis</b>.
|
||||
</p>
|
||||
<div style="height: 1em;"></div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Web Service</td>
|
||||
<td>Description</td>
|
||||
<td>Supported formats</td>
|
||||
</trh>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="eventsExportDoc.html">/events</a></td>
|
||||
<td>Gets all events</td>
|
||||
<td><a href="eventsExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="regattasExportDoc.html">/regattas</a></td>
|
||||
<td>Gets all regattas</td>
|
||||
<td><a href="regattasExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="regattaExportDoc.html">/regatta</a></td>
|
||||
<td>Gets a regatta</td>
|
||||
<td><a href="regattaExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="leaderboardGroupsExportDoc.html">/leaderboardgroups</a></td>
|
||||
<td>Gets all leaderboard groups</td>
|
||||
<td><a href="leaderboardGroupsExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="leaderboardGroupExportDoc.html">/leaderboardgroup</a></td>
|
||||
<td>Gets a group of leaderboards</td>
|
||||
<td><a href="leaderboardGroupExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="leaderboardsExportDoc.html">/leaderboards</a></td>
|
||||
<td>Gets all leaderboards</td>
|
||||
<td><a href="leaderboardsExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="leaderboardExportDoc.html">/leaderboard</a></td>
|
||||
<td>Gets a leaderboard</td>
|
||||
<td><a href="leaderboardExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="windExportDoc.html">/wind</a></td>
|
||||
<td>Gets wind data for a race</td>
|
||||
<td><a href="windExportSample.json">Json</a></td>
|
||||
</tr>
|
||||
<!--
|
||||
<tr>
|
||||
<td><a href="showraceDoc.html">showrace</a></td>
|
||||
<td>Gets general time-dependent data for a race and the competitors</td>
|
||||
<td><a href="showraceSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="showwaypointsDoc.html">showwaypoints</a></td>
|
||||
<td>Gets course and waypoint data for a race</td>
|
||||
<td><a href="showwaypointsSample.json">Json</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="showboatpositionsDoc.html">showboatpositions</a></td>
|
||||
<td>Gets boat GPS data for a race</td>
|
||||
<td><a href="showboatpositionsSample.json">Json</a></td>
|
||||
</tr>
|
||||
-->
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="height: 1em;"></div>
|
||||
<a href="../../index.html">Back to Web Services Home</a>
|
||||
</body>
|
||||
</html>
|
||||
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
+4
-4
@@ -2,10 +2,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../sap.ico' type='image/x-icon'>
|
||||
<title>Gateway services</title>
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>Deprecated Web Services API</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics - Web Services</h1>
|
||||
File renamed without changes.
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<link href='../../../../fontface.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link href='../../../main.css' media='screen' rel='stylesheet' title='Default stylesheet' type='text/css' />
|
||||
<link rel='icon' href='../../../../sap.ico' type='image/x-icon'>
|
||||
<title>SAP Sailing Analytics Webservices API Version 1.0 Beta</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SAP Sailing Analytics Webservices API Version 1.0 Beta</h1>
|
||||
<h2>URL: /api/v1/events</h2>
|
||||
|
||||
<b>Description:</b>
|
||||
<p>The service gets all existing events with their venues and course areas</p>
|
||||
<br/>
|
||||
<table>
|
||||
<tr>
|
||||
<td>Webservice Type:</td>
|
||||
<td>REST</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Output format:</td>
|
||||
<td>Json</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mandatory parameters:</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optional parameters:</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Request method:</td>
|
||||
<td>GET</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Example:</td>
|
||||
<td><a href="http://www.sapsailing.com/sailingserver/api/v1/events">http://www.sapsailing.com/sailingserver/api/v1/events</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div style="height: 1em;"></div>
|
||||
<a href="index.html">Back to Web Service Overview</a>
|
||||
</body>
|
||||
</html>
|
||||
Loaded 100 of 141 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user