Merge remote-tracking branch 'origin/master' into ftes-rltracking-app

This commit is contained in:
Fredrik Teschke committed 2014-10-14 14:17:05 +02:00
commit 25dcadd9ba
25 files changed
+417 -68

No files matched your search

@@ -2,6 +2,6 @@ package com.sap.sailing.domain.common;
public enum ScoringSchemeType {
LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN,
HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE,
HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE, HIGH_POINT_WINNER_GETS_EIGHT,
HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT
}
@@ -44,6 +44,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10LastBreaksTie
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets10Or8AndLastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointFirstGets1LastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie;
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEight;
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive;
import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
@@ -105,6 +106,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain
return new HighPointWinnerGetsFive();
case HIGH_POINT_WINNER_GETS_SIX:
return new HighPointWinnerGetsSix();
case HIGH_POINT_WINNER_GETS_EIGHT:
return new HighPointWinnerGetsEight();
case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT:
return new HighPointFirstGets10Or8AndLastBreaksTie();
}
@@ -0,0 +1,16 @@
package com.sap.sailing.domain.leaderboard.impl;
import com.sap.sailing.domain.common.ScoringSchemeType;
public class HighPointWinnerGetsEight extends HighPointFirstGetsFixedScore {
private static final long serialVersionUID = 330293087596268557L;
public HighPointWinnerGetsEight() {
super(/* scoreForRaceWinner */ 8);
}
@Override
public ScoringSchemeType getType() {
return ScoringSchemeType.HIGH_POINT_WINNER_GETS_EIGHT;
}
}
@@ -388,6 +388,7 @@ public interface StringMessages extends Messages {
String scoringSchemeLowPointWinnerGetsZero();
String scoringSchemeWinnerGetsFive();
String scoringSchemeWinnerGetsSix();
String scoringSchemeWinnerGetsEight();
String scoringSystem();
String createFlexibleLeaderboard();
String createRegattaLeaderboard();
@@ -412,6 +412,7 @@ scoringSchemeHighPointLastBreaksTie=High Point System, Last Race Breaks Tie
scoringSchemeLowPointWinnerGetsZero=Low Point System, Winner Gets Zero
scoringSchemeWinnerGetsFive=High Point System, Winner Gets 5 Points
scoringSchemeWinnerGetsSix=High Point System, Winner Gets 6 Points
scoringSchemeWinnerGetsEight=High Point System, Winner Gets 8 Points
scoringSystem=Scoring system
createFlexibleLeaderboard=Create flexible leaderboard
createRegattaLeaderboard=Create regatta leaderboard
@@ -413,6 +413,7 @@ scoringSchemeHighPointLastBreaksTie=High Point System, letztes Rennen entscheide
scoringSchemeLowPointWinnerGetsZero=Low Point System, Gewinner erhält 0 Punkte
scoringSchemeWinnerGetsFive=High Point System, Gewinner erhält 5 Punkte
scoringSchemeWinnerGetsSix=High Point System, Gewinner erhält 6 Punkte
scoringSchemeWinnerGetsEight=High Point System, Gewinner erhält 8 Punkte
scoringSystem=Bepunktungssystem
createFlexibleLeaderboard=Flexible Rangliste anlegen
createRegattaLeaderboard=Rangliste für Regatta anlegen
@@ -402,6 +402,7 @@ scoringSchemeHighPointLastBreaksTie=Высокобальная система п
scoringSchemeLowPointWinnerGetsZero=Низкобальная система подсчета очков, победитель получает ноль очков
scoringSchemeWinnerGetsFive=Высокобальная система подсчета, победитель получает 5 очков
scoringSchemeWinnerGetsSix=Высокобальная система подсчета, победитель получает 6 очков
scoringSchemeWinnerGetsEight=Высокобальная система подсчета, победитель получает 8 очков
scoringSystem=Система подсчета очков
createFlexibleLeaderboard=Создание адаптивной таблицы лидеров
createRegattaLeaderboard=Создание таблицы лидеров регаты
@@ -24,6 +24,8 @@ public class ScoringSchemeTypeFormatter {
return stringMessages.scoringSchemeWinnerGetsFive();
case HIGH_POINT_WINNER_GETS_SIX:
return stringMessages.scoringSchemeWinnerGetsSix();
case HIGH_POINT_WINNER_GETS_EIGHT:
return stringMessages.scoringSchemeWinnerGetsEight();
case HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT:
return stringMessages.scoringSchemeHighPointFirstGetsTenOrEight();
}
@@ -79,6 +79,9 @@
<source path='ui/shared' />
<source path='ui/actions' />
<source path='ui/simulator' />
<source path='ui/adminconsole' />
<source path='ui/usermanagement' />
<source path='ui/masterdataimport' />
<source path='ui/regattaoverview' />
<source path='ui/leaderboard'/>
<source path='home' />
@@ -34,6 +34,9 @@
<source path='common'/>
<source path="client" />
<source path="datamining" />
<source path="adminconsole" />
<source path="masterdataimport" />
<source path="usermanagement" />
<source path="simulator" />
<source path='shared' />
<source path='common' />
@@ -52,6 +52,9 @@
<source path='common'/>
<source path='client'/>
<source path='controls'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='masterdataimport'/>
<source path='components'/>
<source path='leaderboard'/>
<source path='regattaoverview'/>
@@ -37,6 +37,8 @@
<source path='client'/>
<source path='simulator'/>
<source path='usermanagement'/>
<source path='masterdataimport'/>
<source path='adminconsole'/>
<source path='shared'/>
<source path='leaderboard'/>
</module>
@@ -10,6 +10,11 @@
<inherits name="com.sap.sse.SSECommon" />
<inherits name="com.sap.sailing.domain.SailingDomain" />
<!-- Fancy DateTimePicker (without the rest of Bootstrap!) -->
<!-- GWT-Bootstrap License: Apache License, Version 2.0 -->
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Google Maps API -->
@@ -23,7 +28,11 @@
<extend-property name="locale" values="de"/>
<source path='client' />
<source path='actions'/>
<source path='shared'/>
<source path='common'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='masterdataimport'/>
<source path='simulator'/>
<source path='leaderboard'/>
</module>
@@ -11,6 +11,10 @@
<inherits name="com.sap.sailing.domain.SailingDomain" />
<!-- Highcharts API -->
<inherits name="org.moxieapps.gwt.highcharts.Highcharts" />
<!-- Fancy DateTimePicker (without the rest of Bootstrap!) -->
<!-- GWT-Bootstrap License: Apache License, Version 2.0 -->
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<!-- Google Maps API -->
<inherits name='com.google.gwt.ajaxloader.AjaxLoader' />
<inherits name='com.google.gwt.maps.Maps' />
@@ -25,5 +29,8 @@
<source path='actions'/>
<source path='common'/>
<source path='simulator'/>
<source path='adminconsole'/>
<source path='usermanagement'/>
<source path='masterdataimport'/>
<source path='leaderboard'/>
</module>
@@ -0,0 +1,130 @@
package com.sap.sse.gwt.client;
import java.util.HashSet;
import java.util.Set;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.shared.HandlerRegistration;
/**
* Represents the browser's localStorage and sessionStorage objects and provides eventing support.
*
* @author Axel Uhl (D043530)
*
*/
public class Storage extends JavaScriptObject {
private static final Set<StorageEvent.Handler> storageEventHandlers = new HashSet<>();
static {
registerAsStorageEventHandler();
}
protected Storage() {
super();
}
private static void registerAsStorageEventHandler() {
if (isSupported()) {
registerAsStorageEventHandlerImpl();
}
}
private static native void registerAsStorageEventHandlerImpl() /*-{
$wnd.addEventListener("storage", function(e) {
@com.sap.sse.gwt.client.Storage::onStorageEvent(Lcom/google/gwt/core/client/JavaScriptObject;)(e);
});
}-*/;
public static HandlerRegistration addStorageEventHandler(final StorageEvent.Handler handler) {
storageEventHandlers.add(handler);
return new HandlerRegistration() {
@Override
public void removeHandler() {
storageEventHandlers.remove(handler);
}
};
}
public static void removeStorageEventHandler(StorageEvent.Handler handler) {
storageEventHandlers.remove(handler);
}
private static void onStorageEvent(JavaScriptObject event) {
StorageEvent storageEvent = event.cast();
for (StorageEvent.Handler handler : storageEventHandlers) {
handler.onStorageChange(storageEvent);
}
}
private native static JavaScriptObject getLocalStorageIfSupportedImpl() /*-{
return $wnd.localStorage;
}-*/;
private native static JavaScriptObject getSessionStorageIfSupportedImpl() /*-{
return $wnd.sessionStorage;
}-*/;
public native static boolean isLocalStorageSupported() /*-{
try {
return "localStorage" in $wnd && $wnd["localStorage"] !== null;
} catch (e) {
return false;
}
}-*/;
public native static boolean isSessionStorageSupported() /*-{
try {
return "sessionStorage" in $wnd && $wnd["sessionStorage"] !== null;
} catch (e) {
return false;
}
}-*/;
public static boolean isSupported() {
return isLocalStorageSupported() && isSessionStorageSupported();
}
public static Storage getLocalStorageIfSupported() {
final Storage result;
if (isLocalStorageSupported()) {
result = getLocalStorageIfSupportedImpl().cast();
} else {
result = null;
}
return result;
}
public static Storage getSessionStorageIfSupported() {
final Storage result;
if (isSessionStorageSupported()) {
result = getSessionStorageIfSupportedImpl().cast();
} else {
result = null;
}
return result;
}
public final native void setItem(String key, String value) /*-{
this.setItem(key, value);
}-*/;
public final native String getItem(String key) /*-{
return this.getItem(key);
}-*/;
public final native void removeItem(String key) /*-{
return this.removeItem(key);
}-*/;
public final native void clear() /*-{
this.clear();
}-*/;
public final native String getKey(int index) /*-{
return this.key(index);
}-*/;
public final native int getLength() /*-{
return this.length;
}-*/;
}
@@ -0,0 +1,46 @@
package com.sap.sse.gwt.client;
import com.google.gwt.core.client.JavaScriptObject;
/**
* A change event sent to a {@link Handler} object that has been {@link Storage#addStorageEventHandler(Handler) registered}
* with the browser's {@link Storage}. It will receive events from both, the session storage and the local storage. Which one
* the event came from can be determined by calling {@link #getStorageArea()} on the event and comparing with either
* {@link Storage#getLocalStorageIfSupported()} or {@link Storage#getSessionStorageIfSupported()}.
*
* @author Axel Uhl (D043530)
*
*/
public class StorageEvent extends JavaScriptObject {
protected StorageEvent() {
super();
}
public static interface Handler {
void onStorageChange(StorageEvent event);
}
public final native String getKey() /*-{
return this.key;
}-*/;
public final native String getNewValue() /*-{
return this.newValue;
}-*/;
public final native String getOldValue() /*-{
return this.oldValue;
}-*/;
public final Storage getStorageArea() {
return getStorageAreaImpl().cast();
}
private final native JavaScriptObject getStorageAreaImpl() /*-{
return this.storageArea;
}-*/;
public final native String getUrl() /*-{
return this.url;
}-*/;
}
+2
View File
@@ -2,4 +2,6 @@
Our data is obtained from sensors and user input. Both can be flaky and lack accuracy. We already detect major outliers in the GPS and wind data. However, many data quality issues remain. Particularly, aggregating data of different levels of quality may need to propagate some information about quality and confidence to the aggregated values so that consumers may judge the overall confidence of the aggregated results.
Also, when data has been detected as flaky or plain wrong, it should be possible to exclude such data from further reporting.
See also [Bug 1243](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1243).
+3 -1
View File
@@ -9,7 +9,9 @@ The script `/home/gollum/wiki/serve.sh` can be executed to either start or resta
Accessing this wiki is normally only allowed for authenticated users. If you want to share your work with others not having an account here then you can just request making a given url publicly available. On the server this is done by simply putting a new line to `/home/gollum/wiki/public.txt`.
### Creating a New Account
A new account can be created by adding a new entry to `/home/gollum/wiki/users.yml`. The password there is encrypted using sha1sum (`echo -n "password" | sha1sum`) or, for those who don't happen to have sha1sum available, using an online SHA1 generator such as [this one](http://www.sha1-online.com/).
Send a request to Axel Uhl or Simon Marcel Pamies that includes the SHA1 hash of your desired password. Obtain such an SHA1 hash for your password here: http://www.sha1-online.com/.
A Wiki administrator can add a new account by adding a new entry to `/home/gollum/wiki/users.yml`. The password there is encrypted using sha1sum (`echo -n "password" | sha1sum`) or, for those who don't happen to have sha1sum available, using an online SHA1 generator such as [this one](http://www.sha1-online.com/).
### Editing
You can edit information here freely but do not leave any nonsense here.
+4
View File
@@ -1,3 +1,7 @@
Planning 2014 / 2015
See [http://wiki.sapsailing.com/wiki/planning/offseason-2014-2015](http://wiki.sapsailing.com/wiki/planning/offseason-2014-2015).
# Planning 2013 / 2014
During our workshop of 2013-09-30, three major areas of development were identified as candidates for focus topics for the next few months. These are:
+14
View File
@@ -1,3 +1,17 @@
# Live Audio Streaming
See also [Bug 1522](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1522). We currently have the ManyPlayers Race Viewer that supports this use case. It is based on Flash and requires several additional server-side components. Adding live audio support to the HTML-based SAP Sailing Analytics could simplify the consumption of live audio streams for certain use cases and could ease server administration considerably.
# Update Oct 13 2014
With commit 11d7a168 we support Youtube live streaming. This can be used as replacement for audio-only streaming.
## Benefits
- Recording and streaming is all provided by Youtube.
- Can be complemented with video and other Youtube gimmicks (live pictures, stills, user notifications, user links)
## Shortcomings
- 4h max. duration per session. Otherwise Youtube's rolling storage starts overwriting old content.
- Audio-only not yet possible. But hiding the video panel should be not too much effort.
+49
View File
@@ -0,0 +1,49 @@
# Off-Season 2014/2015 Planning
Planning the off-season activities until the first 2015 event, presumably the first ESS act in Singapore, early February 2015:
We see X areas on which we'd like to focus our work:
## newhome
- A number of bugs and issues have been recorded during and after the first events run with the newhome implementation. See [our Bugzilla Bug #1928](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=1928).
- Navigation Clean-Up: in several sessions with Ubilabs we learned that the current navigation structure is not yet ideal. Ubilabs will come up with an improved suggestions for the site's overall navigational structure that we then have to jointly implement.
- Regatta Overview: This has so far been the tool for the race committees and regatta organizers. We need to find out whether the newhome implementation takes over the role that so far was fulfilled by the RegattaOverview.html entry point or if we still need a page specifically geared towards this audience.
- Live Center support: Media updates and live streams, information coming from the Race Committee App, mixed with the live tracking and scoring information shall constitute the live center content to be implemented in the newhome architecture.
- User Management in the UI: we need support for Sign Up/In/Out on all newhome pages and the race viewer.
- Per Race and Per Regatta default statistics: Instead of leaving the use of the tools only to the user, we want pre-configured default set-ups particularly of our RaceBoard tool to support specific types of analyses, such as start analysis, maneuver analysis, venue analysis and wind pattern analysis. We need separate pages that group these types of analyses, and we need the possibility to pre-configure our tools and views in the ways required.
## Bookmarkability and Sharability
See also [Bug 506](http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=506). We need to be able to capture the entire state of a page in a serializable way so that it can be used to construct a URL which can be shared and based on which another user can re-construct the entire state of the page as it was. Furthermore, the serializability of all settings will help towards improved history management. When a user navigates back using the browser's back button, the page state can be reconstructed exactly the way it was when the user left off.
Serializable settings will also help in the context of user-specific preferences. When we can serialize all settings, we can also put them to the user store when a user is logged on. This way, when the user returns to that page (or similar pages) the same settings can be applied automatically.
## User Management
See [http://wiki.sapsailing.com/wiki/planning/usermanagement](http://wiki.sapsailing.com/wiki/planning/usermanagement) for a description. Some progress has already been made, but it's going to be a lot more work to update our existing UIs, no longer using HTTP Basic Authentication, replacing this with Shiro's authentication and authorization concepts. As briefly touched above, this also has implications on the newhome design.
## Volume Business
Reaching a broader audience with the SAP Sailing Analytics will mainly happen through two channels: smartphone tracking and a free-to-use race committee app. Both activities are underway with Ubilabs contributing the UI/UX design and SAP contributing additional development support. We plan to complete one major iteration of both, the smartphone tracking app for iOS and Android, and one major iteration of the race committee app until the end of this planning time frame.
## Data Quality
See [http://wiki.sapsailing.com/wiki/data-quality](http://wiki.sapsailing.com/wiki/data-quality). We think that transparency needs to be the first step. Therefore, we should start working on internal analyses, probably with the help of the DataMining framework (see below), to produce reports that show us all the facts about the data quality so far. Only then can we decide how much to invest into cleansing and outlier detection and how much to spend on advanced aggregation techniques that live with sparse and lossy data.
## Data Mining and Polar Sheets
We have made good progress with the DataMining framework and corresponding branch. The PolarSheet calculations are to be migrated to the DataMining framework. We want to implement a first set of analysis "models" with a prototypical UI that allows us to test the DataMining framework's maturity. Only if this works out well can we continue with UI/UX design.
## Simulator Integration
The simulator has been integrated with the race viewer. It is currently activated by a hidden URL parameter. We assume that we should attach the availability of this feature to a specific user role, such as coach or partner. Further, the simulator should consider integrating the simulated tracks as "virtual competitors" into an extended leaderboard view, but this feature is out of scope for the time frame discussed here.
## Web Site Access Statistics
We agree that better information about access to our web site would be very helpful. Simon had set up Piwik to analyze our Apache logs. This didn't work so well because the performance for importing the logs is really bad. However, the Apache logs contain only a small portion of what we really would like to know about our users' behavior. In particular, many of the essential requests are HTTP POST requests of which Apache logs only the URL, not the actual request parameters.
We therefore will need to log at a more fine-grained level on the server and probably also capture and collect some user statistics on the client, particularly for those interactions that don't immediately result in a server round-trip. This logging data will then be made amenable to advanced analysis.
We agreed that extending a Bachelor Thesis position or a DHBW internship to work on the topic will be best suited to move this topic ahead.
+1 -1
View File
@@ -14,6 +14,6 @@ We need easy to use and manage sign up, sign on, sign out and manage user accoun
See also bug 27 (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=27).
There is a branch `usermanagement` that contains Benjamin Ebling's contributions to the subject, namely a set of bundles that integrate Apache Shiro with the SAP Sailing Analytics, providing the necessary sign-up, sign-on and sign-out functionality and allowing front end and back end to identify the current user.
There is a branch `usermanagement` that contains Benjamin Ebling's contributions to the subject, namely a set of bundles that integrate Apache Shiro with the SAP Sailing Analytics, providing the necessary sign-up, sign-on and sign-out functionality and allowing front end and back end to identify the current user. This branch has been forked to `axel-usermanagement` which is the continuation of Benjamin's work, working towards master mergability.
On top of that we need to implement account management where users can be assigned to specific accounts, such as a club or event of regatta account. Access by users to administrative features of regattas and events and analytics visibility could then be nicely restricted to users belonging to the right accounts. Technically, an account could probably be implemented as a role, and events, regattas or races could use such special roles to control access to their data.
+4 -65
View File
@@ -5,69 +5,8 @@ The term itself should be revised at some point, and currently refers to the tec
This is the second iteration of implementing this idea. For previous documentation, see [[smartphone tracking|wiki/smartphone-tracking]].
[[_TOC_]]
## Server Architecture
[[Server Architecture|wiki/racelog-tracking/server]]
# Development Infos
RaceLog tracking has been merged into the master branch with commit 4b4b61b6c518139f4389aabd73c282621711855a. It was developed on the following branches:
* ``ftes-rltracking``: The main RaceLog-tracking development
* ``ftes-rltracking-equestrian``: Serves as a reference implementation of a tracking adapter built for RaceLog-tracking.
# Architectural Overview
The basic architecture of Racelog-tracking is presented in this diagram (download as [[PDF|racelog-tracking/architecture.pdf]]):
[[racelog-tracking/architecture.svg]]
Following the numbers in the diagram, this is a possible race log tracking scenario:
1. The race is defined through events that are added to the RaceLog.
2. The RaceTracker is created.
3. As soon as the "StartTrackingEvent" is added to the RaceLog, the RaceTracker creates the TrackedRace.
4. Tracking devices submit GPS fixes to the tracking adapter. This adds these fixes to the global GPSFixStore.
5. The GPSFixStore notifies its listeners - among them the RaceTrackers - of new fixes. Each RaceTracker checks whether a new fix matches the mappings defined in its RaceLog, and if so adds it to the TrackedRace.
Not all identifiers represent actual class or bundle names. For a more technical documentation, refer to the JavaDoc in the various ``*.racelog.tracking`` packages and the ``com.sap.sailing.domain.racelogtrackingadapter`` bundle. The following interfaces and classes are good starting points:
* DeviceIdentifier
* DeviceIdentifierSerializationHandler
* Revokable
* DeviceMappingFinder
* PingDeviceIdentifier, PlaceHolderDeviceIdentifier
# AdminConsole Components
Currently, RaceLogs can be filled with the race metadata via the _RaceLog Tracking_ panel in the AdminConsole. Here one can denote RaceColumn/Fleet combinations within RegattaLeaderboards for RaceLog-tracking, register competitors, define the course layout, add device mappings, and finally start tracking.
When thinking about smartphone tracking, it would of course be a good idea to also integrate similar functionality into the tracking app. Some parts of the communication (registering competitors, defining the course, mapping devices) can be handled via the existing RaceLog communication mechanism. Other parts (creating the Leaderboard structure in the first place, adding the RaceLog tracker) have to be dealt with separately, e.g. via a REST API.
## Steps for setting up a racelog-tracked race in the AdminConsole
[[Walkthrough with screenshots|wiki/racelog-tracking/walkthrough]]
## Reloading a race that has already been tracked
Technically, the entire race is loaded as soon as the RaceLogRaceTracker is attached to the RaceLog, as it will find the already existing StartTrackingEvent and load all fixes that correspond to the mappings.
In the AdminConsole, triggering this step is no different from adding the tracker for the very first time, do so with the _start tracking_ button the the RaceLog Tracking Panel.
# ToDos
## Archiving old Races
Since RaceLog-tracking allows for fully independent tracking, storing and reloading of races, it may be a good foundation for archiving old races. Currently, we rely on tracking providers to retain all data indefinitely, so that it can be reloaded, e.g., after restarting the server. Also see [[bug 2|http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2]] for more details.
## Smartphone Tracking
RaceLog-tracking provides the server-side abilities for independent tracking. Therefore, using smartphones for tracking is one possible application. So far, there is no implementation in terms of a smartphone app. The relation to the existing RaceCommittee app has be be considered, as both should share a common code base, and as there should be certain points of integration (e.g., first defining the race in the tracking app, then setting the start time in the RC-app, and finally tracking one boat with that smartphone - again with the tracking app).
The first option is to simply share code through a Android library module, the second option is integrating everything into one app with two launchers (one for tracking, one for the RaceCommittee functionality).
# How to create a Tracking Adapter
By using the OSGi service registry, adapters are completely decoupled from the Sailing Analytics code. In future, it should be possible to simply deploy one additional bundle to the OSGi server in addition to the Sailing Analytics bundles. This requires provisioning the relevant bundles containing interfaces for the development of the adapter.
The first attempt so far (``ftes-rltracking-equestrian`` branch) is completely restricted to one bundle. However, this is a branch branched from ``master``, and the new bundle has been added to the existing launch configurations and build and deployment descriptors (``pom.xml``, ``feature.xml``, ``raceanalysis.product``). This makes developing and testing easy, but is not in line with the goal stated above.
Steps for creating an adapter:
1. Create a new project: ``com.sap.sailing.domain.<adaptername>``. Think about duplicating an existing project, such as ``com.sap.sailing.domain.racelogtrackingadapter``. In this case, don't forget to adapt the project's ``pom.xml``, ``META-INF/MANIFEST.MF`` and ``.project`` files.
2. Add the new project to the maven build in ``java/pom.xml``.
3. Add the project as an auto-start bundle to the eclipse launch configs. The bundle needs to be started before the central ``com.sap.sailing.server`` bundle, for which currently a startup-level of ``3`` is sufficient.
4. Add the bundle to the ``com.sap.sailing.feature/feature.xml``, and also to the ``com.sap.sailing.feature.p2build/raceanalysis.product`` with the same startup properties as before.
5. Implement a ``DeviceIdentifier`` and the appropriate ``DeviceIdentifierSerializationHandler``s (refer to the JavaDoc of ``DeviceIdentifier``).
6. Register your serialization handlers through the OSGi service registry (refer to the JavaDoc of ``DeviceIdentifierSerializationHandler`` for an example on how to do so).
7. Add some kind of Servlet or similar that adds fixes to the GPSFixStore by calling ``storeFix(DeviceIdentifier device, GPSFix fix)`` on the `GPSFixStore` which can be obtained from `RacingEventService.getGPSFixStore()`.
8. Fire up the server, let OSGi work its magic, define the race metadata and start adding fixes.
## App Architecture
[[App Architecture|wiki/racelog-tracking/app]]
+43
View File
@@ -0,0 +1,43 @@
# RaceLog Tracking App Architecture
[[_TOC_]]
# Development Info
Development is currently underway on the following branches:
* ``ftes-rltracking-app``
* ``jbross-rltracking-app``
# Project and Build structure
## Projects
* ``com.sap.sailing.android.shared`` contains shared code and resources between the Android apps (tracking and [[RCApp|wiki/racecommittee-app]])
* ``com.sap.sailing.android.tracking.app`` is the main project for the app
## Maven
The app cannot only be built and deployed via the Android Eclipse tooling, but is also integrated into the maven build.
## Deployment
# Sending Fixes
* currently to the ``RecordFixesFlatJsonPostServlet`` in the ``racelogtrackingadapter``
```
{ deviceUuid: ...,
timeMillis: ...,
latDeg: ...,
lonDeg: ...,
speedMperS: ...,
bearingDeg: ... }
```
# Mapping to a Competitor
We use a QRCode to transfer the necessary server, race and competitor data to the smartphone. The app can then add the mapping to the RaceLog (the race data is necessary to determine which RaceLog to add to, and the MappingEvent that is added to the RaceLog then contains the DeviceIdentifier and Competitor ID).
Structure of the URL encoded in the QRCode:
```
<serverURL-and-port>/apps/com.sap.sailing.android.tracking.app.apk
?leaderboard=<...>
&raceColumn=<...>
&fleet=<...>
&competitor=<...>
```
By beginning the URL with ``<serverURL-and-port>/apps/com.sap.sailing.android.tracking.app.apk`` it is possible to download and install the app directly, if the QRCode is scanned with a barcode-scanner app.
+68
View File
@@ -0,0 +1,68 @@
# RaceLog Tracking Server Architecture
[[_TOC_]]
# Development Infos
RaceLog tracking has been merged into the master branch with commit 4b4b61b6c518139f4389aabd73c282621711855a. It was developed on the following branches:
* ``ftes-rltracking``: The main RaceLog-tracking development
* ``ftes-rltracking-equestrian``: Serves as a reference implementation of a tracking adapter built for RaceLog-tracking.
# Architectural Overview
The basic architecture of Racelog-tracking is presented in this diagram (download as [[PDF|/wiki/racelog-tracking/architecture.pdf]]):
[[/wiki/racelog-tracking/architecture.svg]]
Following the numbers in the diagram, this is a possible race log tracking scenario:
1. The race is defined through events that are added to the RaceLog.
2. The RaceTracker is created.
3. As soon as the "StartTrackingEvent" is added to the RaceLog, the RaceTracker creates the TrackedRace.
4. Tracking devices submit GPS fixes to the tracking adapter. This adds these fixes to the global GPSFixStore.
5. The GPSFixStore notifies its listeners - among them the RaceTrackers - of new fixes. Each RaceTracker checks whether a new fix matches the mappings defined in its RaceLog, and if so adds it to the TrackedRace.
Not all identifiers represent actual class or bundle names. For a more technical documentation, refer to the JavaDoc in the various ``*.racelog.tracking`` packages and the ``com.sap.sailing.domain.racelogtrackingadapter`` bundle. The following interfaces and classes are good starting points:
* DeviceIdentifier
* DeviceIdentifierSerializationHandler
* Revokable
* DeviceMappingFinder
* PingDeviceIdentifier, PlaceHolderDeviceIdentifier
# AdminConsole Components
Currently, RaceLogs can be filled with the race metadata via the _RaceLog Tracking_ panel in the AdminConsole. Here one can denote RaceColumn/Fleet combinations within RegattaLeaderboards for RaceLog-tracking, register competitors, define the course layout, add device mappings, and finally start tracking.
When thinking about smartphone tracking, it would of course be a good idea to also integrate similar functionality into the tracking app. Some parts of the communication (registering competitors, defining the course, mapping devices) can be handled via the existing RaceLog communication mechanism. Other parts (creating the Leaderboard structure in the first place, adding the RaceLog tracker) have to be dealt with separately, e.g. via a REST API.
## Steps for setting up a racelog-tracked race in the AdminConsole
[[Walkthrough with screenshots|wiki/racelog-tracking/walkthrough]]
## Reloading a race that has already been tracked
Technically, the entire race is loaded as soon as the RaceLogRaceTracker is attached to the RaceLog, as it will find the already existing StartTrackingEvent and load all fixes that correspond to the mappings.
In the AdminConsole, triggering this step is no different from adding the tracker for the very first time, do so with the _start tracking_ button the the RaceLog Tracking Panel.
# ToDos
## Archiving old Races
Since RaceLog-tracking allows for fully independent tracking, storing and reloading of races, it may be a good foundation for archiving old races. Currently, we rely on tracking providers to retain all data indefinitely, so that it can be reloaded, e.g., after restarting the server. Also see [[bug 2|http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=2]] for more details.
## Smartphone Tracking
RaceLog-tracking provides the server-side abilities for independent tracking. Therefore, using smartphones for tracking is one possible application. So far, there is no implementation in terms of a smartphone app. The relation to the existing RaceCommittee app has be be considered, as both should share a common code base, and as there should be certain points of integration (e.g., first defining the race in the tracking app, then setting the start time in the RC-app, and finally tracking one boat with that smartphone - again with the tracking app).
The first option is to simply share code through a Android library module, the second option is integrating everything into one app with two launchers (one for tracking, one for the RaceCommittee functionality).
# How to create a Tracking Adapter
By using the OSGi service registry, adapters are completely decoupled from the Sailing Analytics code. In future, it should be possible to simply deploy one additional bundle to the OSGi server in addition to the Sailing Analytics bundles. This requires provisioning the relevant bundles containing interfaces for the development of the adapter.
The first attempt so far (``ftes-rltracking-equestrian`` branch) is completely restricted to one bundle. However, this is a branch branched from ``master``, and the new bundle has been added to the existing launch configurations and build and deployment descriptors (``pom.xml``, ``feature.xml``, ``raceanalysis.product``). This makes developing and testing easy, but is not in line with the goal stated above.
Steps for creating an adapter:
1. Create a new project: ``com.sap.sailing.domain.<adaptername>``. Think about duplicating an existing project, such as ``com.sap.sailing.domain.racelogtrackingadapter``. In this case, don't forget to adapt the project's ``pom.xml``, ``META-INF/MANIFEST.MF`` and ``.project`` files.
2. Add the new project to the maven build in ``java/pom.xml``.
3. Add the project as an auto-start bundle to the eclipse launch configs. The bundle needs to be started before the central ``com.sap.sailing.server`` bundle, for which currently a startup-level of ``3`` is sufficient.
4. Add the bundle to the ``com.sap.sailing.feature/feature.xml``, and also to the ``com.sap.sailing.feature.p2build/raceanalysis.product`` with the same startup properties as before.
5. Implement a ``DeviceIdentifier`` and the appropriate ``DeviceIdentifierSerializationHandler``s (refer to the JavaDoc of ``DeviceIdentifier``).
6. Register your serialization handlers through the OSGi service registry (refer to the JavaDoc of ``DeviceIdentifierSerializationHandler`` for an example on how to do so).
7. Add some kind of Servlet or similar that adds fixes to the GPSFixStore by calling ``storeFix(DeviceIdentifier device, GPSFix fix)`` on the `GPSFixStore` which can be obtained from `RacingEventService.getGPSFixStore()`.
8. Fire up the server, let OSGi work its magic, define the race metadata and start adding fixes.