mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-17 17:50:56 +00:00
Merge remote-tracking branch 'origin/master' into riccardo
Conflicts: java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java java/com.sap.sailing.gwt.ui/SailingGWT.launch java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/BoatClassJsonDeserializer.java java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java java/com.sap.sailing.simulator.test/src/com/sap/sailing/simulator/test/util/RaceDataAccessEval.java java/com.sap.sailing.simulator.test/src/com/sap/sailing/simulator/test/util/RacingEventPersistence.java java/com.sap.sailing.simulator.test/src/com/sap/sailing/simulator/test/util/TracTracReaderFromURLs.java java/com.sap.sailing.simulator.test/src/com/sap/sailing/simulator/test/util/TracTracWriter.java java/target/stop
This commit is contained in:
commit
69b7096b3d
372 files changed
+72853
-877361
No files matched your search
@@ -8,6 +8,8 @@ manifest.txt
|
||||
java/com.sap.sailing.gwt.ui/gwt-unitCache/*
|
||||
java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/*
|
||||
sailing_debug0*
|
||||
dist
|
||||
build
|
||||
/java/.settings/org.eclipse.jdt.core.prefs
|
||||
/mobile/com.sap.sailing.racecommittee.app/.settings/org.eclipse.jdt.core.prefs
|
||||
/mobile/com.sap.sailing.racecommittee.app/bin/*
|
||||
|
||||
@@ -12,8 +12,8 @@ find_project_home ()
|
||||
PARENT_DIR=`cd $1/..;pwd`
|
||||
OUTPUT=$(find_project_home $PARENT_DIR)
|
||||
|
||||
if [ "$OUTPUT" = "" ] && [ -d "$PARENT_DIR/code" ] && [ -d "$PARENT_DIR/code/.git" ]; then
|
||||
OUTPUT="$PARENT_DIR/code"
|
||||
if [ "$OUTPUT" = "" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY" ] && [ -d "$PARENT_DIR/$CODE_DIRECTORY/.git" ]; then
|
||||
OUTPUT="$PARENT_DIR/$CODE_DIRECTORY"
|
||||
fi
|
||||
echo $OUTPUT
|
||||
return 0
|
||||
@@ -56,6 +56,7 @@ active_branch=`basename $active_branch`
|
||||
HEAD_SHA=$(git show-ref --head -s | head -1)
|
||||
HEAD_DATE=$(date "+%Y%m%d%H%M")
|
||||
VERSION_INFO="$HEAD_SHA-$active_branch-$HEAD_DATE"
|
||||
SIMPLE_VERSION_INFO="$active_branch-$HEAD_DATE"
|
||||
|
||||
MAVEN_SETTINGS=$PROJECT_HOME/configuration/maven-settings.xml
|
||||
MAVEN_SETTINGS_PROXY=$PROJECT_HOME/configuration/maven-settings-proxy.xml
|
||||
@@ -75,7 +76,7 @@ suppress_confirmation=0
|
||||
extra=''
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "buildAndUpdateProduct [-b -u -g -t -o -c -m <config> -n <package> -l <port>] [build|install|all|hot-deploy|remote-deploy]"
|
||||
echo "buildAndUpdateProduct [-b -u -g -t -o -c -m <config> -n <package> -l <port>] [build|install|all|hot-deploy|remote-deploy|release]"
|
||||
echo ""
|
||||
echo "-g Disable GWT compile, no gwt files will be generated, old ones will be preserved."
|
||||
echo "-b Build GWT permutation only for one browser and English language."
|
||||
@@ -86,15 +87,22 @@ if [ $# -eq 0 ]; then
|
||||
echo "-m <path to file> Specify alternate maven configuration (possibly has side effect on proxy setting)"
|
||||
echo "-n <package name> Name of the bundle you want to hot deploy. Needs fully qualified name like"
|
||||
echo " com.sap.sailing.monitoring. Only works if there is a fully built server available."
|
||||
echo " This parameter can also hold the name of the release if you are using the release command."
|
||||
echo "-l <telnet port> Telnet port the OSGi server is running. Optional but enables fully automatic hot-deploy."
|
||||
echo "-s <target server> Name of server you want to use as target for install, hot-deploy or remote-reploy. This overrides default behaviour."
|
||||
echo "-w <ssh target> Target for remote-deploy. Must comply with the following format: user@server."
|
||||
echo "-w <ssh target> Target for remote-deploy and release. Must comply with the following format: user@server."
|
||||
echo "-u Run without confirmation messages. Use with extreme care."
|
||||
echo ""
|
||||
echo "build: builds the server code using Maven to $PROJECT_HOME (log to $START_DIR/build.log)"
|
||||
echo ""
|
||||
echo "install: installs product and configuration to $SERVERS_HOME/$active_branch. Overwrites any configuration by using config from branch."
|
||||
echo ""
|
||||
echo "all: invokes build and then install"
|
||||
echo ""
|
||||
echo "release: Releases a server package to the location specified by -w parameter. The release is named using the branch name and the date."
|
||||
echo "You can overwrite the generated release name by specifying a name with the parameter -n. Do not use spaces or other special characters!"
|
||||
echo "Example: $0 -w trac@sapsailing.com -n release-ess-brazil-2013 release"
|
||||
echo ""
|
||||
echo "hot-deploy: performs hot deployment of named bundle into OSGi server"
|
||||
echo "Example: $0 -n com.sap.sailing.www -l 14888 hot-deploy"
|
||||
echo ""
|
||||
@@ -119,7 +127,7 @@ do
|
||||
case $option in
|
||||
g) gwtcompile=0;;
|
||||
t) testing=0;;
|
||||
b) onegwtpermutationonly=1;;
|
||||
b) onegwtpermutationonly=1;;
|
||||
o) offline=1;;
|
||||
c) clean="";;
|
||||
p) proxy=1;;
|
||||
@@ -141,10 +149,111 @@ echo INSTALL goes to $ACDIR
|
||||
shift $((OPTIND-1))
|
||||
|
||||
if [[ $@ == "" ]]; then
|
||||
echo "You need to specify an action [build|install|all|hot-deploy|remote-deploy]"
|
||||
echo "You need to specify an action [build|install|all|hot-deploy|remote-deploy|release]"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$@" == "release" ]]; then
|
||||
if [ ! -d $p2PluginRepository/plugins ]; then
|
||||
echo "Could not find source directory $p2PluginRepository!"
|
||||
exit
|
||||
fi
|
||||
|
||||
RELEASE_NOTES=""
|
||||
echo ""
|
||||
echo "Please provide me with some notes about this release. You can add more than"
|
||||
echo "one line. Please include major changes or new features. After your notes I will"
|
||||
echo "also include the commits of the last 4 weeks. You can save and quit by hitting ctrl+d."
|
||||
while read -e -p "> " line; do
|
||||
RELEASE_NOTES="$RELEASE_NOTES\n$line"
|
||||
done
|
||||
|
||||
if [[ $RELEASE_NOTES == "" ]]; then
|
||||
echo -e "\nCome on - I can not release without at least some notes about this release!"
|
||||
exit
|
||||
fi
|
||||
echo -e "\nThank you! One last thing..."
|
||||
|
||||
echo "How many weeks of commits do you want to include (0=No commits)?"
|
||||
read -p "> " -e COMMIT_WEEK_COUNT
|
||||
|
||||
mkdir -p $PROJECT_HOME/dist
|
||||
mkdir -p $PROJECT_HOME/build
|
||||
|
||||
RELEASE_NOTES="Release $VERSION_INFO\n$RELEASE_NOTES"
|
||||
echo -e $RELEASE_NOTES > $PROJECT_HOME/build/release-notes.txt
|
||||
echo "" >> $PROJECT_HOME/build/release-notes.txt
|
||||
echo "Commits for the last $COMMIT_WEEK_COUNT weeks:" >> $PROJECT_HOME/build/release-notes.txt
|
||||
echo "" >> $PROJECT_HOME/build/release-notes.txt
|
||||
cd $PROJECT_HOME
|
||||
git log --decorate --pretty=format:"%h - %an, %ar : %s" --date=relative --abbrev-commit --since=$COMMIT_WEEK_COUNT.weeks >> $PROJECT_HOME/build/release-notes.txt
|
||||
|
||||
cd $PROJECT_HOME/build
|
||||
ACDIR=$PROJECT_HOME/build
|
||||
|
||||
mkdir -p configuration/jetty/etc
|
||||
mkdir plugins
|
||||
|
||||
cp -v $PROJECT_HOME/java/target/start $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/stop $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/status $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/shouldIBuildOrShouldIGo.sh $ACDIR/
|
||||
|
||||
cp -v $PROJECT_HOME/java/target/env.sh $ACDIR/
|
||||
cp -v $p2PluginRepository/configuration/config.ini configuration/
|
||||
|
||||
cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/jetty.xml configuration/jetty/etc
|
||||
cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/jetty-selector.xml configuration/jetty/etc
|
||||
cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/jetty-deployer.xml configuration/jetty/etc
|
||||
cp -v $PROJECT_HOME/java/target/configuration/jetty/etc/realm.properties configuration/jetty/etc
|
||||
cp -v $PROJECT_HOME/java/target/configuration/monitoring.properties configuration/
|
||||
cp -v $PROJECT_HOME/configuration/mongodb.cfg $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/udpmirror $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/http2udpmirror $ACDIR
|
||||
cp -v $PROJECT_HOME/java/target/configuration/logging.properties $ACDIR/configuration
|
||||
cp -r -v $p2PluginRepository/configuration/org.eclipse.equinox.simpleconfigurator configuration/
|
||||
cp -vr $p2PluginRepository/plugins $ACDIR/
|
||||
cp -rv $PROJECT_HOME/configuration/native-libraries $ACDIR/
|
||||
cp -v $PROJECT_HOME/configuration/buildAndUpdateProduct.sh $ACDIR/
|
||||
|
||||
# make sure to save the information from env.sh
|
||||
. $ACDIR/env.sh
|
||||
|
||||
echo "$VERSION_INFO System:" > $ACDIR/configuration/jetty/version.txt
|
||||
|
||||
sed -i "/mongo.host/d" "$ACDIR/configuration/config.ini"
|
||||
sed -i "/mongo.port/d" "$ACDIR/configuration/config.ini"
|
||||
sed -i "/expedition.udp.port/d" "$ACDIR/configuration/config.ini"
|
||||
sed -i "/replication.exchangeName/d" "$ACDIR/configuration/config.ini"
|
||||
sed -i "/replication.exchangeHost/d" "$ACDIR/configuration/config.ini"
|
||||
sed -i "s/^.*jetty.port.*$/<Set name=\"port\"><Property name=\"jetty.port\" default=\"$SERVER_PORT\"\/><\/Set>/g" "$ACDIR/configuration/jetty/etc/jetty-selector.xml"
|
||||
|
||||
if [[ $OSGI_BUNDLE_NAME != "" ]]; then
|
||||
SIMPLE_VERSION_INFO=$OSGI_BUNDLE_NAME
|
||||
fi
|
||||
|
||||
mkdir $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
|
||||
`which tar` cvzf $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO/$SIMPLE_VERSION_INFO.tar.gz *
|
||||
cp $ACDIR/env.sh $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
|
||||
cp $PROJECT_HOME/build/release-notes.txt $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
|
||||
|
||||
cd $PROJECT_HOME
|
||||
rm -rf build/*
|
||||
|
||||
SSH_CMD="ssh $REMOTE_SERVER_LOGIN"
|
||||
SCP_CMD="scp -r"
|
||||
|
||||
echo "Packaged release $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO.tar.gz! I've put an env.sh that matches the current branch to $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO/env.sh!"
|
||||
|
||||
echo "Checking the remote connection..."
|
||||
REMOTE_HOME=`ssh $REMOTE_SERVER_LOGIN 'echo $HOME/releases'`
|
||||
echo "Now uploading release to $REMOTE_SERVER_LOGIN:$REMOTE_HOME. Can take quite a while!"
|
||||
|
||||
`which scp` -r $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO $REMOTE_SERVER_LOGIN:$REMOTE_HOME/
|
||||
echo "Uploaded release to $REMOTE_HOME! Make sure to also put an updated env.sh if needed to the right place ($REMOTE_HOME/environment in most cases)"
|
||||
fi
|
||||
|
||||
if [[ "$@" == "hot-deploy" ]]; then
|
||||
# check parameters
|
||||
if [[ $OSGI_BUNDLE_NAME == "" ]]; then
|
||||
@@ -291,7 +400,7 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
|
||||
for i in com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/*.gwt.xml; do
|
||||
echo "INFO: Patching $i files such that only one GWT permutation needs to be compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/^[ ]*<extend-property *name="locale" *values="de" *\/>/<!-- <extend-property name="locale" values="de"\/> --> <set-property name="user.agent" value="safari" \/>/' >$i.sed
|
||||
cat $i | sed -e 's/^[ ]*<extend-property *name="locale" *values="de" *\/>/<!-- <extend-property name="locale" values="de"\/> --> <set-property name="user.agent" value="gecko1_8" \/>/' >$i.sed
|
||||
mv $i.sed $i
|
||||
done
|
||||
else
|
||||
@@ -299,7 +408,7 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
|
||||
for i in com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/*.gwt.xml; do
|
||||
echo "INFO: Patching $i files such that all GWT permutations are compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/<!-- <extend-property *name="locale" *values="de" *\/> --> <set-property name="user.agent" value="safari" \/>/<extend-property name="locale" values="de"\/>/' >$i.sed
|
||||
cat $i | sed -e 's/<!-- <extend-property *name="locale" *values="de" *\/> --> <set-property name="user.agent" value="gecko1_8" \/>/<extend-property name="locale" values="de"\/>/' >$i.sed
|
||||
mv $i.sed $i
|
||||
done
|
||||
fi
|
||||
@@ -329,8 +438,12 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
|
||||
extra="$extra -P no-debug.without-proxy"
|
||||
fi
|
||||
|
||||
echo "Using following command: mvn $extra -fae -s $MAVEN_SETTINGS $clean install"
|
||||
mvn $extra -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log
|
||||
# make sure to honour the service configuration
|
||||
# needed to make sure that tests use the right servers
|
||||
APP_PARAMETERS="-Dmongo.host=$MONGODB_HOST -Dmongo.port=$MONGODB_PORT -Dexpedition.udp.port=$EXPEDITION_PORT -Dreplication.exchangeHost=$REPLICATION_HOST -Dreplication.exchangeName=$REPLICATION_CHANNEL"
|
||||
|
||||
echo "Using following command: mvn $extra -DargLine=\"$APP_PARAMETERS\" -fae -s $MAVEN_SETTINGS $clean install"
|
||||
mvn $extra -DargLine="$APP_PARAMETERS" -fae -s $MAVEN_SETTINGS $clean install 2>&1 | tee $START_DIR/build.log
|
||||
|
||||
if [ $gwtcompile -eq 1 ]; then
|
||||
# Now move back the backup .gwt.xml files before they were (maybe) patched
|
||||
@@ -393,6 +506,7 @@ if [[ "$@" == "install" ]] || [[ "$@" == "all" ]]; then
|
||||
cp -v $PROJECT_HOME/java/target/start $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/stop $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/status $ACDIR/
|
||||
cp -v $PROJECT_HOME/java/target/shouldIBuildOrShouldIGo.sh $ACDIR/
|
||||
|
||||
if [ ! -f "$ACDIR/env.sh" ]; then
|
||||
cp -v $PROJECT_HOME/java/target/env.sh $ACDIR/
|
||||
|
||||
BIN
Binary file not shown.
-874580
File diff suppressed because it is too large.
Load diff
@@ -25,6 +25,8 @@ Like businesses, sailors need the latest information to make strategic decisions
|
||||
* [[Development Environment|wiki/development-environment]]
|
||||
* [[Working with GWT Locally|wiki/local-gwt]]
|
||||
* [[Mobile Development|wiki/mobile-development]]
|
||||
* Information for Webdesigners
|
||||
* [[Layout repository|wiki/webdesign]]
|
||||
* General Information
|
||||
* [[Architecture and Infrastructure|wiki/architecture-and-infrastructure]]
|
||||
* [[Sailing Domain Algorithms|wiki/sailing-domain-algorithms]]
|
||||
@@ -46,3 +48,7 @@ Like businesses, sailors need the latest information to make strategic decisions
|
||||
* [Main Sailing Website](http://www.sapsailing.com)
|
||||
* [Visitor Statistics](http://analysis.sapsailing.com/)
|
||||
* [Traffic and CPU for app01](http://mrtg.sapsailing.com/)
|
||||
|
||||
### TracTrac Workshop in Kopenhagen
|
||||
|
||||
* [[TracTrac Workshop in October 2013 in Kopenhagen|wiki/TracTracWorkshop2013]]
|
||||
@@ -7,7 +7,7 @@
|
||||
<listEntry value="1"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.declination.impl.DeclinationStore"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="2012 2012 1"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="2014 2014 1"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.declination"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy.wdf.sap.corp -Dhttp.proxyPort=8080"/>
|
||||
</launchConfiguration>
|
||||
File diff suppressed because it is too large.
Load diff
+29
-54
@@ -166,62 +166,10 @@ public class DeclinationStore {
|
||||
Calendar cal = new GregorianCalendar(year, month, /* dayOfMonth */ 1);
|
||||
TimePoint timePoint = new MillisecondsTimePoint(cal.getTimeInMillis());
|
||||
for (double lat = 0; lat < 90; lat += grid) {
|
||||
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
|
||||
for (double lng = 0; lng < 180; lng += grid) {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
Declination existingDeclinationRecord;
|
||||
synchronized (storedDeclinations) {
|
||||
existingDeclinationRecord = storedDeclinations.get(point);
|
||||
}
|
||||
if (existingDeclinationRecord == null
|
||||
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
|
||||
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
|
||||
.getTimePoint()) > 0.1) {
|
||||
// less than ~6 nautical miles and/or ~.6 months off
|
||||
fetchAndAppendDeclination(timePoint, point, importer, out);
|
||||
}
|
||||
}
|
||||
for (double lng = -grid; lng > -180; lng -= grid) {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
Declination existingDeclinationRecord;
|
||||
synchronized (storedDeclinations) {
|
||||
existingDeclinationRecord = storedDeclinations.get(point);
|
||||
}
|
||||
if (existingDeclinationRecord == null
|
||||
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord
|
||||
.getPosition().getDistance(point), timePoint, existingDeclinationRecord
|
||||
.getTimePoint()) > 0.1) {
|
||||
// less than ~6 nautical miles and/or ~.6 months off
|
||||
fetchAndAppendDeclination(timePoint, point, importer, out);
|
||||
}
|
||||
}
|
||||
fetchAndAppendDeclinationForLatitude(grid, importer, year, storedDeclinations, out, month, timePoint, lat);
|
||||
}
|
||||
for (double lat = -grid; lat > -90; lat -= grid) {
|
||||
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
|
||||
for (double lng = 0; lng < 180; lng += grid) {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
Declination existingDeclinationRecord;
|
||||
synchronized (storedDeclinations) {
|
||||
existingDeclinationRecord = storedDeclinations.get(point);
|
||||
}
|
||||
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
|
||||
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
|
||||
// less than ~6 nautical miles and/or ~.6 months off
|
||||
fetchAndAppendDeclination(timePoint, point, importer, out);
|
||||
}
|
||||
}
|
||||
for (double lng = -grid; lng > -180; lng -= grid) {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
Declination existingDeclinationRecord;
|
||||
synchronized (storedDeclinations) {
|
||||
existingDeclinationRecord = storedDeclinations.get(point);
|
||||
}
|
||||
if (DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
|
||||
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
|
||||
// less than ~6 nautical miles and/or ~.6 months off
|
||||
fetchAndAppendDeclination(timePoint, point, importer, out);
|
||||
}
|
||||
}
|
||||
fetchAndAppendDeclinationForLatitude(grid, importer, year, storedDeclinations, out, month, timePoint, lat);
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
@@ -229,6 +177,33 @@ public class DeclinationStore {
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchAndAppendDeclinationForLatitude(double grid, NOAAImporter importer, int year,
|
||||
QuadTree<Declination> storedDeclinations, Writer out, int month, TimePoint timePoint, double lat)
|
||||
throws IOException {
|
||||
System.out.println("Date: " + year + "/" + (month + 1) + ", Latitude: " + lat);
|
||||
for (double lng = 0; lng < 180; lng += grid) {
|
||||
fetchAndAppendDeclination(importer, storedDeclinations, out, timePoint, lat, lng);
|
||||
}
|
||||
for (double lng = -grid; lng > -180; lng -= grid) {
|
||||
fetchAndAppendDeclination(importer, storedDeclinations, out, timePoint, lat, lng);
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchAndAppendDeclination(NOAAImporter importer, QuadTree<Declination> storedDeclinations, Writer out,
|
||||
TimePoint timePoint, double lat, double lng) throws IOException {
|
||||
Position point = new DegreePosition(lat, lng);
|
||||
final Declination existingDeclinationRecord;
|
||||
synchronized (storedDeclinations) {
|
||||
existingDeclinationRecord = storedDeclinations.get(point);
|
||||
}
|
||||
if (existingDeclinationRecord == null
|
||||
|| DeclinationServiceImpl.timeAndSpaceDistance(existingDeclinationRecord.getPosition().getDistance(point),
|
||||
timePoint, existingDeclinationRecord.getTimePoint()) > 0.1) {
|
||||
// less than ~6 nautical miles and/or ~.6 months off
|
||||
fetchAndAppendDeclination(timePoint, point, importer, out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the importer, writing to resources/declination-year.txt (where "year" represents the year for which the
|
||||
* values are stored in the file) the declinations downloaded online for the years <code>args[0]</code> to
|
||||
|
||||
+58
-35
@@ -44,16 +44,15 @@ public class AbstractPosition implements Position {
|
||||
@Override
|
||||
public double getCentralAngleRad(Position p) {
|
||||
// Sinnott:
|
||||
double dLat = p.getLatRad()-getLatRad();
|
||||
double dLon = p.getLngRad()-getLngRad();
|
||||
double a = Math.sin(dLat/2.) * Math.sin(dLat/2.) +
|
||||
Math.cos(getLatRad()) * Math.cos(p.getLatRad()) *
|
||||
Math.sin(dLon/2.) * Math.sin(dLon/2.);
|
||||
return 2. * Math.atan2(Math.sqrt(a), Math.sqrt(1.-a));
|
||||
double dLat = p.getLatRad() - getLatRad();
|
||||
double dLon = p.getLngRad() - getLngRad();
|
||||
double a = Math.sin(dLat / 2.) * Math.sin(dLat / 2.) + Math.cos(getLatRad()) * Math.cos(p.getLatRad())
|
||||
* Math.sin(dLon / 2.) * Math.sin(dLon / 2.);
|
||||
return 2. * Math.atan2(Math.sqrt(a), Math.sqrt(1. - a));
|
||||
// Spherical Law of Cosines; simpler formula, but doesn't work well for very small distances
|
||||
// return Math.acos(Math.sin(getLatRad()) * Math.sin(p.getLatRad())
|
||||
// + Math.cos(getLatRad()) * Math.cos(p.getLatRad())
|
||||
// * Math.cos(p.getLngRad() - getLngRad()));
|
||||
// return Math.acos(Math.sin(getLatRad()) * Math.sin(p.getLatRad())
|
||||
// + Math.cos(getLatRad()) * Math.cos(p.getLatRad())
|
||||
// * Math.cos(p.getLngRad() - getLngRad()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,44 +78,46 @@ public class AbstractPosition implements Position {
|
||||
@Override
|
||||
public Position translateRhumb(Bearing bearing, Distance distance) {
|
||||
/*
|
||||
* This algorithm is limited to distances such that dlon < pi/2, i.e those that extend around less than one quarter of the circumference
|
||||
* of the earth in longitude. A completely general, but more complicated algorithm is necessary if greater distances are allowed.
|
||||
* This algorithm is limited to distances such that dlon < pi/2, i.e those that extend around less than one
|
||||
* quarter of the circumference of the earth in longitude. A completely general, but more complicated algorithm
|
||||
* is necessary if greater distances are allowed.
|
||||
*/
|
||||
double distanceRad = distance.getKilometers() / 6371.0; // r = 6371 means earth's radius in km
|
||||
double distanceRad = distance.getKilometers() / 6371.0; // r = 6371 means earth's radius in km
|
||||
double lat1 = getLatRad();
|
||||
double lon1 = getLngRad();
|
||||
double bearingRad = bearing.getRadians();
|
||||
|
||||
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distanceRad) +
|
||||
Math.cos(lat1) * Math.sin(distanceRad) * Math.cos(bearingRad));
|
||||
double lon2 = lon1 + Math.atan2(Math.sin(bearingRad)*Math.sin(distanceRad)*Math.cos(lat1),
|
||||
Math.cos(distanceRad)-Math.sin(lat1)*Math.sin(lat2));
|
||||
lon2 = (lon2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalize to -180..+180
|
||||
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(distanceRad) + Math.cos(lat1) * Math.sin(distanceRad)
|
||||
* Math.cos(bearingRad));
|
||||
double lon2 = lon1
|
||||
+ Math.atan2(Math.sin(bearingRad) * Math.sin(distanceRad) * Math.cos(lat1), Math.cos(distanceRad)
|
||||
- Math.sin(lat1) * Math.sin(lat2));
|
||||
lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalize to -180..+180
|
||||
|
||||
return new DegreePosition(lat2 / Math.PI * 180., lon2 / Math.PI * 180.);
|
||||
return new DegreePosition(lat2 / Math.PI * 180., lon2 / Math.PI * 180.);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position translateGreatCircle(Bearing bearing, Distance distance) {
|
||||
double lat = Math.asin(Math.sin(getLatRad())
|
||||
* Math.cos(distance.getCentralAngleRad())
|
||||
+ Math.cos(getLatRad())
|
||||
* Math.sin(distance.getCentralAngleRad())
|
||||
* Math.cos(bearing.getRadians()));
|
||||
double lat = Math.asin(Math.sin(getLatRad()) * Math.cos(distance.getCentralAngleRad()) + Math.cos(getLatRad())
|
||||
* Math.sin(distance.getCentralAngleRad()) * Math.cos(bearing.getRadians()));
|
||||
double lng = getLngRad()
|
||||
+ Math.atan2(
|
||||
Math.sin(bearing.getRadians())
|
||||
* Math.sin(distance.getCentralAngleRad())
|
||||
Math.sin(bearing.getRadians()) * Math.sin(distance.getCentralAngleRad())
|
||||
* Math.cos(getLatRad()),
|
||||
Math.cos(distance.getCentralAngleRad())
|
||||
- Math.sin(getLatRad()) * Math.sin(lat));
|
||||
Math.cos(distance.getCentralAngleRad()) - Math.sin(getLatRad()) * Math.sin(lat));
|
||||
return new RadianPosition(lat, lng);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance crossTrackError(Position pos2, Bearing bearing) {
|
||||
return new CentralAngleDistance(Math.abs(Math.asin(Math.sin(pos2.getCentralAngleRad(this))
|
||||
* Math.sin(pos2.getBearingGreatCircle(this).getRadians() - bearing.getRadians()))));
|
||||
public Distance absoluteCrossTrackError(Position p, Bearing bearing) {
|
||||
return new CentralAngleDistance(Math.abs(crossTrackError(p, bearing).getCentralAngleRad()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance crossTrackError(Position p, Bearing bearing) {
|
||||
return new CentralAngleDistance(Math.asin(Math.sin(p.getCentralAngleRad(this))
|
||||
* Math.sin(p.getBearingGreatCircle(this).getRadians() - bearing.getRadians())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,19 +126,41 @@ public class AbstractPosition implements Position {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance alongTrackDistance(Position pos2, Bearing bearing) {
|
||||
double direction = Math.signum(Math.cos(pos2.getBearingGreatCircle(this).getRadians() - bearing.getRadians()));
|
||||
public Distance alongTrackDistance(Position from, Bearing bearing) {
|
||||
double direction = Math.signum(Math.cos(from.getBearingGreatCircle(this).getRadians() - bearing.getRadians()));
|
||||
// Test if denominator gets ridiculously small; if so, the cross-track error is about 90� central angle.
|
||||
// This means that the cross-track error is maximized, and that there is no way to determine how far along
|
||||
// the great circle described by pos2 and bearing we should travel. This is an exception which will
|
||||
// surface as a division-by-zero exception or a NaN result
|
||||
return new CentralAngleDistance(direction * Math.acos(Math.cos(pos2.getCentralAngleRad(this))
|
||||
/ Math.cos(crossTrackError(pos2, bearing).getCentralAngleRad())));
|
||||
return new CentralAngleDistance(direction
|
||||
* Math.acos(Math.cos(from.getCentralAngleRad(this))
|
||||
/ Math.cos(crossTrackError(from, bearing).getCentralAngleRad())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Distance getDistanceToLine(Position left, Position right) {
|
||||
final Distance distance;
|
||||
double toLeft = Math.abs(left.getBearingGreatCircle(this).getDifferenceTo(left.getBearingGreatCircle(right))
|
||||
.getDegrees());
|
||||
double toRight = Math.abs(right.getBearingGreatCircle(this).getDifferenceTo(right.getBearingGreatCircle(left))
|
||||
.getDegrees());
|
||||
if (toLeft > 90) {
|
||||
distance = this.getDistance(left);
|
||||
} else {
|
||||
if (toRight > 90) {
|
||||
distance = this.getDistance(right);
|
||||
} else {
|
||||
distance = this.absoluteCrossTrackError(left, left.getBearingGreatCircle(right));
|
||||
}
|
||||
}
|
||||
// Right now this always returns a positiv value. It might be possible to change it so that the sign indicates
|
||||
// which side of the Line the Position is on.
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "("+getLatDeg()+","+getLngDeg()+")";
|
||||
return "(" + getLatDeg() + "," + getLngDeg() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@ public enum DetailType implements Serializable {
|
||||
MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS(1, DESCENDING),
|
||||
TOTAL_DISTANCE_TRAVELED(0, ASCENDING), TOTAL_AVERAGE_SPEED_OVER_GROUND(2, DESCENDING),
|
||||
TOTAL_TIME_SAILED_IN_SECONDS(1, ASCENDING), RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING),
|
||||
RACE_TOTAL_POINTS(2, ASCENDING), REGATTA_TOTAL_POINTS(2, ASCENDING),
|
||||
RACE_TIME_SINCE_LAST_POSITION_FIX_IN_SECONDS(0 , ASCENDING),
|
||||
RACE_TRACKING_QUALITY(0 , ASCENDING), RACE_DISTANCE_TO_START_FIVE_SECONDS_BEFORE_RACE_START(1, ASCENDING),
|
||||
RACE_SPEED_OVER_GROUND_FIVE_SECONDS_BEFORE_START(2, DESCENDING),
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
public enum LeaderboardType {
|
||||
RegattaLeaderboard(false, true), RegattaMetaLeaderboard(true, true),
|
||||
FlexibleLeaderboard(false, false), FlexibleMetaLeaderboard(true, false);
|
||||
|
||||
boolean isRegattaLeaderboard;
|
||||
boolean isMetaLeaderboard;
|
||||
|
||||
LeaderboardType(boolean isMetaLeaderboard, boolean isRegattaLeaderboard) {
|
||||
this.isMetaLeaderboard = isMetaLeaderboard;
|
||||
this.isRegattaLeaderboard = isRegattaLeaderboard;
|
||||
}
|
||||
|
||||
public boolean isMetaLeaderboard() {
|
||||
return isMetaLeaderboard;
|
||||
}
|
||||
|
||||
public boolean isRegattaLeaderboard() {
|
||||
return isRegattaLeaderboard;
|
||||
}
|
||||
|
||||
public boolean isFlexibleLeaderboard() {
|
||||
return !isRegattaLeaderboard;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String result = "";
|
||||
if(isMetaLeaderboard) {
|
||||
result += "Meta, ";
|
||||
}
|
||||
result += isRegattaLeaderboard ? "Regatta" : "Flexible";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public interface Position extends Serializable {
|
||||
double getLatRad();
|
||||
|
||||
@@ -47,6 +48,12 @@ public interface Position extends Serializable {
|
||||
/**
|
||||
* @return an unsigned distance
|
||||
*/
|
||||
Distance absoluteCrossTrackError(Position p, Bearing bearing);
|
||||
|
||||
/**
|
||||
* @return a signed distance; positive distances mean that this position is to the right (starboard) of the
|
||||
* line one gets when traveling from <code>p</code> with <code>bearing</code>
|
||||
*/
|
||||
Distance crossTrackError(Position p, Bearing bearing);
|
||||
|
||||
/**
|
||||
@@ -56,5 +63,11 @@ public interface Position extends Serializable {
|
||||
* if the angle between this position and the great circle is 90 degrees then there is
|
||||
* no solution, and a <code>NaN</code> or exception will result.
|
||||
*/
|
||||
|
||||
Distance alongTrackDistance(Position from, Bearing bearing);
|
||||
|
||||
/**
|
||||
* Computes the distance from this position to the line between <code>left<code> and <code>right<code>.
|
||||
*/
|
||||
Distance getDistanceToLine(Position left, Position right);
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
public enum TrackedRaceStatusEnum { PREPARED(0), LOADING(1), TRACKING(2), FINISHED(3);
|
||||
public enum TrackedRaceStatusEnum { PREPARED(0), LOADING(1), TRACKING(2), FINISHED(3), ERROR(4);
|
||||
|
||||
private final int order;
|
||||
|
||||
|
||||
+3
-3
@@ -9,6 +9,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.LeaderboardType;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
@@ -28,8 +29,7 @@ public abstract class AbstractLeaderboardDTO implements Serializable {
|
||||
public String defaultCourseAreaIdAsString;
|
||||
public String defaultCourseAreaName;
|
||||
public ScoringSchemeType scoringScheme;
|
||||
public boolean isMetaLeaderboard;
|
||||
public boolean isRegattaLeaderboard;
|
||||
public LeaderboardType type;
|
||||
|
||||
private Long delayToLiveInMillisForLatestRace;
|
||||
|
||||
@@ -328,7 +328,7 @@ public abstract class AbstractLeaderboardDTO implements Serializable {
|
||||
return false;
|
||||
if (hasCarriedPoints != other.hasCarriedPoints)
|
||||
return false;
|
||||
if (isMetaLeaderboard != other.isMetaLeaderboard)
|
||||
if (type != other.type)
|
||||
return false;
|
||||
if (scoringScheme != other.scoringScheme)
|
||||
return false;
|
||||
|
||||
+33
-6
@@ -2,6 +2,15 @@ package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the {@link #getIdAsString() ID}, the {@link #getSailID() sail number}, the
|
||||
* {@link #getBoatClass() boat class} (whose equality and hash code, in turn, depends on its name) and the
|
||||
* {@link #getThreeLetterIocCountryCode() IOC country code}. Note that the three latter properties are subject
|
||||
* to change for a competitor while the ID remains unchanged.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serializable {
|
||||
private static final long serialVersionUID = -4997852354821083154L;
|
||||
private String twoLetterIsoCountryCode;
|
||||
@@ -27,8 +36,11 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * getIdAsString().hashCode();
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode());
|
||||
result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode());
|
||||
result = prime * result + ((sailID == null) ? 0 : sailID.hashCode());
|
||||
result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -36,15 +48,30 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
if (!super.equals(obj))
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
CompetitorDTOImpl other = (CompetitorDTOImpl) obj;
|
||||
if (getIdAsString() == null) {
|
||||
if (other.getIdAsString() != null)
|
||||
if (boatClass == null) {
|
||||
if (other.boatClass != null)
|
||||
return false;
|
||||
} else if (!getIdAsString().equals(other.getIdAsString()))
|
||||
} else if (!boatClass.equals(other.boatClass))
|
||||
return false;
|
||||
if (idAsString == null) {
|
||||
if (other.idAsString != null)
|
||||
return false;
|
||||
} else if (!idAsString.equals(other.idAsString))
|
||||
return false;
|
||||
if (sailID == null) {
|
||||
if (other.sailID != null)
|
||||
return false;
|
||||
} else if (!sailID.equals(other.sailID))
|
||||
return false;
|
||||
if (threeLetterIocCountryCode == null) {
|
||||
if (other.threeLetterIocCountryCode != null)
|
||||
return false;
|
||||
} else if (!threeLetterIocCountryCode.equals(other.threeLetterIocCountryCode))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -508,7 +508,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
|
||||
competitorIndexesInPreviousCompetitorsList = new int[competitors.size()];
|
||||
// for this stripping run, remembers the mapping of real CompetitorDTO objects to the compact form that only holds an int as reference to the
|
||||
// previous version's competitors list; those will be used to replace the real CompetitorDTO objects where possible and will be replaced the other
|
||||
// way in apply(...).
|
||||
// way in applyThisToPreviousVersionByUpdatingThis(...).
|
||||
Map<CompetitorDTO, CompetitorDTO> compactCompetitorMap = new HashMap<CompetitorDTO, CompetitorDTO>();
|
||||
int i=0;
|
||||
for (CompetitorDTO competitor : competitors) {
|
||||
|
||||
+28
@@ -1,5 +1,11 @@
|
||||
package com.sap.sailing.domain.common.dto;
|
||||
|
||||
/**
|
||||
* Equality and hash code are based on the index pointing into a previous leaderboard's competitors list.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class PreviousCompetitorDTOImpl implements CompetitorDTO {
|
||||
private static final long serialVersionUID = 8820028699103040805L;
|
||||
private int indexInPreviousCompetitorList;
|
||||
@@ -15,6 +21,28 @@ public class PreviousCompetitorDTOImpl implements CompetitorDTO {
|
||||
return indexInPreviousCompetitorList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + indexInPreviousCompetitorList;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
PreviousCompetitorDTOImpl other = (PreviousCompetitorDTOImpl) obj;
|
||||
if (indexInPreviousCompetitorList != other.indexInPreviousCompetitorList)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTwoLetterIsoCountryCode() {
|
||||
throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+
|
||||
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
package com.sap.sailing.domain.common.impl;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class CountingOutputStream extends FilterOutputStream {
|
||||
private static final Logger logger = Logger.getLogger(CountingOutputStream.class.getName());
|
||||
|
||||
private long count;
|
||||
private final long logEveryHowManyBytes;
|
||||
private long lastMultiple;
|
||||
private final Level level;
|
||||
private final String name;
|
||||
|
||||
public CountingOutputStream(OutputStream out, long logEveryHowManyBytes, Level logLevel, String name) {
|
||||
super(out);
|
||||
this.level = logLevel;
|
||||
this.name = name;
|
||||
this.logEveryHowManyBytes = logEveryHowManyBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
super.write(b);
|
||||
count(1);
|
||||
}
|
||||
|
||||
private void count(int bytesWritten) {
|
||||
count += bytesWritten;
|
||||
if (count >= (lastMultiple+1)*logEveryHowManyBytes) {
|
||||
lastMultiple++;
|
||||
log();
|
||||
}
|
||||
}
|
||||
|
||||
private void log() {
|
||||
logger.log(level, "wrote "+count+" bytes to "+name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
super.write(b);
|
||||
count(b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
super.write(b, off, len);
|
||||
count(len);
|
||||
}
|
||||
}
|
||||
@@ -246,4 +246,22 @@ public class Util {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> int compareToWithNull(Comparable<T> o1, T o2) {
|
||||
final int result;
|
||||
if (o1 == null) {
|
||||
if (o2 == null) {
|
||||
result = 0;
|
||||
} else {
|
||||
result = -1;
|
||||
}
|
||||
} else {
|
||||
if (o2 == null) {
|
||||
result = 1;
|
||||
} else {
|
||||
result = o1.compareTo(o2);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.domain.igtimiadapter.persistence</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>
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
@@ -0,0 +1,9 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Persistence
|
||||
Bundle-SymbolicName: com.sap.sailing.domain.igtimiadapter.persistence
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Require-Bundle: com.sun.jersey;bundle-version="1.17.0",
|
||||
org.objectweb.asm;bundle-version="3.3.1"
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>root</artifactId>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.sap.sailing.domain.igtimiadapter.persistence</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence;
|
||||
|
||||
public interface DomainObjectFactory {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence;
|
||||
|
||||
public interface MongoObjectFactory {
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence.impl;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.DomainObjectFactory;
|
||||
|
||||
public class DomainObjectFactoryimpl implements DomainObjectFactory {
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.persistence.impl;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.persistence.MongoObjectFactory;
|
||||
|
||||
public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.domain.igtimiadapter</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>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
pluginProject.extensions=false
|
||||
resolve.requirebundle=false
|
||||
@@ -0,0 +1,14 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Igtimiadapter
|
||||
Bundle-SymbolicName: com.sap.sailing.domain.igtimiadapter
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
|
||||
Require-Bundle: org.json.simple;bundle-version="1.1.0",
|
||||
com.sun.jersey;bundle-version="1.17.0",
|
||||
org.objectweb.asm;bundle-version="3.3.1"
|
||||
Import-Package: javax.ws.rs;version="1.1.1",
|
||||
javax.ws.rs.core;version="1.1.1",
|
||||
javax.ws.rs.ext;version="1.1.1"
|
||||
Web-ContextPath: /igtimi
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Igtimi Oauth Callback REST API</servlet-name>
|
||||
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>javax.ws.rs.Application</param-name>
|
||||
<param-value>com.sap.sailing.domain.igtimiadapter.oauth.RestApiApplication</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>Igtimi Oauth Callback REST API</servlet-name>
|
||||
<url-pattern>/oauth/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
</web-app>
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>root</artifactId>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.sap.sailing.domain.igtimiadapter</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
package com.sap.sailing.domain.igtimiadapter;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
|
||||
/**
|
||||
* Represents what the Igtimi API calls a "client." In particular, a client has an ID and a secret. The Igtimi
|
||||
* connector of which this interface is a part acts as a client. A client needs to be authorized by a user to
|
||||
* be allowed to access the user's data via the Igtimi web services API. Authorization works by directing the
|
||||
* user to a URL using his/her user agent (usually a browser) which is constructed by the
|
||||
* {@link IgtimiConnectorFactory} and encodes a callback URL that leads to the {@link Callback} servlet.
|
||||
* The servlet records the access token that can be used for Igtimi web service API calls that require
|
||||
* access to the authenticated user's data.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public interface Client {
|
||||
String getId();
|
||||
|
||||
String getSecret();
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.igtimiadapter;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.impl.IgtimiConnectorFactoryImpl;
|
||||
|
||||
public interface IgtimiConnectorFactory {
|
||||
static IgtimiConnectorFactory INSTANCE = new IgtimiConnectorFactoryImpl();
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.impl;
|
||||
|
||||
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectorFactory;
|
||||
|
||||
public class IgtimiConnectorFactoryImpl implements IgtimiConnectorFactory {
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.oauth;
|
||||
|
||||
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;
|
||||
|
||||
@Path("/v1/authorizationcallback")
|
||||
public class Callback {
|
||||
@GET
|
||||
@Produces("application/json;charset=UTF-8")
|
||||
@Path("/")
|
||||
public Response getEvent(@QueryParam("access_token") String accessToken) {
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.sap.sailing.domain.igtimiadapter.oauth;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
public class RestApiApplication extends Application {
|
||||
public RestApiApplication() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { Callback.class }));
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,12 @@ Require-Bundle: com.sap.sailing.mongodb,
|
||||
com.sap.sailing.domain,
|
||||
com.mongodb.driver;bundle-version="2.6.2",
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.shared.android
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.server.gateway.serialization;bundle-version="1.0.0"
|
||||
Export-Package: com.sap.sailing.domain.persistence,
|
||||
com.sap.sailing.domain.persistence.impl;x-friends:="com.sap.sailing.mongodb.test,com.sap.sailing.domain.swisstimingadapter.test,com.sap.sailing.domain.persistence.test",
|
||||
com.sap.sailing.domain.persistence.media
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: org.osgi.framework;version="1.6.0"
|
||||
Import-Package: org.json.simple,
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.6.0"
|
||||
+11
@@ -1,8 +1,11 @@
|
||||
package com.sap.sailing.domain.persistence;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
@@ -86,4 +89,12 @@ public interface DomainObjectFactory {
|
||||
Map<String, Regatta> loadRaceIDToRegattaAssociations(RegattaRegistry regattaRegistry);
|
||||
|
||||
RaceLog loadRaceLog(RaceLogIdentifier identifier);
|
||||
|
||||
/**
|
||||
* Loads all competitors, and resolves them via the domain factory.
|
||||
* @return
|
||||
*/
|
||||
Collection<Competitor> loadAllCompetitors();
|
||||
|
||||
DomainFactory getBaseDomainFactory();
|
||||
}
|
||||
+16
@@ -2,7 +2,9 @@ package com.sap.sailing.domain.persistence;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBObject;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Event;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
@@ -86,4 +88,18 @@ public interface MongoObjectFactory {
|
||||
|
||||
void removeRegattaForRaceID(String raceIDAsString, Regatta regatta);
|
||||
|
||||
/**
|
||||
* Stores a competitor, including the team and boat. This should not be done for competitors for which
|
||||
* the master data is supplied by other systems, such as TracTrac, but rather for smartphone tracking,
|
||||
* where this data is otherwise not recoverable.
|
||||
* @param competitor the competitor to store/update in the database
|
||||
*/
|
||||
void storeCompetitor(Competitor competitor);
|
||||
|
||||
void removeAllCompetitors();
|
||||
|
||||
void removeCompetitor(Competitor competitor);
|
||||
|
||||
DB getDatabase();
|
||||
|
||||
}
|
||||
+5
-4
@@ -1,13 +1,14 @@
|
||||
package com.sap.sailing.domain.persistence;
|
||||
|
||||
import com.sap.sailing.domain.persistence.impl.MongoFactoryImpl;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.persistence.impl.PersistenceFactoryImpl;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
public interface MongoFactory {
|
||||
MongoFactory INSTANCE = new MongoFactoryImpl();
|
||||
public interface PersistenceFactory {
|
||||
PersistenceFactory INSTANCE = new PersistenceFactoryImpl();
|
||||
|
||||
DomainObjectFactory getDefaultDomainObjectFactory();
|
||||
DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDBService);
|
||||
DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDBService, DomainFactory baseDomainFactory);
|
||||
MongoObjectFactory getDefaultMongoObjectFactory();
|
||||
MongoObjectFactory getMongoObjectFactory(MongoDBService mongoDBService);
|
||||
}
|
||||
+6
-1
@@ -51,5 +51,10 @@ public enum CollectionNames {
|
||||
/**
|
||||
* Stores the race log events for a tracked race.
|
||||
*/
|
||||
RACE_LOGS;
|
||||
RACE_LOGS,
|
||||
|
||||
/**
|
||||
* Stores competitors for smartphone tracking.
|
||||
*/
|
||||
COMPETITORS,
|
||||
}
|
||||
+41
-9
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.persistence.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -12,6 +13,8 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
@@ -20,6 +23,7 @@ import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
@@ -110,20 +114,31 @@ import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.CompetitorJsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.deserialization.impl.Helpers;
|
||||
|
||||
public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName());
|
||||
private final CompetitorJsonDeserializer competitorDeserializer;
|
||||
|
||||
private final DB database;
|
||||
|
||||
private RaceLogEventRestoreFactory raceLogEventFactory;
|
||||
private final DomainFactory baseDomainFactory;
|
||||
|
||||
public DomainObjectFactoryImpl(DB db) {
|
||||
public DomainObjectFactoryImpl(DB db, DomainFactory baseDomainFactory) {
|
||||
super();
|
||||
this.baseDomainFactory = baseDomainFactory;
|
||||
this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory);
|
||||
this.database = db;
|
||||
this.raceLogEventFactory = RaceLogEventRestoreFactory.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainFactory getBaseDomainFactory() {
|
||||
return baseDomainFactory;
|
||||
}
|
||||
|
||||
public Wind loadWind(DBObject object) {
|
||||
return new WindImpl(loadPosition(object), loadTimePoint(object), loadSpeedWithBearing(object));
|
||||
}
|
||||
@@ -366,7 +381,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
CourseArea courseArea = null;
|
||||
if (courseAreaId != null) {
|
||||
UUID courseAreaUuid = UUID.fromString(courseAreaId.toString());
|
||||
courseArea = DomainFactory.INSTANCE.getExistingCourseAreaById(courseAreaUuid);
|
||||
courseArea = baseDomainFactory.getExistingCourseAreaById(courseAreaUuid);
|
||||
}
|
||||
|
||||
result = new FlexibleLeaderboardImpl(raceLogStore, (String) dbLeaderboard.get(FieldNames.LEADERBOARD_NAME
|
||||
@@ -418,7 +433,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
|
||||
private ScoringScheme loadScoringScheme(DBObject dbLeaderboard) {
|
||||
ScoringSchemeType scoringSchemeType = getScoringSchemeType(dbLeaderboard);
|
||||
final ScoringScheme scoringScheme = DomainFactory.INSTANCE.createScoringScheme(scoringSchemeType);
|
||||
final ScoringScheme scoringScheme = baseDomainFactory.createScoringScheme(scoringSchemeType);
|
||||
return scoringScheme;
|
||||
}
|
||||
|
||||
@@ -825,7 +840,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
private CourseArea loadCourseArea(DBObject courseAreaDBObject) {
|
||||
String name = (String) courseAreaDBObject.get(FieldNames.COURSE_AREA_NAME.name());
|
||||
Serializable id = (Serializable) courseAreaDBObject.get(FieldNames.COURSE_AREA_ID.name());
|
||||
return DomainFactory.INSTANCE.getOrCreateCourseArea(id, name);
|
||||
return baseDomainFactory.getOrCreateCourseArea(id, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -860,7 +875,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
BoatClass boatClass = null;
|
||||
if (boatClassName != null) {
|
||||
boolean typicallyStartsUpwind = (Boolean) dbRegatta.get(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name());
|
||||
boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass(boatClassName, typicallyStartsUpwind);
|
||||
boatClass = baseDomainFactory.getOrCreateBoatClass(boatClassName, typicallyStartsUpwind);
|
||||
}
|
||||
BasicDBList dbSeries = (BasicDBList) dbRegatta.get(FieldNames.REGATTA_SERIES.name());
|
||||
Iterable<Series> series = loadSeries(dbSeries, trackedRegattaRegistry);
|
||||
@@ -872,7 +887,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
CourseArea courseArea = null;
|
||||
if (courseAreaId != null) {
|
||||
UUID courseAreaUuid = UUID.fromString(courseAreaId.toString());
|
||||
courseArea = DomainFactory.INSTANCE.getExistingCourseAreaById(courseAreaUuid);
|
||||
courseArea = baseDomainFactory.getExistingCourseAreaById(courseAreaUuid);
|
||||
}
|
||||
|
||||
result = new RegattaImpl(raceLogStore, baseName, boatClass, series, /* persistent */ true, loadScoringScheme(dbRegatta), id, courseArea);
|
||||
@@ -1166,7 +1181,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
List<Competitor> competitors = new ArrayList<Competitor>();
|
||||
for (Object object : dbCompetitorList) {
|
||||
Serializable competitorId = (Serializable) object;
|
||||
Competitor competitor = DomainFactory.INSTANCE.getExistingCompetitorById(competitorId);
|
||||
Competitor competitor = baseDomainFactory.getExistingCompetitorById(competitorId);
|
||||
competitors.add(competitor);
|
||||
}
|
||||
return competitors;
|
||||
@@ -1240,7 +1255,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
Mark leftMark = loadMark((DBObject) dbObject.get(FieldNames.GATE_LEFT.name()));
|
||||
Mark rightMark = loadMark((DBObject) dbObject.get(FieldNames.GATE_RIGHT.name()));
|
||||
|
||||
Gate gate = DomainFactory.INSTANCE.createGate(gateId, leftMark, rightMark, gateName);
|
||||
Gate gate = baseDomainFactory.createGate(gateId, leftMark, rightMark, gateName);
|
||||
return gate;
|
||||
}
|
||||
|
||||
@@ -1252,7 +1267,24 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
String markShape = (String) dbObject.get(FieldNames.MARK_SHAPE.name());
|
||||
MarkType markType = MarkType.valueOf((String) dbObject.get(FieldNames.MARK_TYPE.name()));
|
||||
|
||||
Mark mark = DomainFactory.INSTANCE.getOrCreateMark(markId, markName, markType, markColor, markShape, markPattern);
|
||||
Mark mark = baseDomainFactory.getOrCreateMark(markId, markName, markType, markColor, markShape, markPattern);
|
||||
return mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Competitor> loadAllCompetitors() {
|
||||
ArrayList<Competitor> result = new ArrayList<Competitor>();
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
try {
|
||||
for (DBObject o : collection.find()) {
|
||||
JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(JSON.serialize(o)));
|
||||
Competitor c = competitorDeserializer.deserialize(json);
|
||||
result.add(c);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors.");
|
||||
logger.log(Level.SEVERE, "loadCompetitors", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+32
@@ -6,12 +6,14 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DB;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.CourseArea;
|
||||
@@ -66,16 +68,23 @@ import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer;
|
||||
|
||||
public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName());
|
||||
private final DB database;
|
||||
private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create();
|
||||
|
||||
public MongoObjectFactoryImpl(DB database) {
|
||||
super();
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DB getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
public DBObject storeWind(Wind wind) {
|
||||
DBObject result = new BasicDBObject();
|
||||
storePositioned(wind, result);
|
||||
@@ -858,4 +867,27 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
return passing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeCompetitor(Competitor competitor) {
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
JSONObject json = competitorSerializer.serialize(competitor);
|
||||
BasicDBObject query = new BasicDBObject(CompetitorJsonSerializer.FIELD_ID, competitor.getId());
|
||||
DBObject entry = (DBObject) JSON.parse(json.toString());
|
||||
collection.update(query, entry, /* upsrt */true, /* multi */false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllCompetitors() {
|
||||
logger.info("Removing all persistent competitor info");
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
collection.drop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCompetitor(Competitor competitor) {
|
||||
logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId());
|
||||
DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name());
|
||||
BasicDBObject query = new BasicDBObject(CompetitorJsonSerializer.FIELD_ID, competitor.getId().toString());
|
||||
collection.remove(query);
|
||||
}
|
||||
}
|
||||
+12
-6
@@ -1,28 +1,34 @@
|
||||
package com.sap.sailing.domain.persistence.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoFactory;
|
||||
import com.sap.sailing.domain.persistence.MongoObjectFactory;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
public class MongoFactoryImpl implements MongoFactory {
|
||||
public class PersistenceFactoryImpl implements PersistenceFactory {
|
||||
private final DomainObjectFactory defaultDomainObjectFactory;
|
||||
private final MongoObjectFactory defaultMongoObjectFactory;
|
||||
|
||||
public MongoFactoryImpl() {
|
||||
public PersistenceFactoryImpl() {
|
||||
super();
|
||||
this.defaultDomainObjectFactory = new DomainObjectFactoryImpl(MongoDBService.INSTANCE.getDB());
|
||||
this.defaultDomainObjectFactory = new DomainObjectFactoryImpl(MongoDBService.INSTANCE.getDB(), DomainFactory.INSTANCE);
|
||||
this.defaultMongoObjectFactory = new MongoObjectFactoryImpl(MongoDBService.INSTANCE.getDB());
|
||||
}
|
||||
|
||||
/**
|
||||
* A default domain object factory for test purposes only. In a server environment, ensure NOT to use this and use
|
||||
* {@link #getDomainObjectFactory(MongoDBService, DomainFactory)} instead, using the base domain factory that
|
||||
* is provided by <code>RacingEventService.getBaseDomainFactory</code>.
|
||||
*/
|
||||
@Override
|
||||
public DomainObjectFactory getDefaultDomainObjectFactory() {
|
||||
return defaultDomainObjectFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDBService) {
|
||||
return new DomainObjectFactoryImpl(mongoDBService.getDB());
|
||||
public DomainObjectFactory getDomainObjectFactory(MongoDBService mongoDBService, DomainFactory baseDomainFactory) {
|
||||
return new DomainObjectFactoryImpl(mongoDBService.getDB(), baseDomainFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
-1
@@ -7,5 +7,4 @@ public interface Competitor extends Named, WithID, IsManagedBySharedDomainFactor
|
||||
Team getTeam();
|
||||
|
||||
Boat getBoat();
|
||||
|
||||
}
|
||||
-2
@@ -43,7 +43,5 @@ public interface CourseBase extends Named {
|
||||
|
||||
void removeWaypoint(int zeroBasedPosition);
|
||||
|
||||
Iterable<Leg> getLegsAdjacentTo(Mark mark);
|
||||
|
||||
Leg getFirstLeg();
|
||||
}
|
||||
+24
-2
@@ -3,6 +3,9 @@ package com.sap.sailing.domain.base;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.sap.sailing.domain.base.impl.DynamicBoat;
|
||||
import com.sap.sailing.domain.base.impl.DynamicCompetitor;
|
||||
import com.sap.sailing.domain.base.impl.DynamicTeam;
|
||||
import com.sap.sailing.domain.common.MarkType;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
|
||||
@@ -72,11 +75,30 @@ public interface SharedDomainFactory {
|
||||
*/
|
||||
BoatClass getOrCreateBoatClass(String name);
|
||||
|
||||
/**
|
||||
* If a valid competitor is returned and the caller has information available that could be used to update the competitor,
|
||||
* the caller must check the result of {@link #isCompetitorToUpdateDuringGetOrCreate(Competitor)}, and if <code>true</code>,
|
||||
* must call {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} to cause an update of the
|
||||
* competitor's values.
|
||||
*/
|
||||
Competitor getExistingCompetitorById(Serializable competitorId);
|
||||
|
||||
Competitor createCompetitor(Serializable id, String name, Team team, Boat boat);
|
||||
/**
|
||||
* Checks if the <code>competitor</code> shall be updated from the default provided by, e.g., a tracking infrastructure.
|
||||
* Callers of {@link #getExistingCompetitorById(Serializable)} or {@link #getExistingCompetitorByIdAsString(String)}
|
||||
* must call this method in case they retrieve a valid competitor by ID and have data available that can be used to update
|
||||
* the competitor.
|
||||
*/
|
||||
boolean isCompetitorToUpdateDuringGetOrCreate(Competitor result);
|
||||
|
||||
Competitor getOrCreateCompetitor(Serializable competitorId, String name, Team team, Boat boat);
|
||||
Competitor getOrCreateCompetitor(Serializable competitorId, String name, DynamicTeam team, DynamicBoat boat);
|
||||
|
||||
/**
|
||||
* Same as {@link #getOrCreateCompetitor(Serializable, String, DynamicTeam, DynamicBoat)} but returns the writable
|
||||
* specialization of the {@link Competitor} interface. Use with care because the setters offered by the <code>Dynamic...</code>
|
||||
* subinterfaces don't automatically replicate or store the changes.
|
||||
*/
|
||||
DynamicCompetitor getOrCreateDynamicCompetitor(UUID competitorId, String name, DynamicTeam team, DynamicBoat boat);
|
||||
|
||||
CourseArea getOrCreateCourseArea(Serializable courseAreaId, String name);
|
||||
|
||||
|
||||
+7
-3
@@ -1,13 +1,12 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
|
||||
public class BoatImpl extends NamedImpl implements Boat {
|
||||
public class BoatImpl extends NamedImpl implements DynamicBoat {
|
||||
private static final long serialVersionUID = 3489730487528955788L;
|
||||
private final BoatClass boatClass;
|
||||
private final String sailID;
|
||||
private String sailID;
|
||||
|
||||
public BoatImpl(String name, BoatClass boatClass, String sailID) {
|
||||
super(name);
|
||||
@@ -24,4 +23,9 @@ public class BoatImpl extends NamedImpl implements Boat {
|
||||
public String getSailID() {
|
||||
return sailID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSailId(String newSailId) {
|
||||
this.sailID = newSailId;
|
||||
}
|
||||
}
|
||||
+23
-10
@@ -2,37 +2,50 @@ package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.SharedDomainFactory;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
|
||||
public class CompetitorImpl extends NamedImpl implements Competitor {
|
||||
public class CompetitorImpl implements DynamicCompetitor {
|
||||
private static final long serialVersionUID = 294603681016643157L;
|
||||
private final Team team;
|
||||
private final Boat boat;
|
||||
private final DynamicTeam team;
|
||||
private final DynamicBoat boat;
|
||||
private final Serializable id;
|
||||
private String name;
|
||||
|
||||
public CompetitorImpl(Serializable id, String name, Team team, Boat boat) {
|
||||
super(name);
|
||||
public CompetitorImpl(Serializable id, String name, DynamicTeam team, DynamicBoat boat) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.team = team;
|
||||
this.boat = boat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName) {
|
||||
this.name = newName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team getTeam() {
|
||||
public DynamicTeam getTeam() {
|
||||
return team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boat getBoat() {
|
||||
public DynamicBoat getBoat() {
|
||||
return boat;
|
||||
}
|
||||
|
||||
|
||||
-7
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.CourseBase;
|
||||
import com.sap.sailing.domain.base.Leg;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
|
||||
@@ -71,12 +70,6 @@ public class CourseDataImpl extends NamedImpl implements CourseBase {
|
||||
this.waypoints.remove(zeroBasedPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Leg> getLegsAdjacentTo(Mark mark) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Leg getFirstLeg() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
|
||||
public interface DynamicBoat extends Boat {
|
||||
void setSailId(String newSailId);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.Renamable;
|
||||
|
||||
public interface DynamicCompetitor extends Competitor, Renamable {
|
||||
DynamicBoat getBoat();
|
||||
DynamicTeam getTeam();
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Person;
|
||||
|
||||
public interface DynamicPerson extends Person {
|
||||
void setNationality(Nationality newNationality);
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
|
||||
public interface DynamicTeam extends Team {
|
||||
void setNationality(Nationality newNationality);
|
||||
}
|
||||
+29
@@ -48,4 +48,33 @@ public class NationalityImpl implements Nationality {
|
||||
return domainFactory.getOrCreateNationality(getThreeLetterIOCAcronym());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((threeLetterIOCAcronym == null) ? 0 : threeLetterIOCAcronym.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
NationalityImpl other = (NationalityImpl) obj;
|
||||
if (threeLetterIOCAcronym == null) {
|
||||
if (other.threeLetterIOCAcronym != null)
|
||||
return false;
|
||||
} else if (!threeLetterIOCAcronym.equals(other.threeLetterIOCAcronym))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getThreeLetterIOCAcronym();
|
||||
}
|
||||
}
|
||||
+7
-3
@@ -4,12 +4,11 @@ import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Person;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
|
||||
public class PersonImpl extends NamedImpl implements Person {
|
||||
public class PersonImpl extends NamedImpl implements DynamicPerson {
|
||||
private static final long serialVersionUID = -2104903799224233508L;
|
||||
private final Nationality nationality;
|
||||
private Nationality nationality;
|
||||
private final Date dateOfBirth;
|
||||
private final String description;
|
||||
|
||||
@@ -30,6 +29,11 @@ public class PersonImpl extends NamedImpl implements Person {
|
||||
return nationality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNationality(Nationality newNationality) {
|
||||
this.nationality = newNationality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getDateOfBirth() {
|
||||
return dateOfBirth;
|
||||
|
||||
+10
-4
@@ -2,15 +2,14 @@ package com.sap.sailing.domain.base.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Person;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
|
||||
public class TeamImpl extends NamedImpl implements Team {
|
||||
public class TeamImpl extends NamedImpl implements DynamicTeam {
|
||||
private static final long serialVersionUID = 4646922280429210183L;
|
||||
private final Iterable<? extends Person> sailors;
|
||||
private final Iterable<? extends DynamicPerson> sailors;
|
||||
private final Person coach;
|
||||
|
||||
public TeamImpl(String name, Iterable<? extends Person> sailors, Person coach) {
|
||||
public TeamImpl(String name, Iterable<? extends DynamicPerson> sailors, Person coach) {
|
||||
super(name);
|
||||
this.sailors = sailors;
|
||||
this.coach = coach;
|
||||
@@ -39,4 +38,11 @@ public class TeamImpl extends NamedImpl implements Team {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNationality(Nationality newNationality) {
|
||||
for (Person sailor : getSailors()) {
|
||||
((DynamicPerson) sailor).setNationality(newNationality);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-2
@@ -43,8 +43,6 @@ public interface SwissTimingAdapterPersistence extends RaceSpecificMessageLoader
|
||||
|
||||
void storeSwissTimingArchiveConfiguration(SwissTimingArchiveConfiguration createSwissTimingArchiveConfiguration);
|
||||
|
||||
void storeSailMasterMessage(SailMasterMessage message);
|
||||
|
||||
void storeRace(Race race);
|
||||
|
||||
void dropAllRaceMasterData();
|
||||
|
||||
+12
-8
@@ -30,13 +30,15 @@ import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.persistence.PersistenceFactory;
|
||||
import com.sap.sailing.domain.persistence.media.MediaDB;
|
||||
import com.sap.sailing.domain.racelog.impl.EmptyRaceLogStore;
|
||||
import com.sap.sailing.domain.swisstimingadapter.MessageType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterTransceiver;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.DomainFactoryImpl;
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.SwissTimingAdapterFactoryImpl;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.StoreAndForward;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.SwissTimingAdapterPersistence;
|
||||
import com.sap.sailing.domain.swisstimingadapter.persistence.impl.CollectionNames;
|
||||
@@ -78,6 +80,8 @@ public class EndToEndListeningStoreAndFowardTest {
|
||||
private EmptyWindStore emptyWindStore;
|
||||
private EmptyRaceLogStore emptyRaceLogStore;
|
||||
private RacingEventService racingEventService;
|
||||
private SwissTimingAdapter swissTimingAdapter;
|
||||
|
||||
|
||||
private List<RacesHandle> raceHandles;
|
||||
|
||||
@@ -116,9 +120,9 @@ public class EndToEndListeningStoreAndFowardTest {
|
||||
/* upsert */true, /* multi */false);
|
||||
// important: construct a new domain factory each time to make sure the competitor cache starts out empty
|
||||
final com.sap.sailing.domain.base.impl.DomainFactoryImpl baseDomainFactory = new com.sap.sailing.domain.base.impl.DomainFactoryImpl();
|
||||
racingEventService = new RacingEventServiceImpl(mongoDBService, SwissTimingFactory.INSTANCE,
|
||||
new DomainFactoryImpl(baseDomainFactory),
|
||||
new com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl(baseDomainFactory), MediaDB.TEST_STUB);
|
||||
swissTimingAdapter = new SwissTimingAdapterFactoryImpl().getOrCreateSwissTimingAdapter(baseDomainFactory, swissTimingAdapterPersistence);
|
||||
racingEventService = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(
|
||||
mongoDBService, baseDomainFactory), PersistenceFactory.INSTANCE.getMongoObjectFactory(mongoDBService), MediaDB.TEST_STUB);
|
||||
raceHandles = new ArrayList<RacesHandle>();
|
||||
}
|
||||
|
||||
@@ -365,12 +369,12 @@ public class EndToEndListeningStoreAndFowardTest {
|
||||
|
||||
private void setUpUsingScript(String[] racesToTrack, String... scriptNames) throws Exception {
|
||||
for (String raceToTrack : racesToTrack) {
|
||||
RacesHandle raceHandle = racingEventService.addSwissTimingRace(/* regattaToAddTo */ null /* use a default regatta */,
|
||||
raceToTrack, "localhost", /* canSendRequests */
|
||||
CLIENT_PORT, false, emptyWindStore, emptyRaceLogStore, -1);
|
||||
RacesHandle raceHandle = swissTimingAdapter.addSwissTimingRace(racingEventService,
|
||||
/* regattaToAddTo */ null /* use a default regatta */, raceToTrack, /* canSendRequests */
|
||||
"localhost", CLIENT_PORT, false, emptyWindStore, emptyRaceLogStore, -1);
|
||||
raceHandles.add(raceHandle);
|
||||
if (connector == null) {
|
||||
connector = racingEventService.getSwissTimingFactory().getOrCreateSailMasterConnector("localhost",
|
||||
connector = swissTimingAdapter.getSwissTimingFactory().getOrCreateSailMasterConnector("localhost",
|
||||
CLIENT_PORT, swissTimingAdapterPersistence, /* canSendRequests */false);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -198,26 +198,25 @@ public class OverlappingStoredAndReceivedMessagesTest implements RaceSpecificMes
|
||||
|
||||
@Override
|
||||
public Iterable<Race> getRaces() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Race getRace(String raceID) {
|
||||
// TODO Auto-generated method stub
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSailMasterMessage(SailMasterMessage message) {
|
||||
}
|
||||
}
|
||||
@@ -12,3 +12,5 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sailing.domain.common
|
||||
Export-Package: com.sap.sailing.domain.swisstimingadapter,
|
||||
com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test"
|
||||
Import-Package: org.osgi.framework;version="1.7.0"
|
||||
Bundle-Activator: com.sap.sailing.domain.swisstimingadapter.impl.Activator
|
||||
+5
@@ -21,6 +21,11 @@ import com.sap.sailing.domain.tracking.WindStore;
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
public interface DomainFactory {
|
||||
/**
|
||||
* A default domain factory for test purposes only. In a server environment, ensure NOT to use this. Use what can be
|
||||
* reached from <code>RacingEventService.getBaseDomainFactory()</code> instead which should be the single instance
|
||||
* used by all other services linked to the <code>RacingEventService</code>.
|
||||
*/
|
||||
final static DomainFactory INSTANCE = new DomainFactoryImpl(com.sap.sailing.domain.base.DomainFactory.INSTANCE);
|
||||
|
||||
com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory();
|
||||
|
||||
+2
@@ -18,6 +18,8 @@ public interface RaceSpecificMessageLoader {
|
||||
*/
|
||||
List<SailMasterMessage> loadRaceMessages(String raceID);
|
||||
|
||||
void storeSailMasterMessage(SailMasterMessage message);
|
||||
|
||||
Iterable<Race> getRaces();
|
||||
|
||||
Race getRace(String raceID);
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.tracking.RacesHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackerManager;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
|
||||
public interface SwissTimingAdapter {
|
||||
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname, int port,
|
||||
boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException, ParseException;
|
||||
|
||||
/**
|
||||
* @param trackerManager TODO
|
||||
* @param regattaToAddTo
|
||||
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
|
||||
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
|
||||
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
|
||||
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
|
||||
* to add the races to. Otherwise, a default regatta as described above will be created and used.
|
||||
*/
|
||||
RacesHandle addSwissTimingRace(TrackerManager trackerManager, RegattaIdentifier regattaToAddTo, String raceID, String hostname,
|
||||
int port, boolean canSendRequests, WindStore windStore, RaceLogStore logStore, long timeoutInMilliseconds)
|
||||
throws InterruptedException, UnknownHostException, IOException, ParseException, Exception;
|
||||
|
||||
SwissTimingFactory getSwissTimingFactory();
|
||||
|
||||
void storeSwissTimingDummyRace(String racMessage, String stlMesssage, String ccgMessage) throws IllegalArgumentException;
|
||||
|
||||
com.sap.sailing.domain.swisstimingadapter.DomainFactory getSwissTimingDomainFactory();
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
|
||||
public interface SwissTimingAdapterFactory {
|
||||
SwissTimingAdapter getOrCreateSwissTimingAdapter(DomainFactory baseDomainFactory, RaceSpecificMessageLoader persistence);
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
private static final Logger logger = Logger.getLogger(Activator.class.getName());
|
||||
|
||||
private final SwissTimingAdapterFactory swissTimingAdapterFactory;
|
||||
|
||||
public Activator() {
|
||||
// there is exactly one instance of the racingEventService in the whole server
|
||||
swissTimingAdapterFactory = new SwissTimingAdapterFactoryImpl();
|
||||
}
|
||||
|
||||
public void start(BundleContext context) throws Exception {
|
||||
// register the racing service in the OSGi registry
|
||||
context.registerService(SwissTimingAdapterFactory.class.getName(), swissTimingAdapterFactory, null);
|
||||
logger.log(Level.INFO, "Started "+context.getBundle().getSymbolicName());
|
||||
}
|
||||
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -9,18 +9,18 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Person;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseImpl;
|
||||
import com.sap.sailing.domain.base.impl.DynamicBoat;
|
||||
import com.sap.sailing.domain.base.impl.DynamicPerson;
|
||||
import com.sap.sailing.domain.base.impl.DynamicTeam;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
@@ -41,9 +41,9 @@ import com.sap.sailing.domain.swisstimingadapter.Mark;
|
||||
import com.sap.sailing.domain.swisstimingadapter.MessageType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceSpecificMessageLoader;
|
||||
import com.sap.sailing.domain.swisstimingadapter.StartList;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceType;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceType.OlympicRaceCode;
|
||||
import com.sap.sailing.domain.swisstimingadapter.StartList;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
@@ -127,14 +127,14 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
@Override
|
||||
public Competitor getOrCreateCompetitor(com.sap.sailing.domain.swisstimingadapter.Competitor competitor, RaceType raceType) {
|
||||
Competitor result = getCompetitorByBoatIDAndRaceType(competitor.getBoatID(), raceType);
|
||||
if (result == null) {
|
||||
Boat boat = new BoatImpl(competitor.getName(), raceType.getBoatClass(), competitor.getBoatID());
|
||||
List<Person> teamMembers = new ArrayList<Person>();
|
||||
if (result == null || baseDomainFactory.isCompetitorToUpdateDuringGetOrCreate(result)) {
|
||||
DynamicBoat boat = new BoatImpl(competitor.getName(), raceType.getBoatClass(), competitor.getBoatID());
|
||||
List<DynamicPerson> teamMembers = new ArrayList<DynamicPerson>();
|
||||
for (String teamMemberName : competitor.getName().split("[-+&]")) {
|
||||
teamMembers.add(new PersonImpl(teamMemberName.trim(), getOrCreateNationality(competitor.getThreeLetterIOCCode()),
|
||||
/* dateOfBirth */ null, teamMemberName.trim()));
|
||||
}
|
||||
Team team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null);
|
||||
DynamicTeam team = new TeamImpl(competitor.getName(), teamMembers, /* coach */ null);
|
||||
result = baseDomainFactory.getOrCreateCompetitor(getCompetitorID(competitor.getBoatID(), raceType),
|
||||
competitor.getName(), team, boat);
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceSpecificMessageLoader;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory;
|
||||
|
||||
public class SwissTimingAdapterFactoryImpl implements SwissTimingAdapterFactory {
|
||||
private final Map<DomainFactory, SwissTimingAdapter> adaptersForBaseFactories;
|
||||
|
||||
public SwissTimingAdapterFactoryImpl() {
|
||||
adaptersForBaseFactories = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized SwissTimingAdapter getOrCreateSwissTimingAdapter(DomainFactory baseDomainFactory, RaceSpecificMessageLoader persistence) {
|
||||
SwissTimingAdapter result = adaptersForBaseFactories.get(baseDomainFactory);
|
||||
if (result == null) {
|
||||
result = new SwissTimingAdapterImpl(baseDomainFactory, persistence);
|
||||
adaptersForBaseFactories.put(baseDomainFactory, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.swisstimingadapter.Race;
|
||||
import com.sap.sailing.domain.swisstimingadapter.RaceSpecificMessageLoader;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SailMasterMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory;
|
||||
import com.sap.sailing.domain.tracking.RacesHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackerManager;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
|
||||
public class SwissTimingAdapterImpl implements SwissTimingAdapter {
|
||||
private final SwissTimingFactory swissTimingFactory;
|
||||
|
||||
private final com.sap.sailing.domain.swisstimingadapter.DomainFactory swissTimingDomainFactory;
|
||||
|
||||
private final RaceSpecificMessageLoader raceSpecificMessageLoader;
|
||||
|
||||
public SwissTimingAdapterImpl(DomainFactory baseDomainFactory, RaceSpecificMessageLoader raceSpecificMessageLoader) {
|
||||
swissTimingFactory = SwissTimingFactory.INSTANCE;
|
||||
swissTimingDomainFactory = new DomainFactoryImpl(baseDomainFactory);
|
||||
this.raceSpecificMessageLoader = raceSpecificMessageLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sap.sailing.domain.swisstimingadapter.DomainFactory getSwissTimingDomainFactory() {
|
||||
return swissTimingDomainFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwissTimingFactory getSwissTimingFactory() {
|
||||
return swissTimingFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname,
|
||||
int port, boolean canSendRequests) throws InterruptedException, UnknownHostException, IOException,
|
||||
ParseException {
|
||||
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> result = new ArrayList<com.sap.sailing.domain.swisstimingadapter.RaceRecord>();
|
||||
SailMasterConnector swissTimingConnector = swissTimingFactory.getOrCreateSailMasterConnector(hostname, port,
|
||||
raceSpecificMessageLoader, canSendRequests);
|
||||
for (Race race : swissTimingConnector.getRaces()) {
|
||||
String raceID = race.getRaceID();
|
||||
TimePoint startTime = swissTimingConnector.getStartTime(raceID);
|
||||
boolean hasCourse = swissTimingConnector.hasCourse(raceID);
|
||||
boolean hasStartlist = swissTimingConnector.hasStartlist(raceID);
|
||||
result.add(new com.sap.sailing.domain.swisstimingadapter.RaceRecord(raceID,
|
||||
race.getDescription(), startTime == null ? null : startTime.asDate(),
|
||||
hasCourse, hasStartlist));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RacesHandle addSwissTimingRace(TrackerManager trackerManager, RegattaIdentifier regattaToAddTo, String raceID, String hostname,
|
||||
int port, boolean canSendRequests, WindStore windStore, RaceLogStore logStore, long timeoutInMilliseconds)
|
||||
throws Exception {
|
||||
return trackerManager.addRace(regattaToAddTo, swissTimingDomainFactory.createTrackingConnectivityParameters(hostname, port,
|
||||
raceID, canSendRequests, TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS, swissTimingFactory,
|
||||
swissTimingDomainFactory, logStore, windStore, raceSpecificMessageLoader), windStore,
|
||||
timeoutInMilliseconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSwissTimingDummyRace(String racMessage, String stlMessage, String ccgMessage) {
|
||||
SailMasterMessage racSMMessage = swissTimingFactory.createMessage(racMessage, null);
|
||||
SailMasterMessage stlSMMessage = swissTimingFactory.createMessage(stlMessage, null);
|
||||
SailMasterMessage ccgSMMessage = swissTimingFactory.createMessage(ccgMessage, null);
|
||||
if (raceSpecificMessageLoader.getRace(stlSMMessage.getRaceID()) != null) {
|
||||
throw new IllegalArgumentException("Race with raceID \"" + stlSMMessage.getRaceID() + "\" already exists.");
|
||||
} else {
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(racSMMessage);
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(stlSMMessage);
|
||||
raceSpecificMessageLoader.storeSailMasterMessage(ccgSMMessage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+5
-4
@@ -17,6 +17,7 @@ import java.util.Map;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayRace;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingRaceConfig;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayServiceImpl;
|
||||
@@ -29,13 +30,13 @@ public class SwissTimingRaceConfigurationTest {
|
||||
@Test
|
||||
public void testLoadConfigurations() throws IOException, ParseException, org.json.simple.parser.ParseException {
|
||||
InputStream inputStream = getClass().getResourceAsStream(JSON_URL);
|
||||
List<SwissTimingReplayRace> races = new SwissTimingReplayServiceImpl().parseJSONObject(inputStream , JSON_URL);
|
||||
List<SwissTimingReplayRace> races = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).parseJSONObject(inputStream , JSON_URL);
|
||||
Map<String, SwissTimingRaceConfig> configsById = new HashMap<String, SwissTimingRaceConfig>();
|
||||
for (SwissTimingReplayRace race : races) {
|
||||
URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, race.getRaceId()));
|
||||
URLConnection connection = configFileURL.openConnection();
|
||||
InputStream configDataStream = connection.getInputStream();
|
||||
SwissTimingRaceConfig raceConfig = new SwissTimingReplayServiceImpl().loadRaceConfig(configDataStream);
|
||||
SwissTimingRaceConfig raceConfig = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream);
|
||||
configsById.put(race.getRaceId(), raceConfig);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +46,7 @@ public class SwissTimingRaceConfigurationTest {
|
||||
URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, "446483"));
|
||||
URLConnection connection = configFileURL.openConnection();
|
||||
InputStream configDataStream = connection.getInputStream();
|
||||
SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl().loadRaceConfig(configDataStream);
|
||||
SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream);
|
||||
assertNotNull(config_446483);
|
||||
assertEquals("GB", config_446483.country_code);
|
||||
assertNull(config_446483.event_name);
|
||||
@@ -62,7 +63,7 @@ public class SwissTimingRaceConfigurationTest {
|
||||
URL configFileURL = new URL(MessageFormat.format(SwissTimingReplayServiceImpl.RACE_CONFIG_URL_TEMPLATE, "6260"));
|
||||
URLConnection connection = configFileURL.openConnection();
|
||||
InputStream configDataStream = connection.getInputStream();
|
||||
SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl().loadRaceConfig(configDataStream);
|
||||
SwissTimingRaceConfig config_446483 = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE).loadRaceConfig(configDataStream);
|
||||
assertNotNull(config_446483);
|
||||
assertEquals("GB", config_446483.country_code);
|
||||
assertEquals("London 2012 Olympic Games", config_446483.event_name);
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class SwissTimingReplayAdapterServiceTest {
|
||||
public void testLoadRaceJson() throws Exception {
|
||||
String swissTimingUrlText = "/2012_OSG.json";
|
||||
InputStream inputStream = getClass().getResourceAsStream(swissTimingUrlText);
|
||||
final SwissTimingReplayServiceImpl swissTimingReplayService = new SwissTimingReplayServiceImpl();
|
||||
final SwissTimingReplayServiceImpl swissTimingReplayService = new SwissTimingReplayServiceImpl(DomainFactory.INSTANCE);
|
||||
List<SwissTimingReplayRace> races = swissTimingReplayService.parseJSONObject(inputStream , swissTimingUrlText);
|
||||
assertEquals(201, races.size());
|
||||
assertEquals("446483", races.get(0).getRaceId());
|
||||
|
||||
@@ -12,3 +12,5 @@ Require-Bundle: com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.swisstimingadapter,
|
||||
com.googlecode.java-diff-utils;bundle-version="1.3.0"
|
||||
Export-Package: com.sap.sailing.domain.swisstimingreplayadapter
|
||||
Import-Package: org.osgi.framework;version="1.7.0"
|
||||
Bundle-Activator: com.sap.sailing.domain.swisstimingreplayadapter.impl.Activator
|
||||
+1
-2
@@ -7,7 +7,6 @@ import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingRaceConfig;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
|
||||
@@ -41,6 +40,6 @@ public interface SwissTimingReplayService {
|
||||
* the regatta to which the race shall be added; if <code>null</code>, a default regatta will be
|
||||
* created/used
|
||||
*/
|
||||
void loadRaceData(String link, DomainFactory domainFactory, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry);
|
||||
void loadRaceData(String link, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry);
|
||||
|
||||
}
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
package com.sap.sailing.domain.swisstimingreplayadapter;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.impl.SwissTimingReplayServiceFactoryImpl;
|
||||
|
||||
public interface SwissTimingReplayServiceFactory {
|
||||
static SwissTimingReplayServiceFactory INSTANCE = new SwissTimingReplayServiceFactoryImpl();
|
||||
|
||||
SwissTimingReplayService createSwissTimingReplayService();
|
||||
SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory);
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.sap.sailing.domain.swisstimingreplayadapter.impl;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayServiceFactory;
|
||||
|
||||
public class Activator implements BundleActivator {
|
||||
private static final Logger logger = Logger.getLogger(Activator.class.getName());
|
||||
|
||||
private final SwissTimingReplayServiceFactory swissTimingReplayServiceFactory;
|
||||
|
||||
public Activator() {
|
||||
// there is exactly one instance of the racingEventService in the whole server
|
||||
swissTimingReplayServiceFactory = new SwissTimingReplayServiceFactoryImpl();
|
||||
}
|
||||
|
||||
public void start(BundleContext context) throws Exception {
|
||||
// register the racing service in the OSGi registry
|
||||
context.registerService(SwissTimingReplayServiceFactory.class.getName(), swissTimingReplayServiceFactory, null);
|
||||
logger.log(Level.INFO, "Started "+context.getBundle().getSymbolicName());
|
||||
}
|
||||
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
}
|
||||
}
|
||||
+16
-3
@@ -1,13 +1,26 @@
|
||||
package com.sap.sailing.domain.swisstimingreplayadapter.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayService;
|
||||
import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayServiceFactory;
|
||||
|
||||
public class SwissTimingReplayServiceFactoryImpl implements SwissTimingReplayServiceFactory {
|
||||
private final Map<DomainFactory, SwissTimingReplayService> servicesForDomainFactories;
|
||||
|
||||
@Override
|
||||
public SwissTimingReplayService createSwissTimingReplayService() {
|
||||
return new SwissTimingReplayServiceImpl();
|
||||
public SwissTimingReplayServiceFactoryImpl() {
|
||||
servicesForDomainFactories = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SwissTimingReplayService createSwissTimingReplayService(DomainFactory domainFactory) {
|
||||
SwissTimingReplayService result = servicesForDomainFactories.get(domainFactory);
|
||||
if (result == null) {
|
||||
result = new SwissTimingReplayServiceImpl(domainFactory);
|
||||
servicesForDomainFactories.put(domainFactory, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -33,6 +33,12 @@ public class SwissTimingReplayServiceImpl implements SwissTimingReplayService {
|
||||
private static final String SWISSTIMING_DATEFORMAT_PATTERN = "dd.MM.yyyy HH:mm";
|
||||
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("GMT");
|
||||
|
||||
private final DomainFactory domainFactory;
|
||||
|
||||
public SwissTimingReplayServiceImpl(DomainFactory domainFactory) {
|
||||
this.domainFactory = domainFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SwissTimingReplayRace> listReplayRaces(String swissTimingUrlText) {
|
||||
URL raceListUrl;
|
||||
@@ -143,7 +149,7 @@ public class SwissTimingReplayServiceImpl implements SwissTimingReplayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadRaceData(String link, DomainFactory domainFactory, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
public void loadRaceData(String link, Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
SwissTimingReplayListener listener = new SwissTimingReplayToDomainAdapter(regatta, domainFactory, trackedRegattaRegistry);
|
||||
loadRaceData(link, listener);
|
||||
}
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.domain.test"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=10.18.22.156 -ea -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -XX:+UseParallelGC -Dtractrac.tunnel=true -Dtractrac.tunnel.host=localhost -ea -Djava.util.logging.config.file=${project_loc:com.sap.sailing.server}/../target/configuration/logging_debug.properties"/>
|
||||
</launchConfiguration>
|
||||
+1
-1
@@ -16,6 +16,6 @@ public abstract class AbstractLeaderboardTest {
|
||||
/* 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",
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null));
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), /* sailID */ null));
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.MeterDistance;
|
||||
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.LineLengthAndAdvantage;
|
||||
import com.sap.sailing.domain.tracking.impl.GPSFixImpl;
|
||||
|
||||
public class LineAnalysisTest extends TrackBasedTest {
|
||||
private MillisecondsTimePoint now;
|
||||
private DynamicTrackedRace trackedRace;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
final List<Competitor> emptyCompetitorList = Collections.emptyList();
|
||||
now = MillisecondsTimePoint.now();
|
||||
trackedRace = createTestTrackedRace("Test Regatta", "Test Race", "505", emptyCompetitorList, now);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinesAnalysisWithNoAdvantage() {
|
||||
final LineLengthAndAdvantage startLine = trackedRace.getStartLine(now);
|
||||
assertEquals(0, startLine.getAdvantage().getMeters(), 0.001);
|
||||
final LineLengthAndAdvantage finishLine = trackedRace.getFinishLine(now);
|
||||
assertEquals(0, finishLine.getAdvantage().getMeters(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartLineAnalysisWithAdvantageOnStarboard() {
|
||||
Mark right = getMark("Right lee gate buoy");
|
||||
final DynamicGPSFixTrack<Mark, GPSFix> rightMarkTrack = trackedRace.getOrCreateTrack(right);
|
||||
Position rightMarkAtNow = rightMarkTrack.getFirstRawFix().getPosition();
|
||||
TimePoint aBitAfterNow = now.plus(1000);
|
||||
final MeterDistance advantage = new MeterDistance(10);
|
||||
rightMarkTrack.addGPSFix(new GPSFixImpl(rightMarkAtNow.translateGreatCircle(new DegreeBearingImpl(0), advantage), aBitAfterNow));
|
||||
final LineLengthAndAdvantage startLine = trackedRace.getStartLine(aBitAfterNow);
|
||||
assertEquals(advantage.getMeters(), startLine.getAdvantage().getMeters(), 0.1);
|
||||
assertEquals(NauticalSide.STARBOARD, startLine.getAdvantageousSideWhileApproachingLine());
|
||||
final LineLengthAndAdvantage finishLine = trackedRace.getFinishLine(aBitAfterNow);
|
||||
assertEquals(advantage.getMeters(), finishLine.getAdvantage().getMeters(), 0.1);
|
||||
assertEquals(NauticalSide.PORT, finishLine.getAdvantageousSideWhileApproachingLine());
|
||||
}
|
||||
|
||||
private Mark getMark(String name) {
|
||||
for (Mark mark : trackedRace.getMarks()) {
|
||||
if (mark.getName().equals(name)) {
|
||||
return mark;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+24
-1
@@ -14,18 +14,25 @@ import java.util.Set;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Mark;
|
||||
import com.sap.sailing.domain.base.Nationality;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
|
||||
import com.sap.sailing.domain.base.impl.DomainFactoryImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
|
||||
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
|
||||
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
|
||||
import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard;
|
||||
|
||||
public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
/**
|
||||
@@ -87,6 +94,22 @@ public class OfflineSerializationTest extends AbstractSerializationTest {
|
||||
clone.getDiscardIndexResultsStartingWithHowManyRaces()));
|
||||
}
|
||||
|
||||
// see bug 1605
|
||||
@Test
|
||||
public void testSerializingOverallLeaderboardWithFactorOnColumn() throws ClassNotFoundException, IOException {
|
||||
Leaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 5 }), new HighPoint(), new CourseAreaImpl("Alpha", "Alpha"));
|
||||
LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("LeaderboardGroup", "Test Leaderboard Group", /* displayGroupsInReverseOrder */ false, Arrays.asList(new Leaderboard[] { leaderboard }));
|
||||
final LeaderboardGroupMetaLeaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPoint(), new ThresholdBasedResultDiscardingRuleImpl(new int[0]));
|
||||
leaderboardGroup.setOverallLeaderboard(overallLeaderboard);
|
||||
final double FACTOR = 2.0;
|
||||
overallLeaderboard.getRaceColumnByName("Test Leaderboard").setFactor(FACTOR);
|
||||
|
||||
DomainFactory receiverDomainFactory = new DomainFactoryImpl();
|
||||
LeaderboardGroup clone = cloneBySerialization(leaderboardGroup, receiverDomainFactory);
|
||||
assertEquals(FACTOR, overallLeaderboard.getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
assertEquals(FACTOR, clone.getOverallLeaderboard().getRaceColumnByName("Test Leaderboard").getFactor(), 0.00000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdentityStabilityOfMarkSerialization() throws ClassNotFoundException, IOException {
|
||||
DomainFactory senderDomainFactory = new DomainFactoryImpl();
|
||||
|
||||
@@ -150,14 +150,38 @@ public class PositionTest {
|
||||
assertEquals(0.5*p1.getDistance(p2).getMeters(), alongTrackDistanceFromP1ToPNorth.getMeters(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negativeAlongTrackDistanceTest() {
|
||||
Position p1 = new DegreePosition(1, 0);
|
||||
Position p2 = new DegreePosition(1, -0.0001);
|
||||
final Bearing bearingFromP1ToP2 = p1.getBearingGreatCircle(p2);
|
||||
assertEquals(-p1.getDistance(p2).getMeters(), p1.alongTrackDistance(p2, bearingFromP1ToP2).getMeters(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroCrossTrackError() {
|
||||
Position p1 = new DegreePosition(20, 15);
|
||||
Position p2 = new DegreePosition(15, 15);
|
||||
Distance result = p1.crossTrackError(p2, new DegreeBearingImpl(0));
|
||||
Distance result = p1.absoluteCrossTrackError(p2, new DegreeBearingImpl(0));
|
||||
assertEquals(0, result.getMeters(), 0.0000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignedCrossTrackErrorToRight() {
|
||||
Position p1 = new DegreePosition(20, 16);
|
||||
Position p2 = new DegreePosition(15, 15);
|
||||
Distance result = p1.crossTrackError(p2, new DegreeBearingImpl(0));
|
||||
assertTrue(result.getMeters() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignedCrossTrackErrorToLeft() {
|
||||
Position p1 = new DegreePosition(20, 14);
|
||||
Position p2 = new DegreePosition(15, 15);
|
||||
Distance result = p1.crossTrackError(p2, new DegreeBearingImpl(0));
|
||||
assertTrue(result.getMeters() < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addBearings() {
|
||||
Bearing b1 = new DegreeBearingImpl(123);
|
||||
@@ -196,5 +220,26 @@ public class PositionTest {
|
||||
assertEquals(180., b3.getDifferenceTo(b6).getDegrees(), 0.000000001);
|
||||
assertEquals(-180., b6.getDifferenceTo(b3).getDegrees(), 0.000000001);
|
||||
}
|
||||
@Test
|
||||
public void distanceToLineTest(){
|
||||
double delta = 0.000000001;
|
||||
Position left = new DegreePosition(-1, -1);
|
||||
Position right = new DegreePosition(1, 1);
|
||||
Position p1 = new DegreePosition(0,0);
|
||||
Position p2 = new DegreePosition(1, -1);
|
||||
Position p3 = new DegreePosition(-2, 0);
|
||||
Position p4 = new DegreePosition(5, 0);
|
||||
Position p5 = new DegreePosition(2, 2);
|
||||
Position p6 = new DegreePosition(0, -2);
|
||||
assertEquals(p2.getDistanceToLine(left, right).getMeters(), p2.absoluteCrossTrackError(left, left.getBearingGreatCircle(right)).getMeters(), delta);
|
||||
assertEquals(p3.getDistanceToLine(left, right).getMeters(), p3.getDistance(left).getMeters(), delta);
|
||||
assertEquals(p4.getDistanceToLine(left, right).getMeters(), p4.getDistance(right).getMeters(), delta);
|
||||
assertEquals(p5.getDistanceToLine(left, right).getMeters(), p5.getDistance(right).getMeters(), delta);
|
||||
assertEquals(p1.getDistanceToLine(p3, p4).getMeters(), 0, delta);
|
||||
assertEquals(p4.getDistanceToLine(p1, p3).getMeters(), p4.getDistance(p1).getMeters(), delta);
|
||||
assertEquals(p6.getDistanceToLine(p3, p4).getMeters(), p6.getDistance(p1).getMeters(), delta);
|
||||
assertEquals(p6.getDistanceToLine(p1, p4).getMeters(), p6.getDistance(p1).getMeters(), delta);
|
||||
assertEquals(right.getDistanceToLine(p6, p1).getMeters(), right.getDistance(p1).getMeters(), delta);
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -17,11 +17,11 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.Person;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
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.DynamicPerson;
|
||||
import com.sap.sailing.domain.base.impl.DynamicTeam;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
@@ -114,8 +114,8 @@ public abstract class StoredTrackBasedTest extends TrackBasedTest {
|
||||
Map<Competitor, DynamicGPSFixTrack<Competitor, GPSFixMoving>> tracks = new HashMap<Competitor, DynamicGPSFixTrack<Competitor,GPSFixMoving>>();
|
||||
final String KIELER_WOCHE = "Kieler Woche";
|
||||
for (String competitorName : getCompetitorNamesOfStoredTracks(KIELER_WOCHE)) {
|
||||
Person p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null);
|
||||
Team t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null);
|
||||
DynamicPerson p = new PersonImpl(competitorName, /* nationality */ null, /* dateOfBirth */ null, /* description */ null);
|
||||
DynamicTeam t = new TeamImpl(competitorName, Collections.singleton(p), /* coach */ null);
|
||||
Competitor c = new CompetitorImpl(competitorName, competitorName, t, new BoatImpl(competitorName,
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */ true), null));
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = readTrack(c, KIELER_WOCHE);
|
||||
|
||||
@@ -305,6 +305,69 @@ public class TrackTest {
|
||||
assertEquals(0, average.getBearing().getDegrees(), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixValidEvenIfFixProvidedSpeedIsOutrageous() {
|
||||
DynamicGPSFixTrack<Object, GPSFixMoving> track = new DynamicGPSFixMovingTrackImpl<Object>(null, /* millisecondsOverWhichToAverage */ 5000l);
|
||||
TimePoint t1 = new MillisecondsTimePoint(1000);
|
||||
TimePoint t2 = new MillisecondsTimePoint(2000);
|
||||
TimePoint t3 = new MillisecondsTimePoint(3000);
|
||||
GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed
|
||||
GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
track.addGPSFix(f1);
|
||||
track.addGPSFix(f2);
|
||||
track.addGPSFix(f3);
|
||||
assertEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint())); // expect the fix to still be valid, but only its provided speed shall be ignored
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixInvalidEvenIfPositionInferredSpeedIsOutrageous() {
|
||||
DynamicGPSFixTrack<Object, GPSFixMoving> track = new DynamicGPSFixMovingTrackImpl<Object>(null, /* millisecondsOverWhichToAverage */ 5000l);
|
||||
TimePoint t1 = new MillisecondsTimePoint(1000);
|
||||
TimePoint t2 = new MillisecondsTimePoint(2000);
|
||||
TimePoint t3 = new MillisecondsTimePoint(3000);
|
||||
GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(150./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed
|
||||
GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
track.addGPSFix(f1);
|
||||
track.addGPSFix(f2);
|
||||
track.addGPSFix(f3);
|
||||
assertEquals(f3, track.getFirstFixAtOrAfter(f2.getTimePoint())); // expect the f2 fix to be invalid
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFixInvalidBecauseProvidedSpeedIsTooDifferent() {
|
||||
DynamicGPSFixTrack<Object, GPSFixMoving> track = new DynamicGPSFixMovingTrackImpl<Object>(null, /* millisecondsOverWhichToAverage */ 5000l);
|
||||
TimePoint t1 = new MillisecondsTimePoint(1000);
|
||||
TimePoint t2 = new MillisecondsTimePoint(2000);
|
||||
TimePoint t3 = new MillisecondsTimePoint(3000);
|
||||
GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed
|
||||
GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
track.addGPSFix(f1);
|
||||
track.addGPSFix(f2);
|
||||
track.addGPSFix(f3);
|
||||
// expect the f2 fix to be invalid because provided speed is too different
|
||||
assertEquals(0, f3.getPosition().getDistance(track.getFirstFixAtOrAfter(f2.getTimePoint()).getPosition()).getMeters(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoringFixProvidedSpeedIfItIsOutrageous() {
|
||||
DynamicGPSFixTrack<Object, GPSFixMoving> track = new DynamicGPSFixMovingTrackImpl<Object>(null, /* millisecondsOverWhichToAverage */ 5000l);
|
||||
TimePoint t1 = new MillisecondsTimePoint(1000);
|
||||
TimePoint t2 = new MillisecondsTimePoint(2000);
|
||||
TimePoint t3 = new MillisecondsTimePoint(3000);
|
||||
GPSFixMoving f1 = new GPSFixMovingImpl(new DegreePosition(1./3600.*1./60., 0), t1, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
GPSFixMoving f2 = new GPSFixMovingImpl(new DegreePosition(2./3600.*1./60., 0), t2, new KnotSpeedWithBearingImpl(150, new DegreeBearingImpl(0))); // outrageous speed; to be ignored by getEstimatedSpeed
|
||||
GPSFixMoving f3 = new GPSFixMovingImpl(new DegreePosition(3./3600.*1./60., 0), t3, new KnotSpeedWithBearingImpl(1, new DegreeBearingImpl(0)));
|
||||
track.addGPSFix(f1);
|
||||
track.addGPSFix(f2);
|
||||
track.addGPSFix(f3);
|
||||
assertEquals(f2, track.getFirstFixAtOrAfter(f2.getTimePoint())); // expect the fix to still be valid, but only its provided speed shall be ignored
|
||||
SpeedWithBearing average = track.getEstimatedSpeed(t2);
|
||||
assertEquals(1, average.getKnots(), 0.001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBearingAveragingAcrossZeroDegreesWithGPSFixMoving() {
|
||||
DynamicGPSFixMovingTrackImpl<Object> track = new DynamicGPSFixMovingTrackImpl<Object>(null, /* millisecondsOverWhichToAverage */ 5000);
|
||||
@@ -352,7 +415,7 @@ public class TrackTest {
|
||||
}
|
||||
|
||||
private TimePoint addMillisToTimepoint(TimePoint p, long millis) {
|
||||
return new MillisecondsTimePoint(p.asMillis() + millis);
|
||||
return p.plus(millis);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+20
@@ -38,6 +38,7 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.GPSFix;
|
||||
import com.sap.sailing.domain.tracking.GPSFixMoving;
|
||||
import com.sap.sailing.domain.tracking.LineLengthAndAdvantage;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
@@ -423,6 +424,12 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegattaAndRaceIdentifier getRaceIdentifier(RaceDefinition race) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -858,4 +865,17 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LineLengthAndAdvantage getStartLine(TimePoint at) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LineLengthAndAdvantage getFinishLine(TimePoint at) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -29,6 +29,7 @@ import com.sap.sailing.domain.tracking.CourseDesignChangedListener;
|
||||
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.LineLengthAndAdvantage;
|
||||
import com.sap.sailing.domain.tracking.Maneuver;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
@@ -563,4 +564,16 @@ public class MockedTrackedRaceWithStartTimeAndRanks implements TrackedRace {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LineLengthAndAdvantage getStartLine(TimePoint at) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LineLengthAndAdvantage getFinishLine(TimePoint at) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
-5
@@ -1,8 +1,6 @@
|
||||
package com.sap.sailing.domain.tractracadapter.persistence;
|
||||
|
||||
import com.sap.sailing.domain.tractracadapter.TracTracConfiguration;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.impl.DomainObjectFactoryImpl;
|
||||
import com.sap.sailing.mongodb.MongoDBService;
|
||||
|
||||
/**
|
||||
* Offers methods to load domain objects from a Mongo DB
|
||||
@@ -11,8 +9,5 @@ import com.sap.sailing.mongodb.MongoDBService;
|
||||
*
|
||||
*/
|
||||
public interface DomainObjectFactory {
|
||||
DomainObjectFactory INSTANCE = new DomainObjectFactoryImpl(MongoDBService.INSTANCE.getDB());
|
||||
|
||||
Iterable<TracTracConfiguration> getTracTracConfigurations();
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.sap.sailing.domain.tractracadapter.persistence;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.impl.PersistenceFactoryImpl;
|
||||
|
||||
public interface PersistenceFactory {
|
||||
PersistenceFactory INSTANCE = new PersistenceFactoryImpl();
|
||||
|
||||
DomainObjectFactory createDomainObjectFactory(DB db, DomainFactory tracTracDomainFactory);
|
||||
}
|
||||
+5
-2
@@ -18,9 +18,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
|
||||
private final DB database;
|
||||
|
||||
public DomainObjectFactoryImpl(DB db) {
|
||||
private final DomainFactory tracTracDomainFactory;
|
||||
|
||||
public DomainObjectFactoryImpl(DB db, DomainFactory tracTracDomainFactory) {
|
||||
super();
|
||||
this.database = db;
|
||||
this.tracTracDomainFactory = tracTracDomainFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,7 +53,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
String tracTracUsername = tracTracUsernameObject == null ? "" : (String) tracTracUsernameObject;
|
||||
String tracTracPassword = tracTracPasswordObject == null ? "" : (String) tracTracPasswordObject;
|
||||
|
||||
return DomainFactory.INSTANCE.createTracTracConfiguration((String) object.get(FieldNames.TT_CONFIG_NAME.name()),
|
||||
return tracTracDomainFactory.createTracTracConfiguration((String) object.get(FieldNames.TT_CONFIG_NAME.name()),
|
||||
(String) object.get(FieldNames.TT_CONFIG_JSON_URL.name()),
|
||||
(String) object.get(FieldNames.TT_CONFIG_LIVE_DATA_URI.name()),
|
||||
(String) object.get(FieldNames.TT_CONFIG_STORED_DATA_URI.name()),
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sap.sailing.domain.tractracadapter.persistence.impl;
|
||||
|
||||
import com.mongodb.DB;
|
||||
import com.sap.sailing.domain.tractracadapter.DomainFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory;
|
||||
import com.sap.sailing.domain.tractracadapter.persistence.PersistenceFactory;
|
||||
|
||||
public class PersistenceFactoryImpl implements PersistenceFactory {
|
||||
@Override
|
||||
public DomainObjectFactory createDomainObjectFactory(DB db, DomainFactory tracTracDomainFactory) {
|
||||
return new DomainObjectFactoryImpl(db, tracTracDomainFactory);
|
||||
}
|
||||
}
|
||||
@@ -14,4 +14,6 @@ Export-Package: com.sap.sailing.domain.tractracadapter,
|
||||
com.sap.sailing.domain.tractracadapter.impl;x-friends:="com.sap.sailing.domain.test,com.sap.sailing.domain.swisstimingadapter.test,com.sap.sailing.server.test"
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Import-Package: org.json.simple,
|
||||
org.json.simple.parser
|
||||
org.json.simple.parser,
|
||||
org.osgi.framework;version="1.7.0"
|
||||
Bundle-Activator: com.sap.sailing.domain.tractracadapter.impl.Activator
|
||||
+5
-7
@@ -20,7 +20,6 @@ import com.sap.sailing.domain.base.Person;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Sideline;
|
||||
import com.sap.sailing.domain.base.Team;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
@@ -52,6 +51,11 @@ import com.tractrac.clientmodule.data.Position;
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
public interface DomainFactory {
|
||||
/**
|
||||
* A default domain factory for test purposes only. In a server environment, ensure NOT to use this. Use what can be
|
||||
* reached from <code>RacingEventService.getBaseDomainFactory()</code> instead which should be the single instance
|
||||
* used by all other services linked to the <code>RacingEventService</code>.
|
||||
*/
|
||||
static DomainFactory INSTANCE = new DomainFactoryImpl(com.sap.sailing.domain.base.DomainFactory.INSTANCE);
|
||||
|
||||
com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory();
|
||||
@@ -79,12 +83,6 @@ public interface DomainFactory {
|
||||
|
||||
Person getOrCreatePerson(String name, Nationality nationality, UUID id);
|
||||
|
||||
/**
|
||||
* If a team called <code>name</code> already is known by this domain factory, it is returned. Otherwise, the team name
|
||||
* is split along "+" signs with one {@link Person} object created for each part.
|
||||
*/
|
||||
Team getOrCreateTeam(String name, Nationality nationality, UUID competitorId);
|
||||
|
||||
/**
|
||||
* Fetch a race definition previously created by a call to {@link #getOrCreateRaceDefinitionAndTrackedRace}. If no such
|
||||
* race definition was created so far, the call blocks until such a definition is provided by a call to
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
package com.sap.sailing.domain.tractracadapter;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
import com.sap.sailing.domain.tracking.RacesHandle;
|
||||
import com.sap.sailing.domain.tracking.TrackerManager;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
|
||||
public interface TracTracAdapter {
|
||||
DomainFactory getTracTracDomainFactory();
|
||||
|
||||
/**
|
||||
* If not already tracking the URL/URI/URI combination, adds a single race tracker and starts tracking the race,
|
||||
* using the race's parameter URL which delivers the single configuration text file for that race. While the result
|
||||
* of passing this URL to the TracTrac <code>KeyValue.setup</code> is a TracTrac <code>Event</code>, those events
|
||||
* only manage a single race. In our domain model, we group those races into a single instance of our
|
||||
* {@link Regatta} class.
|
||||
* <p>
|
||||
*
|
||||
* If this is the first race of an event, the {@link Regatta} is created as well. If the {@link RaceDefinition} for
|
||||
* the race already exists, it isn't created again. Also, if a {@link TracTracRaceTracker} for the given race
|
||||
* already exists, it is not added again.
|
||||
* <p>
|
||||
*
|
||||
* Note that when the race identified by <code>paramURL</code>, <code>liveURI</code> and <code>storedURI</code> is
|
||||
* already being tracked, then regardless of the <code>windStore</code> selection the existing tracker will be used
|
||||
* and its race handle will be returned. A log message will indicate a potential wind store mismatch (based on
|
||||
* {@link WindStore#equals(Object)}).
|
||||
*
|
||||
* @param trackerManager
|
||||
* the race will be added to that manager
|
||||
* @param timeoutInMilliseconds
|
||||
* if the race definition is not received for the race within this time, the race tracker for that race
|
||||
* is stopped; use -1 to wait forever
|
||||
*/
|
||||
RacesHandle addTracTracRace(TrackerManager trackerManager, URL paramURL, URI liveURI, URI storedURI,
|
||||
URI courseDesignUpdateURI, RaceLogStore raceLogStore, WindStore windStore, long timeoutInMilliseconds,
|
||||
String tracTracUsername, String tracTracPassword) throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception;
|
||||
|
||||
/**
|
||||
* Same as {@link #addTracTracRace(URL, URI, URI, WindStore, long)}, only that start and end of tracking are
|
||||
* specified which may help reducing the amount of stored data (particularly mark positions) that needs to be
|
||||
* loaded.
|
||||
*
|
||||
* @param trackerManager
|
||||
* the race will be added to that manager
|
||||
* @param regattaToAddTo
|
||||
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
|
||||
* appended in parentheses will be looked up; if not found, a default regatta with that name will be
|
||||
* created, with a single default series and a single default fleet. If a valid {@link RegattaIdentifier}
|
||||
* is specified, a regatta lookup is performed with that identifier; if the regatta is found, it is used
|
||||
* to add the races to. Otherwise, a default regatta as described above will be created and used.
|
||||
*/
|
||||
RacesHandle addTracTracRace(TrackerManager trackerManager, RegattaIdentifier regattaToAddTo, URL paramURL, URI liveURI,
|
||||
URI storedURI, URI courseDesignUpdateURI, TimePoint trackingStartTime,
|
||||
TimePoint trackingEndTime, RaceLogStore raceLogStore, WindStore windStore,
|
||||
long timeoutForReceivingRaceDefinitionInMilliseconds, boolean simulateWithStartTimeNow, String tracTracUsername, String tracTracPassword)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, Exception;
|
||||
|
||||
/**
|
||||
* Defines the regatta and for each race listed in the JSON document that is not already being tracked by this service
|
||||
* creates a {@link TracTracRaceTracker} that starts tracking the respective race. The {@link RaceDefinition}s obtained this
|
||||
* way are all grouped into the single {@link Regatta} produced for the event listed in the JSON response. Note that
|
||||
* the many race trackers will have their TracTrac <code>Event</code> each, all with the same name, meaning the same
|
||||
* event but being distinct.
|
||||
* @param trackerManager TODO
|
||||
* @param jsonURL
|
||||
* URL of a JSON response that contains an "event" object telling the event's name and ID, as well as a
|
||||
* JSON array named "races" which tells ID and replay URL for the race. From those replay URLs the
|
||||
* paramURL for the Java client can be derived.
|
||||
* @param timeoutInMilliseconds
|
||||
* if a race definition is not received for a race of this event within this time, the race tracker for
|
||||
* that race is stopped; use -1 to wait forever
|
||||
* @param raceLogStore TODO
|
||||
*/
|
||||
Regatta addRegatta(TrackerManager trackerManager, URL jsonURL, URI liveURI, URI storedURI, URI courseDesignUpdateURI, WindStore windStore,
|
||||
long timeoutInMilliseconds, String tracTracUsername, String tracTracPassword, RaceLogStore raceLogStore)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, IOException, ParseException,
|
||||
org.json.simple.parser.ParseException, Exception;
|
||||
|
||||
/**
|
||||
* For the JSON URL of an account / event, lists the paramURLs that can be used for
|
||||
* {@link #addTracTracRace(URL, URI, URI, WindStore, long)} calls to individually start tracking races of this
|
||||
* event, rather than tracking <em>all</em> races in the event which is hardly ever useful. The returned pair's
|
||||
* first component is the event name.
|
||||
*
|
||||
* @param loadClientParams
|
||||
* shall the properties from the clientparams.php file such as liveURI and storedURI already be loaded?
|
||||
* Generally, this is not necessary as the
|
||||
* {@link #addTracTracRace(TrackerManager, RegattaIdentifier, URL, URI, URI, URI, TimePoint, TimePoint, RaceLogStore, WindStore, long, boolean, String, String)}
|
||||
* and {@link #addTracTracRace(TrackerManager, URL, URI, URI, URI, RaceLogStore, WindStore, long, String, String)} will
|
||||
* fetch the JSON and clientparams.php documents to work with up-to-date data.
|
||||
*/
|
||||
Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL, boolean loadClientParams) throws IOException,
|
||||
ParseException, org.json.simple.parser.ParseException, URISyntaxException;
|
||||
|
||||
RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams) throws Exception;
|
||||
|
||||
TracTracConfiguration createTracTracConfiguration(String name, String jsonURL, String liveDataURI,
|
||||
String storedDataURI, String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword);
|
||||
|
||||
}
|
||||
Loaded 100 of 372 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user