Merge remote-tracking branch 'origin/master' into dataMining-BigBang

Conflicts:
	java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/components/AbstractLeaderboardGroupDataRetrievalWorker.java
	java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/gps_fix/GPSFixLeaderboardGroupDataRetrievalWorker.java
	java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/gps_fix/GPSFixWithContextImpl.java
	java/com.sap.sailing.datamining/src/com/sap/sailing/datamining/impl/tracked_leg_of_competitor/TrackedLegOfCompetitorLeaderboardGroupDataRetrievalWorker.java
	java/com.sap.sailing.domain.common/META-INF/MANIFEST.MF
	java/com.sap.sailing.domain.shared.android/META-INF/MANIFEST.MF
	java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java
	java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java
	java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Nationality.java
	java/com.sap.sailing.domain/META-INF/MANIFEST.MF
	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/client/DataMiningEntryPoint.java
This commit is contained in:
Lennart Hensler committed 2014-06-07 11:20:56 +02:00
commit 679ef1c3f4
1496 files changed
+231940 -14337

No files matched your search

+147
View File
@@ -0,0 +1,147 @@
#!/bin/sh
# This is a template for creating backup of data and persist them
# to a central backup server. Make sure to adapt this script to your needs.
#
# Please do not change the name of the bakup (bup save -n) because that can
# have strange effects. If you change it you absolutely need to make sure that
# only the same root directories are associated to that name. It is NOT possible
# to backup different root directories to the same backup name.
#
# Documentation: http://wiki.sapsailing.com/wiki/amazon-ec2-backup-strategy
#
# Maintainer: simon.marcel.pamies@sap.com
# If you want to just backup directories follow steps 1-4. If you want to
# backup MongoDB and/or MySQL databases then follow steps 5-8.
# 1: Select directories to backup. Each directory needs to be separated from
# others by a blank. Directories with blanks need to be surrounded by quotes.
BACKUP_DIRECTORIES="/etc /var/log/mongodb"
# 2: Prefix for backup - set that to the hostname of your server or any other
# name that describes your server. No blanks or special characters allowed.
PREFIX="database"
# 3: Directory for temporary files. If you do not want to backup MySQL or MongoBD
# then you can just leave it to /tmp.
TARGET_DIR=/tmp
# 4: Include any patterns that should match files to be ignored. The parameter
# is a regular expression. You can use multiple --exclude-rx= parameters.
BUP_IGNORES='--exclude-rx=/war/$'
# **************************************
# If you do not want any MySQL or MongoDB backup then you're done.
# If not then continue with the following steps.
# **************************************
# 5: Enable MongoDB backup by setting this variable to 1
ENABLE_MONGODB_BACKUP=0
# 6: Provide MongoDB instances to backup. Format is <port>:<database name>
MONGODB_DATABASES="10202:winddb 10201:winddb"
# No need to change the following values in most cases
MONGOEXPORT_CMD="/opt/mongodb-linux-x86_64-1.8.1/bin/mongoexport"
MONGODB_COLLECTIONS_NO_WIND="EVENTS LEADERBOARD_GROUPS LEADERBOARDS RACE_LOGS RACES_MESSAGES REGATTA_FOR_RACE_ID REGATTAS TRACTRAC_CONFIGURATIONS COMMAND_MESSAGES COMPETITORS CONFIGURATIONS LAST_MESSAGE_COUNT VIDEOS"
MONGODB_COLLECTIONS_WIND="WIND_TRACKS"
# 7: Enable MySQL backup by setting this variable to 1
ENABLE_MYSQL_BACKUP=0
# 8: Space separated list of mysql databases to backup
MYSQL_DATABASES="bugs mysql"
# 9: Provide the username and password for MySQL
MYSQLEXPORT_CMD="mysqldump -u root --password=xxxx"
# **************************************
# You're done.
# **************************************
# Configuration for external backup server - needs a ssh key
BACKUP_SERVER="backup@172.31.25.136"
# Set date for this backup - this makes it possible to restore
# files from different branches (named backups)
BACKUP_DATE=`date +%s`
# Aliases
BUP_CMD="/opt/bup/bup"
BUP_ADDITIONAL="-r $BACKUP_SERVER:/home/backup/$PREFIX"
BUP_CMD_INDEX="$BUP_CMD index $BUP_IGNORES"
BUP_CMD_SAVE="$BUP_CMD save --date=$BACKUP_DATE $BUP_ADDITIONAL"
PARAM=$@
# Make sure to install the right libraries
yum install python-devel fuse-python pyxattr pylibacl perl-Time-HiRes
# We need to set HOME in case it isn't set right - assuming root is calling
export HOME=/root
# Make sure to init local and remote repository
# It is perfectly safe to reinitialize a repository w/o overwriting data
$BUP_CMD init
ssh $BACKUP_SERVER "/opt/bup/bup init -r /home/backup/$PREFIX"
# Backup general directories
for OTHER_DIR in $BACKUP_DIRECTORIES; do
NORMALIZED_DIR_NAME=${OTHER_DIR//\//-}
echo "Backing up $OTHER_DIR"
$BUP_CMD_INDEX $OTHER_DIR
$BUP_CMD_SAVE -n dir$NORMALIZED_DIR_NAME $OTHER_DIR
# no need to remove any backup files here
done
# **************************************
# Start of database specific backup
# **************************************
if [ $ENABLE_MONGODB_BACKUP -eq 1 ]; then
# Export MongoDB instances with wind upon request (weekly parameter provided)
if [ "$PARAM" = "weekly" ]; then
for MONGO_CONFIG in $MONGODB_DATABASES; do
PARTS=(${MONGO_CONFIG//:/ })
mkdir $TARGET_DIR/mongodb-${PARTS[0]}-wind
for COLLECTION in $MONGODB_COLLECTIONS_WIND; do
echo "$MONGOEXPORT_CMD --port ${PARTS[0]} -d ${PARTS[1]} -c $COLLECTION > $TARGET_DIR/mongodb-${PARTS[0]}-wind/$COLLECTION.json"
$MONGOEXPORT_CMD --port ${PARTS[0]} -d ${PARTS[1]} -c $COLLECTION > $TARGET_DIR/mongodb-${PARTS[0]}-wind/$COLLECTION.json
done
done
fi
# Export MongoDB instances without wind
for MONGO_CONFIG in $MONGODB_DATABASES; do
PARTS=(${MONGO_CONFIG//:/ })
mkdir $TARGET_DIR/mongodb-${PARTS[0]}
for COLLECTION in $MONGODB_COLLECTIONS_NO_WIND; do
echo "$MONGOEXPORT_CMD --port ${PARTS[0]} -d ${PARTS[1]} -c $COLLECTION > $TARGET_DIR/mongodb-${PARTS[0]}/$COLLECTION.json"
$MONGOEXPORT_CMD --port ${PARTS[0]} -d ${PARTS[1]} -c $COLLECTION > $TARGET_DIR/mongodb-${PARTS[0]}/$COLLECTION.json
done
done
# Backup the whole thing now and push to external server
$BUP_CMD_INDEX $TARGET_DIR
$BUP_CMD_SAVE -n mongodb-databases $TARGET_DIR/
find $TARGET_DIR -name *.json | xargs rm -f
fi
if [ $ENABLE_MYSQL_BACKUP -eq 1 ]; then
# Export MySQL dump for selected databases
for MYSQL_DB in $MYSQL_DATABASES; do
mkdir $TARGET_DIR/mysql
echo "$MYSQLEXPORT_CMD $MYSQL_DB > $TARGET_DIR/mysql/$MYSQL_DB.sql"
$MYSQLEXPORT_CMD $MYSQL_DB > $TARGET_DIR/mysql/$MYSQL_DB.sql
done
# Backup the whole thing now and push to external server
$BUP_CMD_INDEX $TARGET_DIR
$BUP_CMD_SAVE -n mysql-databases $TARGET_DIR/mysql
rm -f $TARGET_DIR/mysql/*.sql
fi
# **************************************
# End of database specific backup
# **************************************
+9
View File
@@ -243,6 +243,15 @@ if [[ "$@" == "release" ]]; then
fi fi
mkdir $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO mkdir $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
echo "
MONGODB_NAME=myspecificevent
REPLICATION_CHANNEL=myspecificevent
SERVER_STARTUP_NOTIFY=simon.marcel.pamies@sap.com
SERVER_NAME=MYSPECIFICEVENT
USE_ENVIRONMENT=live-server
INSTALL_FROM_RELEASE=$SIMPLE_VERSION_INFO
" >> $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO/amazon-launch-config.txt
`which tar` cvzf $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO/$SIMPLE_VERSION_INFO.tar.gz * `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 $ACDIR/env.sh $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
cp $PROJECT_HOME/build/release-notes.txt $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO cp $PROJECT_HOME/build/release-notes.txt $PROJECT_HOME/dist/$SIMPLE_VERSION_INFO
+49
View File
@@ -0,0 +1,49 @@
#!/bin/bash
# Script to warn whenever the size of a commit exceeds
# a certain limit
# File size limit is meant to be configured through 'hooks.filesizelimit' setting
filesizelimit=$(git config hooks.filesizelimit)
# If we haven't configured a file size limit, use default value of about 100M
if [ -z "$filesizelimit" ]; then
filesizelimit=10000000 # 10MB
fi
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [ "$local_sha" = $z40 ]
then
# Delete
echo ""
else
if [ "$remote_sha" = $z40 ]
then
# New branch, examine all commits
range="$local_sha"
else
# Update to existing branch, examine new commits
range="$remote_sha..$local_sha"
fi
biggest_checkin_normalized=$(git diff-tree -r $range | sort -k 4 -n -r | head -1 )
file_blob_id=`echo $biggest_checkin_normalized | cut -d ' ' -f4,4`
filesize=`git cat-file -s $file_blob_id`
if [ $filesize -gt $filesizelimit ]; then
filename=`echo $biggest_checkin_normalized | cut -d ' ' -f6,6`
echo "You are attempting to push a commit containing a file ($filename) that is larger than the allowed $filesizelimit bytes ($filesize bytes)!"
echo "Please inform at least Axel Uhl and Simon Pamies about that!"
echo "(This message comes from a script located in .git/hooks/pre-push)"
exec < /dev/tty
read -p "I will comply (yes/[no]): " input
if [ "$input" = "yes" ]; then
exit 0
else
echo "Aborting push..."
fi
fi
fi
done
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env python
import socket
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
print data
client.close()
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
#
# mongodb Starts sailing services like MongoDB
#
# chkconfig: 2345 95 10
# description: Sailing contains all sailing services
# Source function library.
. /etc/init.d/functions
RETVAL=0
MONGODB_BINARY=/opt/mongodb-linux-x86_64-1.8.1/bin/mongod
MONGODB_CONF_DIR=/etc/mongodb
MONGODB_START_INSTANCES="default dev live archive racecommittee_dev"
start_mongodb() {
for conf in $MONGODB_START_INSTANCES; do
echo "Starting MongoDB server $conf"
rm -f /var/lib/mongodb/$conf/mongod.lock
su - mongodb -c "$MONGODB_BINARY --quiet --fork -f $MONGODB_CONF_DIR/mongodb-$conf.cfg"
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
done
# give database servers some time to start
sleep 2
}
stop_mongodb() {
killall mongod
sleep 2
}
# See how we were called.
case "$1" in
start)
start_mongodb
;;
stop)
stop_mongodb
;;
start-mongo)
start_mongodb
;;
start-wiki)
start_wiki
;;
status)
status mongod
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status}"
RETVAL=3
esac
exit $RETVAL
+16
View File
@@ -0,0 +1,16 @@
DEPLOY_TO=server
SERVER_NAME=LIVE
MEMORY=4096m
REPLICATION_HOST=172.31.25.253
REPLICATION_CHANNEL=sapsailinganalytics-live
TELNET_PORT=14888
SERVER_PORT=8888
MONGODB_HOST=172.31.25.253
MONGODB_PORT=10201
EXPEDITION_PORT=2010
REPLICATE_ON_START=False
REPLICATE_MASTER_SERVLET_HOST=
REPLICATE_MASTER_SERVLET_PORT=
REPLICATE_MASTER_QUEUE_HOST=
REPLICATE_MASTER_QUEUE_PORT=
ADDITIONAL_JAVA_ARGS="-XX:+UseMembar -XX:+UseParallelGC -XX:+UseParallelOldGC -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog"
+59
View File
@@ -0,0 +1,59 @@
[default]
access_key = <ACCESS_KEY_HERE>
secret_key = <SECRET_KEY_HERE>
access_token =
add_content_encoding = True
add_encoding_exts =
add_headers =
bucket_location = US
cache_file =
cloudfront_host = cloudfront.amazonaws.com
default_mime_type = binary/octet-stream
delay_updates = False
delete_after = False
delete_after_fetch = False
delete_removed = False
dry_run = False
enable_multipart = True
encoding = UTF-8
encrypt = False
follow_symlinks = False
force = False
get_continue = False
gpg_command = /usr/bin/gpg
gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_passphrase = sailaway
guess_mime_type = True
host_base = s3.amazonaws.com
host_bucket = %(bucket)s.s3.amazonaws.com
human_readable_sizes = False
ignore_failed_copy = False
invalidate_default_index_on_cf = False
invalidate_default_index_root_on_cf = True
invalidate_on_cf = False
list_md5 = False
log_target_prefix =
max_delete = -1
mime_type =
multipart_chunk_size_mb = 15
preserve_attrs = True
progress_meter = True
proxy_host =
proxy_port = 0
put_continue = False
recursive = False
recv_chunk = 4096
reduced_redundancy = False
send_chunk = 4096
server_side_encryption = False
simpledb_host = sdb.amazonaws.com
skip_existing = False
socket_timeout = 300
urlencoding_mode = normal
use_https = False
use_mime_magic = True
verbosity = WARNING
website_endpoint = http://%(bucket)s.s3-website-%(location)s.amazonaws.com/
website_error =
website_index = index.html
+3 -2
View File
@@ -12,8 +12,8 @@ Like businesses, sailors need the latest information to make strategic decisions
* [[General Project Information|wiki/general-information]] * [[General Project Information|wiki/general-information]]
* Production Environment * Production Environment
* [[Amazon EC2|wiki/amazon-ec2]] * [[Amazon EC2|wiki/amazon-ec2]]
* [[Production Environment|wiki/production-environment]] * [[EC2 Backup Strategy|wiki/amazon-ec2-backup-strategy]]
* [[TracTrac Lifecycle for Event Managers|wiki/tractrac-lifecycle]] * [[TracTrac|wiki/tractrac-lifecycle]]
* Information for Developers * Information for Developers
* [[Cook Book|wiki/cook-book]] * [[Cook Book|wiki/cook-book]]
* [[OnBoarding Information|wiki/onboarding]] * [[OnBoarding Information|wiki/onboarding]]
@@ -24,6 +24,7 @@ Like businesses, sailors need the latest information to make strategic decisions
* [[Server Replication|wiki/server-replication]] * [[Server Replication|wiki/server-replication]]
* [[Configure Races on Server|wiki/typical-development-scenarios]] * [[Configure Races on Server|wiki/typical-development-scenarios]]
* [[Development Environment|wiki/development-environment]] * [[Development Environment|wiki/development-environment]]
* [[Working with GWT UI Binder|wiki/gwt-ui-binder]]
* [[Working with GWT Locally|wiki/local-gwt]] * [[Working with GWT Locally|wiki/local-gwt]]
* [[Mobile Development|wiki/mobile-development]] * [[Mobile Development|wiki/mobile-development]]
* Information for Webdesigners * Information for Webdesigners
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: Osgi Bundle-Name: Osgi
Bundle-SymbolicName: com.google.gwt.osgi Bundle-SymbolicName: com.google.gwt.osgi
Bundle-Version: 2.6.0.qualifier Bundle-Version: 2.6.1.qualifier
Bundle-Vendor: GOOGLE Bundle-Vendor: GOOGLE
Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ClassPath: lib/gwt-user.jar, Bundle-ClassPath: lib/gwt-user.jar,
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -8,6 +8,6 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<artifactId>com.google.gwt.osgi</artifactId> <artifactId>com.google.gwt.osgi</artifactId>
<version>2.6.0-SNAPSHOT</version> <version>2.6.1-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging> <packaging>eclipse-plugin</packaging>
</project> </project>
@@ -11,4 +11,5 @@ Require-Bundle: org.junit4;bundle-version="4.8.2",
com.sap.sailing.barbados.resultimport, com.sap.sailing.barbados.resultimport,
com.sap.sailing.domain.common, com.sap.sailing.domain.common,
com.sap.sailing.domain, com.sap.sailing.domain,
com.sap.sailing.resultimport com.sap.sailing.resultimport,
com.sap.sse.common
@@ -28,11 +28,11 @@ import com.sap.sailing.domain.common.RegattaScoreCorrections;
import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsForRace; import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsForRace;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.resultimport.RegattaResults; import com.sap.sailing.resultimport.RegattaResults;
import com.sap.sailing.resultimport.ResultDocumentDescriptor; import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider; import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.impl.ResultDocumentDescriptorImpl; import com.sap.sailing.resultimport.impl.ResultDocumentDescriptorImpl;
import com.sap.sse.common.Util;
public class BarbadosResultImportTest { public class BarbadosResultImportTest {
private static final MillisecondsTimePoint NOW = MillisecondsTimePoint.now(); private static final MillisecondsTimePoint NOW = MillisecondsTimePoint.now();
@@ -74,16 +74,16 @@ public class BarbadosResultImportTest {
@Test @Test
public void testHasResultsThroughScoreCorrectionProvider() throws Exception { public void testHasResultsThroughScoreCorrectionProvider() throws Exception {
Map<String, Set<Pair<String, TimePoint>>> hasResultsFor = scp.getHasResultsForBoatClassFromDateByEventName(); Map<String, Set<Util.Pair<String, TimePoint>>> hasResultsFor = scp.getHasResultsForBoatClassFromDateByEventName();
assertNotNull(hasResultsFor); assertNotNull(hasResultsFor);
assertEquals(1, hasResultsFor.size()); assertEquals(1, hasResultsFor.size());
Entry<String, Set<Pair<String, TimePoint>>> entry = hasResultsFor.entrySet().iterator().next(); Entry<String, Set<Util.Pair<String, TimePoint>>> entry = hasResultsFor.entrySet().iterator().next();
assertEquals("505", entry.getValue().iterator().next().getA()); assertEquals("505", entry.getValue().iterator().next().getA());
} }
@Test @Test
public void testResultsThroughScoreCorrectionProvider() throws Exception { public void testResultsThroughScoreCorrectionProvider() throws Exception {
Map<String, Set<Pair<String, TimePoint>>> hasResultsFor = scp.getHasResultsForBoatClassFromDateByEventName(); Map<String, Set<Util.Pair<String, TimePoint>>> hasResultsFor = scp.getHasResultsForBoatClassFromDateByEventName();
String eventName = hasResultsFor.entrySet().iterator().next().getKey(); String eventName = hasResultsFor.entrySet().iterator().next().getKey();
String boatClassName = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getA(); String boatClassName = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getA();
TimePoint timePoint = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getB(); TimePoint timePoint = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getB();
@@ -125,7 +125,7 @@ public class BarbadosResultImportTest {
return result; return result;
} }
}); });
Map<String, Set<Pair<String, TimePoint>>> hasResultsFor = scp2.getHasResultsForBoatClassFromDateByEventName(); Map<String, Set<Util.Pair<String, TimePoint>>> hasResultsFor = scp2.getHasResultsForBoatClassFromDateByEventName();
String eventName = hasResultsFor.entrySet().iterator().next().getKey(); String eventName = hasResultsFor.entrySet().iterator().next().getKey();
String boatClassName = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getA(); String boatClassName = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getA();
TimePoint timePoint = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getB(); TimePoint timePoint = hasResultsFor.entrySet().iterator().next().getValue().iterator().next().getB();
@@ -15,7 +15,8 @@ Require-Bundle: com.sap.sailing.server,
com.sap.sailing.domain, com.sap.sailing.domain,
jcl.over.slf4j;bundle-version="1.6.4", jcl.over.slf4j;bundle-version="1.6.4",
com.sap.sailing.resultimport, com.sap.sailing.resultimport,
slf4j.api;bundle-version="1.6.4" slf4j.api;bundle-version="1.6.4",
com.sap.sse.common
Bundle-ClassPath: lib/com.springsource.org.apache.commons.beanutils-1.8.0.jar, Bundle-ClassPath: lib/com.springsource.org.apache.commons.beanutils-1.8.0.jar,
lib/com.springsource.org.apache.commons.collections-3.2.1.jar, lib/com.springsource.org.apache.commons.collections-3.2.1.jar,
lib/com.springsource.org.apache.commons.digester-1.8.0.jar, lib/com.springsource.org.apache.commons.digester-1.8.0.jar,
@@ -9,12 +9,12 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.common.RegattaScoreCorrections; import com.sap.sailing.domain.common.RegattaScoreCorrections;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.resultimport.RegattaResults; import com.sap.sailing.resultimport.RegattaResults;
import com.sap.sailing.resultimport.ResultDocumentDescriptor; import com.sap.sailing.resultimport.ResultDocumentDescriptor;
import com.sap.sailing.resultimport.ResultDocumentProvider; import com.sap.sailing.resultimport.ResultDocumentProvider;
import com.sap.sailing.resultimport.impl.AbstractDocumentBasedScoreCorrectionProvider; import com.sap.sailing.resultimport.impl.AbstractDocumentBasedScoreCorrectionProvider;
import com.sap.sailing.resultimport.impl.RegattaScoreCorrectionsImpl; import com.sap.sailing.resultimport.impl.RegattaScoreCorrectionsImpl;
import com.sap.sse.common.Util;
public class ScoreCorrectionProviderImpl extends AbstractDocumentBasedScoreCorrectionProvider { public class ScoreCorrectionProviderImpl extends AbstractDocumentBasedScoreCorrectionProvider {
private static final Logger logger = Logger.getLogger(ScoreCorrectionProviderImpl.class.getName()); private static final Logger logger = Logger.getLogger(ScoreCorrectionProviderImpl.class.getName());
@@ -34,19 +34,19 @@ public class ScoreCorrectionProviderImpl extends AbstractDocumentBasedScoreCorre
} }
@Override @Override
public Map<String, Set<Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() throws Exception { public Map<String, Set<Util.Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() throws Exception {
Map<String, Set<Pair<String, TimePoint>>> result = new HashMap<String, Set<Pair<String,TimePoint>>>(); Map<String, Set<Util.Pair<String, TimePoint>>> result = new HashMap<String, Set<Util.Pair<String,TimePoint>>>();
for (ResultDocumentDescriptor resultDocDescr : getResultDocumentProvider().getResultDocumentDescriptors()) { for (ResultDocumentDescriptor resultDocDescr : getResultDocumentProvider().getResultDocumentDescriptors()) {
try { try {
RegattaResults regattaResults = new BarbadosResultSpreadsheet(resultDocDescr.getInputStream()).getRegattaResults(); RegattaResults regattaResults = new BarbadosResultSpreadsheet(resultDocDescr.getInputStream()).getRegattaResults();
TimePoint lastModified = resultDocDescr.getLastModified(); TimePoint lastModified = resultDocDescr.getLastModified();
final String boatClassName = getBoatClassName(regattaResults); final String boatClassName = getBoatClassName(regattaResults);
Set<Pair<String, TimePoint>> set = result.get(boatClassName); Set<Util.Pair<String, TimePoint>> set = result.get(boatClassName);
if (set == null) { if (set == null) {
set = new HashSet<>(); set = new HashSet<>();
result.put(/* use document name as "event" name */ resultDocDescr.getDocumentName(), set); result.put(/* use document name as "event" name */ resultDocDescr.getDocumentName(), set);
} }
set.add(new Pair<String, TimePoint>(boatClassName, lastModified)); set.add(new Util.Pair<String, TimePoint>(boatClassName, lastModified));
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, "Couldn't parse Barbados result document "+ resultDocDescr.getDocumentName(), e); logger.log(Level.WARNING, "Couldn't parse Barbados result document "+ resultDocDescr.getDocumentName(), e);
} }
@@ -10,4 +10,5 @@ Import-Package: junit.framework;version="4.8.2",
org.junit;version="4.8.2", org.junit;version="4.8.2",
org.junit.runner;version="4.8.2" org.junit.runner;version="4.8.2"
Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5", Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5",
org.hamcrest;bundle-version="1.1.0" org.hamcrest;bundle-version="1.1.0",
com.sap.sse.common
@@ -14,6 +14,7 @@ Require-Bundle: com.sap.sailing.domain;bundle-version="1.0.0",
com.sap.sailing.domain.common, com.sap.sailing.domain.common,
com.sap.sailing.datamining.shared;bundle-version="1.0.0", com.sap.sailing.datamining.shared;bundle-version="1.0.0",
com.sap.sse.datamining;bundle-version="1.0.0", com.sap.sse.datamining;bundle-version="1.0.0",
com.sap.sse.datamining.shared;bundle-version="1.0.0" com.sap.sse.datamining.shared;bundle-version="1.0.0",
com.sap.sse.common
Bundle-ClassPath: . Bundle-ClassPath: .
Bundle-Activator: com.sap.sailing.datamining.Activator Bundle-Activator: com.sap.sailing.datamining.Activator
@@ -14,8 +14,10 @@ Export-Package: com.sap.sailing.domain.common,
com.sap.sailing.domain.common.quadtree, com.sap.sailing.domain.common.quadtree,
com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test", com.sap.sailing.domain.common.quadtree.impl;x-friends:="com.sap.sailing.domain.test",
com.sap.sailing.domain.common.racelog, com.sap.sailing.domain.common.racelog,
com.sap.sailing.domain.common.racelog.tracking,
com.sap.sailing.domain.common.racelog.utils, com.sap.sailing.domain.common.racelog.utils,
com.sap.sailing.domain.common.scalablevalue, com.sap.sailing.domain.common.scalablevalue,
com.sap.sailing.domain.common.scalablevalue.impl, com.sap.sailing.domain.common.scalablevalue.impl,
com.sap.sailing.domain.common.trackfiles com.sap.sailing.domain.common.trackfiles
Require-Bundle: com.sap.sse.datamining.shared Require-Bundle: com.sap.sse.datamining.shared,
com.sap.sse.common
@@ -7,5 +7,6 @@
<source path='common/filter'/> <source path='common/filter'/>
<source path='common/media'/> <source path='common/media'/>
<source path='common/scalablevalue'/> <source path='common/scalablevalue'/>
<source path='common/racelog/tracking'/>
<source path='common/scalablevalue/impl'/> <source path='common/scalablevalue/impl'/>
</module> </module>
@@ -57,7 +57,13 @@ public class AbstractPosition implements Position {
@Override @Override
public Distance getDistance(Position p) { public Distance getDistance(Position p) {
return new CentralAngleDistance(getCentralAngleRad(p)); final Distance result;
if (p == this || this.equals(p)) {
result = Distance.NULL;
} else {
result = new CentralAngleDistance(getCentralAngleRad(p));
}
return result;
} }
@Override @Override
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.common;
import java.io.Serializable; import java.io.Serializable;
import com.sap.sailing.domain.common.impl.RGBColor; import com.sap.sailing.domain.common.impl.RGBColor;
import com.sap.sailing.domain.common.impl.Util;
public interface Color extends Serializable { public interface Color extends Serializable {
final Color WHITE = new RGBColor(255, 255, 255); final Color WHITE = new RGBColor(255, 255, 255);
@@ -32,9 +31,9 @@ public interface Color extends Serializable {
final Color BLUE = new RGBColor(0, 0, 255); final Color BLUE = new RGBColor(0, 0, 255);
Util.Triple<Integer, Integer, Integer> getAsRGB(); com.sap.sse.common.Util.Triple<Integer, Integer, Integer> getAsRGB();
Util.Triple<Float, Float, Float> getAsHSV(); com.sap.sse.common.Util.Triple<Float, Float, Float> getAsHSV();
String getAsHtml(); String getAsHtml();
} }
@@ -1,7 +1,10 @@
package com.sap.sailing.domain.common; package com.sap.sailing.domain.common;
import static com.sap.sailing.domain.common.SortingOrder.ASCENDING;
import static com.sap.sailing.domain.common.SortingOrder.DESCENDING;
import static com.sap.sailing.domain.common.SortingOrder.NONE;
import java.io.Serializable; import java.io.Serializable;
import static com.sap.sailing.domain.common.SortingOrder.*;
/** /**
* Identifies details that can be requested from the racing service. Optionally, the details can specify a precision * Identifies details that can be requested from the racing service. Optionally, the details can specify a precision
@@ -13,7 +16,7 @@ import static com.sap.sailing.domain.common.SortingOrder.*;
*/ */
public enum DetailType implements Serializable { public enum DetailType implements Serializable {
DISTANCE_TRAVELED(0, ASCENDING), AVERAGE_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING), RACE_RANK(0, ASCENDING), REGATTA_RANK(0, ASCENDING), OVERALL_RANK(0, ASCENDING), DISTANCE_TRAVELED(0, ASCENDING), AVERAGE_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING), RACE_RANK(0, ASCENDING), REGATTA_RANK(0, ASCENDING), OVERALL_RANK(0, ASCENDING),
RANK_GAIN(0, DESCENDING), NUMBER_OF_MANEUVERS(0, ASCENDING), CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING), RANK_GAIN(0, ASCENDING), NUMBER_OF_MANEUVERS(0, ASCENDING), CURRENT_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING),
ESTIMATED_TIME_TO_NEXT_WAYPOINT_IN_SECONDS(1, ASCENDING), VELOCITY_MADE_GOOD_IN_KNOTS(2, DESCENDING), ESTIMATED_TIME_TO_NEXT_WAYPOINT_IN_SECONDS(1, ASCENDING), VELOCITY_MADE_GOOD_IN_KNOTS(2, DESCENDING),
GAP_TO_LEADER_IN_SECONDS(0, ASCENDING), GAP_CHANGE_SINCE_LEG_START_IN_SECONDS(0, ASCENDING), GAP_TO_LEADER_IN_SECONDS(0, ASCENDING), GAP_CHANGE_SINCE_LEG_START_IN_SECONDS(0, ASCENDING),
SIDE_TO_WHICH_MARK_AT_LEG_START_WAS_ROUNDED(0, ASCENDING), WINDWARD_DISTANCE_TO_GO_IN_METERS(0, ASCENDING), SIDE_TO_WHICH_MARK_AT_LEG_START_WAS_ROUNDED(0, ASCENDING), WINDWARD_DISTANCE_TO_GO_IN_METERS(0, ASCENDING),
@@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.impl.MillisecondsDurationImpl;
*/ */
public interface Duration extends Serializable, Comparable<Duration> { public interface Duration extends Serializable, Comparable<Duration> {
static final Duration NULL = new MillisecondsDurationImpl(0);
static final Duration ONE_SECOND = new MillisecondsDurationImpl(1000); static final Duration ONE_SECOND = new MillisecondsDurationImpl(1000);
static final Duration ONE_MINUTE = ONE_SECOND.times(60); static final Duration ONE_MINUTE = ONE_SECOND.times(60);
static final Duration ONE_HOUR = ONE_MINUTE.times(60); static final Duration ONE_HOUR = ONE_MINUTE.times(60);
@@ -12,13 +12,13 @@ package com.sap.sailing.domain.common;
*/ */
public enum PassingInstruction { public enum PassingInstruction {
None, None(1, 2),
Port, Port(1),
Starboard, Starboard(1),
Gate, Gate(2),
Line, Line(2),
Offset, Offset(2),
FixedBearing; FixedBearing(1);
public static PassingInstruction[] relevantValues() { public static PassingInstruction[] relevantValues() {
PassingInstruction[] uiValues = new PassingInstruction[PassingInstruction.values().length - 1]; PassingInstruction[] uiValues = new PassingInstruction[PassingInstruction.values().length - 1];
@@ -40,4 +40,15 @@ public enum PassingInstruction {
return null; return null;
} }
/**
* Denotes for which types of {@code ControlPoints} (defined by the number of marks they are made up of)
* this passing instruction is applicable.<p>
* E.g. {@code [1,2]} denotes that the passing instruction is applicable for {@code ControlPoints} with either one
* or two marks.
*/
public final int[] applicability;
private PassingInstruction(int... applicability) {
this.applicability = applicability;
}
} }
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.common; package com.sap.sailing.domain.common;
import com.sap.sse.common.Named;
public interface Renamable extends Named { public interface Renamable extends Named {
void setName(String newName); void setName(String newName);
} }
@@ -3,7 +3,9 @@ package com.sap.sailing.domain.common;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sse.common.Named;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
/** /**
* Describes sources of official regatta results which may be imported and applied to <code>ScoreCorrection</code> * Describes sources of official regatta results which may be imported and applied to <code>ScoreCorrection</code>
@@ -19,7 +21,7 @@ public interface ScoreCorrectionProvider extends Named {
* score corrections taken at different times. Later score corrections are expected to be cumulative, meaning they * score corrections taken at different times. Later score corrections are expected to be cumulative, meaning they
* also contain all previous corrections. * also contain all previous corrections.
*/ */
public Map<String, Set<Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() throws Exception; public Map<String, Set<Util.Pair<String, TimePoint>>> getHasResultsForBoatClassFromDateByEventName() throws Exception;
/** /**
* @param eventName * @param eventName
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.common; package com.sap.sailing.domain.common;
public enum ScoringSchemeType { public enum ScoringSchemeType {
LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN,
HIGH_POINT_FIRST_GETS_TEN, HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE
} }
@@ -0,0 +1,67 @@
package com.sap.sailing.domain.common;
import java.io.Serializable;
public interface TimeRange extends Comparable<TimeRange>, Serializable {
/**
* @return {@code null}, if the timepoint is at the beginning of time
*/
TimePoint from();
/**
* @return {@code null}, if the timepoint is at the beginning of time
*/
TimePoint to();
/**
* Also returns true if (either or both) the from or to timepoints are equal.
* E.g. 10-100 lies within 10-00, and 10-50 lies within 10-100.
* @param other
* @return
*/
boolean liesWithin(TimeRange other);
/**
* Reverse operation of {@link #liesWithin(TimeRange)}.
* x.includes(y) = y.liesWithin(x)
* @param other
* @return
*/
boolean includes(TimeRange other);
boolean includes(TimePoint timePoint);
boolean intersects(TimeRange other);
boolean startsBefore(TimeRange other);
boolean endsAfter(TimeRange other);
/**
* Is the time range open ended towards older timepoints?
*/
boolean openBeginning();
/**
* Is the time range open ended towards newer timepoints?
*/
boolean openEnd();
/**
* Get time-difference between the timepoint and this timerange.
* It will be 0 if the timepoint lies within the timerange, otherwise the time-difference
* to either the start or end of the timerange, depending on which is closer. The
* time difference is a duration that is guaranteed to be positive.
*/
Duration timeDifference(TimePoint timePoint);
/**
* Merges the two ranges, only possible if {@code other} {@link #intersects()} this range.
*/
TimeRange union(TimeRange other);
/**
* Intersection of the two ranges, only possible if {@code other} {@link #intersects()} this range.
*/
TimeRange intersection(TimeRange other);
}
@@ -13,7 +13,7 @@ import java.util.UUID;
import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.LeaderboardType;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sse.common.Util;
public abstract class AbstractLeaderboardDTO implements Serializable { public abstract class AbstractLeaderboardDTO implements Serializable {
private static final long serialVersionUID = -205106531931903527L; private static final long serialVersionUID = -205106531931903527L;
@@ -277,12 +277,12 @@ public abstract class AbstractLeaderboardDTO implements Serializable {
return false; return false;
} }
public List<Pair<RaceColumnDTO, FleetDTO>> getLiveRaces(long serverTimePointAsMillis) { public List<Util.Pair<RaceColumnDTO, FleetDTO>> getLiveRaces(long serverTimePointAsMillis) {
List<Pair<RaceColumnDTO, FleetDTO>> result = new ArrayList<Pair<RaceColumnDTO, FleetDTO>>(); List<Util.Pair<RaceColumnDTO, FleetDTO>> result = new ArrayList<Util.Pair<RaceColumnDTO, FleetDTO>>();
for (RaceColumnDTO race : getRaceList()) { for (RaceColumnDTO race : getRaceList()) {
for (FleetDTO fleet : race.getFleets()) { for (FleetDTO fleet : race.getFleets()) {
if (race.isLive(fleet, serverTimePointAsMillis)) { if (race.isLive(fleet, serverTimePointAsMillis)) {
result.add(new Pair<RaceColumnDTO, FleetDTO>(race, fleet)); result.add(new Util.Pair<RaceColumnDTO, FleetDTO>(race, fleet));
} }
} }
} }
@@ -23,7 +23,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial
private String idAsString; private String idAsString;
private BoatClassDTO boatClass; private BoatClassDTO boatClass;
CompetitorDTOImpl() {} public CompetitorDTOImpl() {}
public CompetitorDTOImpl(String name, Color color, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, public CompetitorDTOImpl(String name, Color color, String twoLetterIsoCountryCode, String threeLetterIocCountryCode,
String countryName, String sailID, String idAsString, BoatClassDTO boatClass) { String countryName, String sailID, String idAsString, BoatClassDTO boatClass) {
@@ -12,8 +12,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import com.sap.sailing.domain.common.Cloner; import com.sap.sailing.domain.common.Cloner;
import com.sap.sailing.domain.common.impl.Util; import com.sap.sse.common.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
/** /**
* Reduces the transmission size of a {@link LeaderboardDTO} by comparing this object to a previous version of * Reduces the transmission size of a {@link LeaderboardDTO} by comparing this object to a previous version of
@@ -177,14 +176,14 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
/** /**
* @param previousVersion needed because after serialization/deserialization, the transient {@link #previousLeaderboard} will be <code>null</code> * @param previousVersion needed because after serialization/deserialization, the transient {@link #previousLeaderboard} will be <code>null</code>
*/ */
public Set<Pair<CompetitorDTO, K>> getAllUnchangedCompetitorsAndKeys(LeaderboardDTO previousVersion) { public Set<com.sap.sse.common.Util.Pair<CompetitorDTO, K>> getAllUnchangedCompetitorsAndKeys(LeaderboardDTO previousVersion) {
Set<Pair<CompetitorDTO, K>> result = new HashSet<Util.Pair<CompetitorDTO,K>>(); Set<com.sap.sse.common.Util.Pair<CompetitorDTO, K>> result = new HashSet<com.sap.sse.common.Util.Pair<CompetitorDTO,K>>();
for (Map.Entry<K, long[]> raceColumnNameAndBitSet : unchanged.entrySet()) { for (Map.Entry<K, long[]> raceColumnNameAndBitSet : unchanged.entrySet()) {
final long[] bitset = raceColumnNameAndBitSet.getValue(); final long[] bitset = raceColumnNameAndBitSet.getValue();
if (bitset == null) { if (bitset == null) {
// this means that all entries for the column are unchanged for all competitors // this means that all entries for the column are unchanged for all competitors
for (CompetitorDTO competitor : previousVersion.competitors) { for (CompetitorDTO competitor : previousVersion.competitors) {
result.add(new Pair<CompetitorDTO, K>(competitor, raceColumnNameAndBitSet.getKey())); result.add(new com.sap.sse.common.Util.Pair<CompetitorDTO, K>(competitor, raceColumnNameAndBitSet.getKey()));
} }
} else { } else {
int competitorNumber = 0; int competitorNumber = 0;
@@ -192,7 +191,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
long bitValue = 1; long bitValue = 1;
for (int bit=0; bit<Long.SIZE; bit++) { for (int bit=0; bit<Long.SIZE; bit++) {
if ((bitset[arrayIndex] & bitValue) != 0) { if ((bitset[arrayIndex] & bitValue) != 0) {
result.add(new Pair<CompetitorDTO, K>(previousVersion.competitors.get(competitorNumber), raceColumnNameAndBitSet.getKey())); result.add(new com.sap.sse.common.Util.Pair<CompetitorDTO, K>(previousVersion.competitors.get(competitorNumber), raceColumnNameAndBitSet.getKey()));
} }
bitValue <<= 1; bitValue <<= 1;
competitorNumber++; competitorNumber++;
@@ -259,7 +258,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
* @author Axel Uhl (d043530) * @author Axel Uhl (d043530)
* *
*/ */
static class UnchangedLegDetails extends UnchangedWithCompetitorsInBitSet<Pair<String, Integer>> { static class UnchangedLegDetails extends UnchangedWithCompetitorsInBitSet<com.sap.sse.common.Util.Pair<String, Integer>> {
private static final long serialVersionUID = 8726138955651801210L; private static final long serialVersionUID = 8726138955651801210L;
UnchangedLegDetails() {} // for (de)serialization UnchangedLegDetails() {} // for (de)serialization
@@ -277,7 +276,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
* by <code>null</code>, meaning the race column / leg details are unchnaged for all competitors. * by <code>null</code>, meaning the race column / leg details are unchnaged for all competitors.
*/ */
public void compact() { public void compact() {
for (Pair<String, Integer> key : getAllUnchangedKeys()) { for (com.sap.sse.common.Util.Pair<String, Integer> key : getAllUnchangedKeys()) {
if (key.getB() != null) { if (key.getB() != null) {
tryToCompact(key); tryToCompact(key);
} }
@@ -290,11 +289,11 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
* or for which all entries in the race column are unchanged. * or for which all entries in the race column are unchanged.
*/ */
@Override @Override
protected int getNumberOfSetBits(Pair<String, Integer> key) { protected int getNumberOfSetBits(com.sap.sse.common.Util.Pair<String, Integer> key) {
int result; int result;
if (key.getB() != null) { if (key.getB() != null) {
long[] bitset = getUnchangedBitset(key); long[] bitset = getUnchangedBitset(key);
long[] nullBitset = getUnchangedBitset(new Pair<String, Integer>(key.getA(), null)); long[] nullBitset = getUnchangedBitset(new com.sap.sse.common.Util.Pair<String, Integer>(key.getA(), null));
long[] orBitset = or(bitset, nullBitset); long[] orBitset = or(bitset, nullBitset);
result = getNumberOfBitsSet(orBitset); result = getNumberOfBitsSet(orBitset);
} else { } else {
@@ -413,16 +412,16 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
} }
final Set<CompetitorDTO> rowsUnchangedForCompetitors = new HashSet<CompetitorDTO>(); final Set<CompetitorDTO> rowsUnchangedForCompetitors = new HashSet<CompetitorDTO>();
if (rowsUnchanged != null) { if (rowsUnchanged != null) {
for (Pair<CompetitorDTO, Void> rowUnchanged : rowsUnchanged.getAllUnchangedCompetitorsAndKeys(previousVersion)) { for (com.sap.sse.common.Util.Pair<CompetitorDTO, Void> rowUnchanged : rowsUnchanged.getAllUnchangedCompetitorsAndKeys(previousVersion)) {
rowsUnchangedForCompetitors.add(rowUnchanged.getA()); rowsUnchangedForCompetitors.add(rowUnchanged.getA());
rows.put(rowUnchanged.getA(), previousVersion.rows.get(rowUnchanged.getA())); rows.put(rowUnchanged.getA(), previousVersion.rows.get(rowUnchanged.getA()));
} }
} }
final Set<Pair<CompetitorDTO, String>> allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames = final Set<com.sap.sse.common.Util.Pair<CompetitorDTO, String>> allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames =
unchangedLeaderboardEntries == null ? new HashSet<Util.Pair<CompetitorDTO,String>>() : unchangedLeaderboardEntries == null ? new HashSet<com.sap.sse.common.Util.Pair<CompetitorDTO,String>>() :
unchangedLeaderboardEntries.getAllUnchangedCompetitorsAndKeys(previousVersion); unchangedLeaderboardEntries.getAllUnchangedCompetitorsAndKeys(previousVersion);
if (unchangedLeaderboardEntries != null) { if (unchangedLeaderboardEntries != null) {
for (Pair<CompetitorDTO, String> competitorAndColumnName : allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames) { for (com.sap.sse.common.Util.Pair<CompetitorDTO, String> competitorAndColumnName : allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames) {
CompetitorDTO previousCompetitor = competitorAndColumnName.getA(); CompetitorDTO previousCompetitor = competitorAndColumnName.getA();
if (!rowsUnchangedForCompetitors.contains(previousCompetitor)) { // only care if not the entire row was marked unchanged if (!rowsUnchangedForCompetitors.contains(previousCompetitor)) { // only care if not the entire row was marked unchanged
LeaderboardEntryDTO previousEntry = previousVersion.rows.get(previousCompetitor).fieldsByRaceColumnName.get( LeaderboardEntryDTO previousEntry = previousVersion.rows.get(previousCompetitor).fieldsByRaceColumnName.get(
@@ -435,14 +434,14 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
} }
} }
if (legDetailsUnchanged != null) { if (legDetailsUnchanged != null) {
for (Pair<CompetitorDTO, Pair<String, Integer>> competitorInPreviosAndColumnNameAndLegDetailsIndex : legDetailsUnchanged for (com.sap.sse.common.Util.Pair<CompetitorDTO, com.sap.sse.common.Util.Pair<String, Integer>> competitorInPreviosAndColumnNameAndLegDetailsIndex : legDetailsUnchanged
.getAllUnchangedCompetitorsAndKeys(previousVersion)) { .getAllUnchangedCompetitorsAndKeys(previousVersion)) {
CompetitorDTO previousCompetitor = competitorInPreviosAndColumnNameAndLegDetailsIndex.getA(); CompetitorDTO previousCompetitor = competitorInPreviosAndColumnNameAndLegDetailsIndex.getA();
final String raceColumnName = competitorInPreviosAndColumnNameAndLegDetailsIndex.getB().getA(); final String raceColumnName = competitorInPreviosAndColumnNameAndLegDetailsIndex.getB().getA();
// if it's already clear that the entire LeaderboardEntryDTO was unchanged, the entry in legDetailsUnchanged was // if it's already clear that the entire LeaderboardEntryDTO was unchanged, the entry in legDetailsUnchanged was
// merely a hint for column compression within legDetailsUnchanged and doesn't need to be handled here // merely a hint for column compression within legDetailsUnchanged and doesn't need to be handled here
if (!allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames if (!allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames
.contains(new Pair<CompetitorDTO, String>(previousCompetitor, raceColumnName))) { .contains(new com.sap.sse.common.Util.Pair<CompetitorDTO, String>(previousCompetitor, raceColumnName))) {
final LeaderboardRowDTO leaderboardRowDTO = rows.get(previousCompetitor); final LeaderboardRowDTO leaderboardRowDTO = rows.get(previousCompetitor);
LeaderboardEntryDTO leaderboardEntry = leaderboardRowDTO == null ? null LeaderboardEntryDTO leaderboardEntry = leaderboardRowDTO == null ? null
: leaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName); : leaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName);
@@ -606,7 +605,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
// also mark all leg details for the competitor for this column as unchanged; this will ensure // also mark all leg details for the competitor for this column as unchanged; this will ensure
// that column compression can work for leg details // that column compression can work for leg details
getLegDetailsUnchanged(previousVersion).unchanged(competitorAndRow.getKey(), getLegDetailsUnchanged(previousVersion).unchanged(competitorAndRow.getKey(),
new Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(), null)); new com.sap.sse.common.Util.Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(), null));
} else { } else {
LeaderboardEntryDTO newLeaderboardEntryDTO = new LeaderboardEntryDTO(); LeaderboardEntryDTO newLeaderboardEntryDTO = new LeaderboardEntryDTO();
cloner.clone(raceColumnNameAndLeaderboardEntry.getValue(), newLeaderboardEntryDTO); cloner.clone(raceColumnNameAndLeaderboardEntry.getValue(), newLeaderboardEntryDTO);
@@ -627,7 +626,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
&& previousVersion.competitors.contains(competitorAndRow.getKey())) { && previousVersion.competitors.contains(competitorAndRow.getKey())) {
getLegDetailsUnchanged(previousVersion).unchanged( getLegDetailsUnchanged(previousVersion).unchanged(
competitorAndRow.getKey(), competitorAndRow.getKey(),
new Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(), new com.sap.sse.common.Util.Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(),
legDetailsIndex)); legDetailsIndex));
newLeaderboardEntryDTO.legDetails.set(legDetailsIndex, null); newLeaderboardEntryDTO.legDetails.set(legDetailsIndex, null);
} }
@@ -641,7 +640,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
// however, mark the legDetails as unchanged in legDetailsUnchanged so as to allow for // however, mark the legDetails as unchanged in legDetailsUnchanged so as to allow for
// all-column compression // all-column compression
getLegDetailsUnchanged(previousVersion).unchanged(competitorAndRow.getKey(), getLegDetailsUnchanged(previousVersion).unchanged(competitorAndRow.getKey(),
new Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(), null)); new com.sap.sse.common.Util.Pair<String, Integer>(raceColumnNameAndLeaderboardEntry.getKey(), null));
} }
} }
} }
@@ -693,7 +692,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
if (row != null && row.fieldsByRaceColumnName != null) { if (row != null && row.fieldsByRaceColumnName != null) {
for (Map.Entry<String, LeaderboardEntryDTO> e : row.fieldsByRaceColumnName.entrySet()) { for (Map.Entry<String, LeaderboardEntryDTO> e : row.fieldsByRaceColumnName.entrySet()) {
getUnchangedLeaderboardEntries(previousVersion).unchanged(competitor, e.getKey()); getUnchangedLeaderboardEntries(previousVersion).unchanged(competitor, e.getKey());
getLegDetailsUnchanged(previousVersion).unchanged(competitor, new Pair<String, Integer>(e.getKey(), /* all legs unchanged */ null)); getLegDetailsUnchanged(previousVersion).unchanged(competitor, new com.sap.sse.common.Util.Pair<String, Integer>(e.getKey(), /* all legs unchanged */ null));
} }
} }
} }
@@ -49,18 +49,26 @@ public class LeaderboardDTO extends AbstractLeaderboardDTO implements Serializab
*/ */
private boolean higherScoresIsBetter; private boolean higherScoresIsBetter;
/**
* Tells whether this leaderboard has data about overall details. This corresponds with the <code>addOverallDetails</code> request parameter
* for a leaderboard DTO computation.
*/
private boolean hasOverallDetails;
LeaderboardDTO() {} // for serialization LeaderboardDTO() {} // for serialization
/** /**
* @param uuidGenerator used to provide the {@link #id ID} for this object (see also {@link #getId()}) and for any clones produced * @param uuidGenerator used to provide the {@link #id ID} for this object (see also {@link #getId()}) and for any clones produced
* from it by the {@link #clone()} operation. * from it by the {@link #clone()} operation.
* @param hasOverallDetails TODO
*/ */
public LeaderboardDTO(Date timePointOfLastCorrectionsValidity, String comment, boolean higherScoreIsBetter, UUIDGenerator uuidGenerator) { public LeaderboardDTO(Date timePointOfLastCorrectionsValidity, String comment, boolean higherScoreIsBetter, UUIDGenerator uuidGenerator, boolean hasOverallDetails) {
initCollections(); initCollections();
id = uuidGenerator.generateRandomUUID(); id = uuidGenerator.generateRandomUUID();
this.timePointOfLastCorrectionsValidity = timePointOfLastCorrectionsValidity; this.timePointOfLastCorrectionsValidity = timePointOfLastCorrectionsValidity;
this.comment = comment; this.comment = comment;
this.higherScoresIsBetter = higherScoreIsBetter; this.higherScoresIsBetter = higherScoreIsBetter;
this.hasOverallDetails = hasOverallDetails;
} }
private void initCollections() { private void initCollections() {
@@ -165,4 +173,12 @@ public class LeaderboardDTO extends AbstractLeaderboardDTO implements Serializab
public void setComment(String comment) { public void setComment(String comment) {
this.comment = comment; this.comment = comment;
} }
/**
* Tells whether this leaderboard has data about overall details. This corresponds with the <code>addOverallDetails</code> request parameter
* for a leaderboard DTO computation.
*/
public boolean hasOverallDetails() {
return hasOverallDetails;
}
} }
@@ -2,7 +2,9 @@ package com.sap.sailing.domain.common.dto;
import java.io.Serializable; import java.io.Serializable;
public class NamedDTO implements Serializable { import com.sap.sse.common.Named;
public class NamedDTO implements Named, Serializable {
private static final long serialVersionUID = -6620231501480297257L; private static final long serialVersionUID = -6620231501480297257L;
private String name; private String name;
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.common.dto; package com.sap.sailing.domain.common.dto;
import com.sap.sailing.domain.common.impl.Util; import com.sap.sse.common.Util;
/** /**
* Like the superclass, but competitors are fetched from the {@link LeaderboardDTO#getSuppressedCompetitors()} list * Like the superclass, but competitors are fetched from the {@link LeaderboardDTO#getSuppressedCompetitors()} list
@@ -23,6 +23,8 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
private Double explicitFactor; private Double explicitFactor;
private double effectiveFactor; private double effectiveFactor;
private Map<FleetDTO, RaceLogTrackingInfoDTO> raceLogTrackingInfos = new HashMap<FleetDTO, RaceLogTrackingInfoDTO>();
RaceColumnDTO() {} // for GWT serialization RaceColumnDTO() {} // for GWT serialization
public RaceColumnDTO(Boolean isValidInTotalScore) { public RaceColumnDTO(Boolean isValidInTotalScore) {
@@ -283,4 +285,12 @@ public class RaceColumnDTO extends NamedDTO implements Serializable {
public double getEffectiveFactor() { public double getEffectiveFactor() {
return effectiveFactor; return effectiveFactor;
} }
public RaceLogTrackingInfoDTO getRaceLogTrackingInfo(FleetDTO fleet) {
return raceLogTrackingInfos.get(fleet);
}
public void setRaceLogTrackingInfo(FleetDTO fleet, RaceLogTrackingInfoDTO info) {
raceLogTrackingInfos.put(fleet, info);
}
} }
@@ -0,0 +1,21 @@
package com.sap.sailing.domain.common.dto;
import java.io.Serializable;
import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState;
public class RaceLogTrackingInfoDTO implements Serializable {
private static final long serialVersionUID = -6861382173074620168L;
public boolean raceLogTrackerExists;
public boolean competitorRegistrationsExists;
public RaceLogTrackingState raceLogTrackingState;
protected RaceLogTrackingInfoDTO() {}
public RaceLogTrackingInfoDTO(boolean raceLogTrackerExists, boolean competitorRegistrationsExists,
RaceLogTrackingState raceLogTrackingState) {
this.raceLogTrackerExists = raceLogTrackerExists;
this.competitorRegistrationsExists = competitorRegistrationsExists;
this.raceLogTrackingState = raceLogTrackingState;
}
}
@@ -1,14 +1,14 @@
package com.sap.sailing.domain.common.impl; package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.Color; import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sse.common.Util;
public abstract class AbstractColor implements Color { public abstract class AbstractColor implements Color {
private static final long serialVersionUID = 7758884012281863458L; private static final long serialVersionUID = 7758884012281863458L;
@Override @Override
public String getAsHtml() { public String getAsHtml() {
Triple<Integer, Integer, Integer> asRGB = getAsRGB(); Util.Triple<Integer, Integer, Integer> asRGB = getAsRGB();
return "#" + toBrowserHexValue(asRGB.getA()) + toBrowserHexValue(asRGB.getB()) return "#" + toBrowserHexValue(asRGB.getA()) + toBrowserHexValue(asRGB.getB())
+ toBrowserHexValue(asRGB.getC()); + toBrowserHexValue(asRGB.getC());
} }
@@ -14,8 +14,9 @@ public abstract class AbstractTimePoint implements TimePoint {
@Override @Override
public int compare(TimePoint o1, TimePoint o2) { public int compare(TimePoint o1, TimePoint o2) {
long milliDiff = o1.asMillis() - o2.asMillis(); long o1Millis = o1.asMillis();
return milliDiff<0 ? -1 : milliDiff == 0 ? 0 : 1; long o2Millis = o2.asMillis();
return o1Millis<o2Millis?-1:o1Millis==o2Millis?0:1;
} }
}; };
@@ -6,7 +6,7 @@ import java.util.List;
import com.sap.sailing.domain.common.Color; import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.ColorMap; import com.sap.sailing.domain.common.ColorMap;
import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sse.common.Util;
/** /**
@@ -64,7 +64,7 @@ public class ColorMapImpl<T> implements ColorMap<T> {
public boolean addBlockedColor(Color color) { public boolean addBlockedColor(Color color) {
boolean result = false; boolean result = false;
if(color != null) { if(color != null) {
Triple<Float, Float, Float> asHSV = color.getAsHSV(); Util.Triple<Float, Float, Float> asHSV = color.getAsHSV();
result = blockedColors.add(new HSVColor(asHSV.getA(), asHSV.getB(), asHSV.getC())); result = blockedColors.add(new HSVColor(asHSV.getA(), asHSV.getB(), asHSV.getC()));
} }
return result; return result;
@@ -73,7 +73,7 @@ public class ColorMapImpl<T> implements ColorMap<T> {
public boolean removeBlockedColor(Color color) { public boolean removeBlockedColor(Color color) {
boolean result = false; boolean result = false;
if(color != null) { if(color != null) {
Triple<Float, Float, Float> asHSV = color.getAsHSV(); Util.Triple<Float, Float, Float> asHSV = color.getAsHSV();
result = blockedColors.remove(new HSVColor(asHSV.getA(), asHSV.getB(), asHSV.getC())); result = blockedColors.remove(new HSVColor(asHSV.getA(), asHSV.getB(), asHSV.getC()));
} }
return result; return result;
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.common.impl; package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sse.common.Util;
/** /**
* A color defined in the HSV color schema (hue, saturation, brightness) Hue is a degree between 0.0 and 360.0 * A color defined in the HSV color schema (hue, saturation, brightness) Hue is a degree between 0.0 and 360.0
@@ -35,7 +35,7 @@ public class HSVColor extends AbstractColor {
} }
@Override @Override
public Triple<Integer, Integer, Integer> getAsRGB() { public Util.Triple<Integer, Integer, Integer> getAsRGB() {
float r, b, g; float r, b, g;
if (saturation == 0) { if (saturation == 0) {
@@ -80,14 +80,14 @@ public class HSVColor extends AbstractColor {
b = q; b = q;
} }
} }
Triple<Integer, Integer, Integer> RGBColor = new Triple<Integer, Integer, Integer>(Math.round(r * 255), Util.Triple<Integer, Integer, Integer> RGBColor = new Util.Triple<Integer, Integer, Integer>(Math.round(r * 255),
Math.round(g * 255), Math.round(b * 255)); Math.round(g * 255), Math.round(b * 255));
return RGBColor; return RGBColor;
} }
@Override @Override
public Triple<Float, Float, Float> getAsHSV() { public Util.Triple<Float, Float, Float> getAsHSV() {
return new Triple<Float, Float, Float>(hue, saturation, brightness); return new Util.Triple<Float, Float, Float>(hue, saturation, brightness);
} }
@Override @Override
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.common.impl; package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.Named; import com.sap.sse.common.Named;
public class NamedImpl implements Named { public class NamedImpl implements Named {
private static final long serialVersionUID = -4815125282671451300L; private static final long serialVersionUID = -4815125282671451300L;
@@ -13,7 +13,7 @@ import java.util.Comparator;
public class NaturalComparator implements Comparator<String> { public class NaturalComparator implements Comparator<String> {
boolean caseSensitive; boolean caseSensitive;
public NaturalComparator(boolean caseSensitive){ public NaturalComparator(boolean caseSensitive) {
this.caseSensitive = caseSensitive; this.caseSensitive = caseSensitive;
} }
@@ -26,9 +26,9 @@ public class NaturalComparator implements Comparator<String> {
*/ */
@Override @Override
public int compare(String a, String b) { public int compare(String a, String b) {
if(!caseSensitive){ if (!caseSensitive){
a = a.toLowerCase(); a = a.toLowerCase();
b = a.toLowerCase(); b = b.toLowerCase();
} }
int result = 0; int result = 0;
int aIndex = 0; int aIndex = 0;
@@ -2,7 +2,7 @@ package com.sap.sailing.domain.common.impl;
import java.net.URLEncoder; import java.net.URLEncoder;
import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sse.common.Util;
/** /**
* This class is used by our backend, in GWT-client code and by the Android app. Therefore we cannot use classes like * This class is used by our backend, in GWT-client code and by the Android app. Therefore we cannot use classes like
@@ -18,7 +18,7 @@ public class QRCodeUtils {
return apkUrl + "#" + fragmentKey + "=" + encodedIdentifier; return apkUrl + "#" + fragmentKey + "=" + encodedIdentifier;
} }
public static Pair<String, String> splitQRContent(String qrCodeContent) { public static Util.Pair<String, String> splitQRContent(String qrCodeContent) {
int fragmentIndex = qrCodeContent.lastIndexOf('#'); int fragmentIndex = qrCodeContent.lastIndexOf('#');
if (fragmentIndex == -1 || fragmentIndex == 0 || qrCodeContent.length() == fragmentIndex + 1) { if (fragmentIndex == -1 || fragmentIndex == 0 || qrCodeContent.length() == fragmentIndex + 1) {
throw new IllegalArgumentException("There is no server or identifier."); throw new IllegalArgumentException("There is no server or identifier.");
@@ -31,7 +31,7 @@ public class QRCodeUtils {
deviceIdentifier = deviceIdentifier.replaceAll("%20", " "); deviceIdentifier = deviceIdentifier.replaceAll("%20", " ");
String apkUrl = qrCodeContent.substring(0, fragmentIndex); String apkUrl = qrCodeContent.substring(0, fragmentIndex);
return new Pair<String, String>(deviceIdentifier, apkUrl); return new Util.Pair<String, String>(deviceIdentifier, apkUrl);
} }
} }
@@ -1,6 +1,6 @@
package com.sap.sailing.domain.common.impl; package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sse.common.Util;
/** /**
* A color defined in the RGB color schema * A color defined in the RGB color schema
@@ -66,11 +66,11 @@ public class RGBColor extends AbstractColor {
} }
@Override @Override
public Triple<Integer, Integer, Integer> getAsRGB() { public Util.Triple<Integer, Integer, Integer> getAsRGB() {
return new Triple<Integer, Integer, Integer>(red, green, blue); return new Util.Triple<Integer, Integer, Integer>(red, green, blue);
} }
public Triple<Float, Float, Float> getAsHSV() { public Util.Triple<Float, Float, Float> getAsHSV() {
float hue, saturation, brightness; float hue, saturation, brightness;
int cmax = (red > green) ? red : green; int cmax = (red > green) ? red : green;
if (blue > cmax) { if (blue > cmax) {
@@ -107,7 +107,7 @@ public class RGBColor extends AbstractColor {
} }
} }
Triple<Float, Float, Float> HSVColor = new Triple<Float, Float, Float>(hue, saturation, brightness); Util.Triple<Float, Float, Float> HSVColor = new Util.Triple<Float, Float, Float>(hue, saturation, brightness);
return HSVColor; return HSVColor;
} }
@@ -0,0 +1,143 @@
package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.Duration;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.TimeRange;
import com.sap.sse.common.Util;
public class TimeRangeImpl extends Util.Pair<TimePoint, TimePoint> implements TimeRange {
public static final TimePoint BeginningOfTime = new MillisecondsTimePoint(Long.MIN_VALUE);
public static final TimePoint EndOfTime = new MillisecondsTimePoint(Long.MAX_VALUE);
private static final long serialVersionUID = 8710198176227507300L;
public static TimeRange create(long fromMillis, long toMillis) {
return new TimeRangeImpl(new MillisecondsTimePoint(fromMillis), new MillisecondsTimePoint(toMillis));
}
public TimeRangeImpl(TimePoint from, TimePoint to) {
super(from == null ? BeginningOfTime : from, to == null ? EndOfTime : to);
if (from().after(to())) {
throw new IllegalArgumentException("from " + from() + " must lie before to " + to() + " in a TimeRange");
}
}
@Override
public int compareTo(TimeRange other) {
final int result;
if (other.from().equals(from()) && other.to().equals(to())) {
result = 0;
} else {
result = startsBefore(other) ? -1 : 1;
}
return result;
}
@Override
public TimePoint from() {
return getA();
}
@Override
public TimePoint to() {
return getB();
}
@Override
public boolean liesWithin(TimeRange other) {
return from().compareTo(other.from()) >= 0 && to().compareTo(other.to()) <= 0;
}
@Override
public boolean includes(TimeRange other) {
return other.liesWithin(this);
}
@Override
public boolean intersects(TimeRange other) {
return includes(other.from()) || includes(other.to()) || liesWithin(other);
}
@Override
public boolean includes(TimePoint timePoint) {
return from().compareTo(timePoint) <= 0 && to().compareTo(timePoint) >= 0;
}
@Override
public boolean startsBefore(TimeRange other) {
return from().before(other.from());
}
@Override
public boolean endsAfter(TimeRange other) {
return to().after(other.to());
}
@Override
public Duration timeDifference(TimePoint timePoint) {
final Duration result;
if (includes(timePoint)) {
result = Duration.NULL;
} else if (timePoint.before(from())) {
result = timePoint.until(from());
} else {
result = to().until(timePoint);
}
return result;
}
@Override
public TimeRange union(TimeRange other) {
final TimeRange result;
if (!intersects(other)) {
result = null;
} else {
TimePoint newFrom = startsBefore(other) ? from() : other.from();
TimePoint newTo = endsAfter(other) ? to() : other.to();
result = new TimeRangeImpl(newFrom, newTo);
}
return result;
}
@Override
public boolean openBeginning() {
return from().equals(BeginningOfTime);
}
@Override
public boolean openEnd() {
return to().equals(EndOfTime);
}
@Override
public TimeRange intersection(TimeRange other) {
final TimeRange result;
if (!intersects(other)) {
result = null;
} else {
TimePoint newFrom = startsBefore(other) ? other.from() : from();
TimePoint newTo = endsAfter(other) ? other.to() : to();
result = new TimeRangeImpl(newFrom, newTo);
}
return result;
}
@Override
public boolean equals(Object obj) {
final boolean result;
if (this == obj) {
result = true;
} else {
if (obj instanceof TimeRange) {
TimeRange other = (TimeRange) obj;
return from().equals(other.from()) && to().equals(other.to());
}
result = super.equals(obj);
}
return result;
}
@Override
public String toString() {
return from() + "-" + to();
}
}
@@ -1,5 +1,6 @@
package com.sap.sailing.domain.common.impl; package com.sap.sailing.domain.common.impl;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.WindSourceType;
/** /**
@@ -1,18 +1,29 @@
package com.sap.sailing.domain.common.racelog; package com.sap.sailing.domain.common.racelog;
/** /**
* The status of a race in a race log
* @author D053502 * @author D053502
* *
*/ */
public enum RaceLogRaceStatus { public enum RaceLogRaceStatus {
UNKNOWN, UNSCHEDULED, SCHEDULED, STARTPHASE, RUNNING, FINISHING, FINISHED; UNKNOWN(0), UNSCHEDULED(1), SCHEDULED(2), STARTPHASE(3), RUNNING(4), FINISHING(5), FINISHED(6);
/** the order number represents the natural order of the states */
private int orderNumber;
RaceLogRaceStatus(int orderNumber) {
this.orderNumber = orderNumber;
}
public static boolean isActive(RaceLogRaceStatus status) { public static boolean isActive(RaceLogRaceStatus status) {
if (status == null) { if (status == null) {
return false; return false;
} }
return status.equals(SCHEDULED) || status.equals(STARTPHASE) || status.equals(RUNNING) return status.equals(SCHEDULED) || status.equals(STARTPHASE) || status.equals(RUNNING) || status.equals(FINISHING);
|| status.equals(FINISHING); }
public int getOrderNumber() {
return orderNumber;
} }
} }
@@ -0,0 +1,24 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NoCorrespondingServiceRegisteredException extends RuntimeException {
public String type;
public String serviceInterface;
private static final long serialVersionUID = -358955216089477585L;
protected NoCorrespondingServiceRegisteredException() {}
public NoCorrespondingServiceRegisteredException(String message, String type, String serviceInterface) {
super(message);
this.type = type;
this.serviceInterface = serviceInterface;
}
public String getDeviceType() {
return type;
}
@Override
public String toString() {
return super.toString() + " (Service: " + serviceInterface + ", Type: " + type + ")";
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotDenotableForRaceLogTrackingException extends Exception {
private static final long serialVersionUID = 6721038282862173471L;
public NotDenotableForRaceLogTrackingException() {
super();
}
public NotDenotableForRaceLogTrackingException(String msg) {
super(msg);
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotDenotedForRaceLogTrackingException extends Exception {
private static final long serialVersionUID = 6721038282862173471L;
public NotDenotedForRaceLogTrackingException() {
super();
}
public NotDenotedForRaceLogTrackingException(String msg) {
super(msg);
}
}
@@ -0,0 +1,13 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class NotRevokableException extends Exception {
private static final long serialVersionUID = 6825451915706047105L;
public NotRevokableException() {
super();
}
public NotRevokableException(String msg) {
super(msg);
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class RaceLogRaceTrackerExistsException extends RuntimeException {
private static final long serialVersionUID = 6721038282862173471L;
public RaceLogRaceTrackerExistsException() {
super();
}
public RaceLogRaceTrackerExistsException(String raceLogName) {
super("Tracker for racelog " + raceLogName + " already exists");
}
}
@@ -0,0 +1,30 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* The state of the race tracked via the racelog. This can be determined by inspecting the corresponding events
* in the racelog with the {@link RaceLogTrackingStateAnalyzer}.
* @author Fredrik Teschke
*
*/
public enum RaceLogTrackingState {
//can't determine whether tracking has ended from race log, therefore omitting TRACKING_ENDED state for now
/**
* no {@link DenoteForTrackingEvent} is present
*/
NOT_A_RACELOG_TRACKED_RACE,
/**
* a {@link DenoteForTrackingEvent} is present, but no {@link StartTrackingEvent} yet.
*/
AWAITING_RACE_DEFINITION,
/**
* a {@link StartTrackingEvent} is present
*/
TRACKING;
public boolean isForTracking() {
return this != NOT_A_RACELOG_TRACKED_RACE;
}
}
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common.racelog.tracking;
public class RaceNotCreatedException extends RuntimeException {
private static final long serialVersionUID = 6721038282862173471L;
public RaceNotCreatedException() {
super();
}
public RaceNotCreatedException(String msg) {
super(msg);
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* Only can provide the service for a single {@code type}, e.g. on smartphones with no OSGi context.
* Optionally, a {@link #setFallbackService(Object) fallback} can be set.
* @author Fredrik Teschke
*/
public class SingleTypeBasedServiceFinderImpl<ServiceType> implements
TypeBasedServiceFinder<ServiceType> {
private final ServiceType service;
private final String type;
private ServiceType fallback;
public SingleTypeBasedServiceFinderImpl(ServiceType service, ServiceType fallback, String type) {
this.service = service;
this.type = type;
this.fallback = fallback;
}
public SingleTypeBasedServiceFinderImpl(ServiceType service, String type) {
this(service, null, type);
}
@Override
public ServiceType findService(String type)
throws NoCorrespondingServiceRegisteredException {
if (type.equals(this.type)) return service;
if (fallback != null) return fallback;
throw new NoCorrespondingServiceRegisteredException("Only one service registered", type, service.getClass().getSimpleName());
}
@Override
public void setFallbackService(ServiceType fallback) {
this.fallback = fallback;
}
}
@@ -0,0 +1,30 @@
package com.sap.sailing.domain.common.racelog.tracking;
import java.io.IOException;
public class TransformationException extends IOException {
private static final long serialVersionUID = -7795777645371428971L;
public TransformationException() {
}
public TransformationException(Class<?> from, Class<?> to, String at, Throwable e) {
super("Couldn't transform "+from.getName()+" into "+to.getName()+" at "+at, e);
}
public TransformationException(Class<?> from, Class<?> to, String at) {
this(from, to, at, null);
}
public TransformationException(String message, Throwable e) {
super(message, e);
}
public TransformationException(Throwable e) {
super(e);
}
public TransformationException(String message) {
super(message);
}
}
@@ -0,0 +1,13 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* Handle transformation between two types. Most likely use-case is serialization,
* e.g. for JSON documents or database persistence.
*
* @author Fredrik Teschke
*
*/
public interface TransformationHandler<T1, T2> {
T1 transformBack(T2 object) throws TransformationException;
T2 transformForth(T1 object) throws TransformationException;
}
@@ -0,0 +1,29 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* @author Fredrik Teschke
*
* @param <ServiceType> Specifies desired the service interface
*/
public interface TypeBasedServiceFinder<ServiceType> {
public static final String TYPE = "type";
/**
* Find a service that implements the <ServiceType> interface for the specified {@code type}
* of object (e.g. type of a {@link GPSFix}).
* @param type A {@link String} that specifies for which type the service should be registered
* @throws NoCorrespondingServiceRegisteredException Thrown, if no service is registered for this type.
*/
ServiceType findService(String type) throws NoCorrespondingServiceRegisteredException;
/**
* Sets a fallback service (optional), that is used if no service is registered for a {@code type}.
* This should be a generic service, that can deal with any {@code type}, and provides a
* "better-than-nothing" implementation, which will be returned instead of throwing a
* {@link NoCorrespondingServiceRegisteredException}.
* <p>
* This method does not need to be implemented, but can remain a stub, if no fallback behaviour
* is desired.
*/
void setFallbackService(ServiceType fallback);
}
@@ -0,0 +1,18 @@
package com.sap.sailing.domain.common.racelog.tracking;
/**
* A factory for creating {@link TypeBasedServiceFinder}s, for a specific type of service.
* The desired service type is specified by the {@link Class} object passed to the
* {@link #createServiceFinder(Class)} method.
*
* The created {@link TypeBasedServiceFinder} can then be used to find the desired
* service for a specific type. E.g., there may be a persistence service interface for
* {@link GPSFix}es, and there are several different service registered, depending on the type
* of {@link GPSFix}. The service finder then can find the appropriate service for each fix.
* @author Fredrik Teschke
*
*/
public interface TypeBasedServiceFinderFactory {
<ServiceT> TypeBasedServiceFinder<ServiceT> createServiceFinder(Class<ServiceT> clazz);
}
@@ -6,8 +6,8 @@ import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.RadianBearingImpl; import com.sap.sailing.domain.common.impl.RadianBearingImpl;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.scalablevalue.ScalableValue; import com.sap.sailing.domain.common.scalablevalue.ScalableValue;
import com.sap.sse.common.Util;
/** /**
* Separately scales speed and bearing. Instead of considering speed and bearing a single vector that can be scaled, the * Separately scales speed and bearing. Instead of considering speed and bearing a single vector that can be scaled, the
@@ -19,7 +19,7 @@ import com.sap.sailing.domain.common.scalablevalue.ScalableValue;
* @author Axel Uhl (d043530) * @author Axel Uhl (d043530)
* *
*/ */
public class ScalableSpeedWithBearing implements ScalableValue<Triple<Speed, Double, Double>, SpeedWithBearing> { public class ScalableSpeedWithBearing implements ScalableValue<Util.Triple<Speed, Double, Double>, SpeedWithBearing> {
private final Speed speed; private final Speed speed;
private final double sin; private final double sin;
private final double cos; private final double cos;
@@ -42,7 +42,7 @@ public class ScalableSpeedWithBearing implements ScalableValue<Triple<Speed, Dou
} }
@Override @Override
public ScalableSpeedWithBearing add(ScalableValue<Triple<Speed, Double, Double>, SpeedWithBearing> t) { public ScalableSpeedWithBearing add(ScalableValue<Util.Triple<Speed, Double, Double>, SpeedWithBearing> t) {
Speed newSpeed = new KnotSpeedImpl(speed.getKnots() + t.getValue().getA().getKnots()); Speed newSpeed = new KnotSpeedImpl(speed.getKnots() + t.getValue().getA().getKnots());
return new ScalableSpeedWithBearing(newSpeed, sin+t.getValue().getB(), cos+t.getValue().getC()); return new ScalableSpeedWithBearing(newSpeed, sin+t.getValue().getB(), cos+t.getValue().getC());
} }
@@ -61,8 +61,8 @@ public class ScalableSpeedWithBearing implements ScalableValue<Triple<Speed, Dou
} }
@Override @Override
public Triple<Speed, Double, Double> getValue() { public Util.Triple<Speed, Double, Double> getValue() {
return new Triple<Speed, Double, Double>(speed, sin, cos); return new Util.Triple<Speed, Double, Double>(speed, sin, cos);
} }
} }
@@ -0,0 +1,8 @@
<?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="src" path="resources"/>
<classpathentry kind="output" path="bin"/>
</classpath>
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sailing.domain.deckmanadapter.test</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>
@@ -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
@@ -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: Test
Bundle-SymbolicName: com.sap.sailing.domain.deckmanadapter.test
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Fragment-Host: com.sap.sailing.domain.deckmanadapter
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit4
@@ -0,0 +1,5 @@
source.. = src/,\
resources/
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.deckmanadapter.test</artifactId>
<packaging>eclipse-test-plugin</packaging>
</project>
@@ -0,0 +1,4 @@
date,race_name,leg_name,leg_score,boat_speed,heel,leeway,rudder,heading,course,depth,tws,twa,twd,aws,awa,latitude,longitude,sog,cog,abstwa,absawa,absheel,absleeway,absrudder,foresail,staysail,mainsail,forestay,rake,vmg,status,starboard_port,rudder2,keelang,absrudder2,abskeelang
2013-10-11 07:16:33 UTC,2013_10_11_aa_Training01,,,12.65,-4.4,-0.5,20.1,305.0,304.5,,13.8,152.0,97.0,6.6,86.0,45.657005,13.70788,12.48,305.0,152.0,86.0,-4.4,-0.5,20.1,A2F,,M offshore D,2.4,,-11.1692870496654,DOWNWIND,starboard,41.9,65.0,41.9,65.0
2013-10-11 07:16:34 UTC,2013_10_11_aa_Training01,,,12.59,-6.8,-0.4,20.1,305.0,304.6,,13.8,150.0,97.0,6.9,85.0,45.6570633333333,13.7077783333333,12.22,298.0,150.0,85.0,-6.8,-0.4,20.1,A2F,,M offshore D,2.8,,-10.9032598336461,DOWNWIND,starboard,41.9,65.0,41.9,65.0
2013-10-11 07:16:35 UTC,2013_10_11_aa_Training01,,,12.54,-6.0,-0.5,20.1,307.0,306.5,,13.8,148.0,97.0,7.3,83.0,45.6570783333333,13.7077666666667,11.91,301.0,148.0,83.0,-6.0,-0.5,20.1,A2F,,M offshore D,2.2,,-10.6345231258016,DOWNWIND,starboard,41.9,65.0,41.9,65.0
1 date race_name leg_name leg_score boat_speed heel leeway rudder heading course depth tws twa twd aws awa latitude longitude sog cog abstwa absawa absheel absleeway absrudder foresail staysail mainsail forestay rake vmg status starboard_port rudder2 keelang absrudder2 abskeelang
2 2013-10-11 07:16:33 UTC 2013_10_11_aa_Training01 12.65 -4.4 -0.5 20.1 305.0 304.5 13.8 152.0 97.0 6.6 86.0 45.657005 13.70788 12.48 305.0 152.0 86.0 -4.4 -0.5 20.1 A2F M offshore D 2.4 -11.1692870496654 DOWNWIND starboard 41.9 65.0 41.9 65.0
3 2013-10-11 07:16:34 UTC 2013_10_11_aa_Training01 12.59 -6.8 -0.4 20.1 305.0 304.6 13.8 150.0 97.0 6.9 85.0 45.6570633333333 13.7077783333333 12.22 298.0 150.0 85.0 -6.8 -0.4 20.1 A2F M offshore D 2.8 -10.9032598336461 DOWNWIND starboard 41.9 65.0 41.9 65.0
4 2013-10-11 07:16:35 UTC 2013_10_11_aa_Training01 12.54 -6.0 -0.5 20.1 307.0 306.5 13.8 148.0 97.0 7.3 83.0 45.6570783333333 13.7077666666667 11.91 301.0 148.0 83.0 -6.0 -0.5 20.1 A2F M offshore D 2.2 -10.6345231258016 DOWNWIND starboard 41.9 65.0 41.9 65.0
@@ -0,0 +1,56 @@
package com.sap.sailing.domain.deckmanadapter.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import org.junit.Test;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapter;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapterFactory;
import com.sap.sailing.domain.deckmanadapter.Record;
import com.sap.sailing.domain.deckmanadapter.impl.FieldType;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.Wind;
public class TestDeckmanLogfileParsing {
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
@Test
public void testSimpleLogFileParsing() throws IOException, ParseException {
Reader r = new InputStreamReader(getClass().getClassLoader().getResourceAsStream("simpletest.csv"));
DeckmanAdapter adapter = DeckmanAdapterFactory.INSTANCE.createDeckmanAdapter();
Iterator<Record> recordIter = adapter.parseLogFile(r);
// date,race_name,leg_name,leg_score,boat_speed,heel,leeway,rudder,heading,course,depth,tws,twa,twd,aws,awa,latitude,longitude,sog,cog,abstwa,absawa,absheel,absleeway,absrudder,foresail,staysail,mainsail,forestay,rake,vmg,status,starboard_port,rudder2,keelang,absrudder2,abskeelang
// 2013-10-11 07:16:33 UTC,2013_10_11_aa_Training01,,,12.65,-4.4,-0.5,20.1,305.0,304.5,,13.8,152.0,97.0,6.6,86.0,45.657005,13.70788,12.48,305.0,152.0,86.0,-4.4,-0.5,20.1,A2F,,M offshore D,2.4,,-11.1692870496654,DOWNWIND,starboard,41.9,65.0,41.9,65.0
Record r1 = recordIter.next();
TimePoint r1TimePoint = r1.getTimePoint();
Position r1Position = r1.getPosition();
GPSFixMoving r1Fix = r1.getGpsFix();
Wind r1Wind = r1.getWind();
assertEquals(dateFormat.parse("2013-10-11 07:16:33 UTC"), r1TimePoint.asDate());
assertEquals(r1Fix.getPosition(), r1Position);
// SOG / COG: 12.48,305.0
assertEquals(12.48, r1Fix.getSpeed().getKnots(), 0.000001);
assertEquals(305.0, r1Fix.getSpeed().getBearing().getDegrees(), 0.000001);
assertEquals(45.657005, r1Position.getLatDeg(), 0.0000001);
assertEquals(13.70788, r1Position.getLngDeg(), 0.0000001);
assertEquals(13.8, r1Wind.getKnots(), 0.000001);
assertEquals(97.0, r1Wind.getBearing().getDegrees(), 0.000001);
assertEquals(12.65, Double.valueOf(r1.getField(FieldType.boat_speed)), 0.000001);
recordIter.next();
recordIter.next();
assertFalse(recordIter.hasNext());
}
}
+7
View File
@@ -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
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.sap.sailing.domain.deckmanadapter</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>
@@ -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
@@ -0,0 +1,3 @@
eclipse.preferences.version=1
pluginProject.extensions=false
resolve.requirebundle=false
@@ -0,0 +1,13 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Deckmanadapter
Bundle-SymbolicName: com.sap.sailing.domain.deckmanadapter
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.domain.common,
com.sap.sailing.domain.shared.android,
com.sap.sailing.server.trackfiles
Import-Package: org.osgi.framework
Bundle-Activator: com.sap.sailing.domain.deckmanadapter.impl.Activator
@@ -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.deckmanadapter</artifactId>
<packaging>eclipse-plugin</packaging>
</project>
@@ -0,0 +1,8 @@
package com.sap.sailing.domain.deckmanadapter;
import java.io.IOException;
import java.io.Reader;
public interface DeckmanAdapter {
LogFile parseLogFile(Reader r) throws IOException;
}
@@ -0,0 +1,9 @@
package com.sap.sailing.domain.deckmanadapter;
import com.sap.sailing.domain.deckmanadapter.impl.DeckmanAdapterFactoryImpl;
public interface DeckmanAdapterFactory {
DeckmanAdapterFactory INSTANCE = new DeckmanAdapterFactoryImpl();
DeckmanAdapter createDeckmanAdapter();
}
@@ -0,0 +1,6 @@
package com.sap.sailing.domain.deckmanadapter;
import java.util.Iterator;
public interface LogFile extends Iterator<Record> {
}
@@ -0,0 +1,78 @@
package com.sap.sailing.domain.deckmanadapter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Map;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.deckmanadapter.impl.FieldType;
import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.Positioned;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.tracking.impl.WindImpl;
public class Record implements Timed, Positioned {
private static final long serialVersionUID = -7939775022865795801L;
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private final TimePoint timePoint;
private final Position position;
private final GPSFixMoving gpsFix;
private final Wind wind;
private Map<FieldType, String> fieldsAsString;
public Record(Map<FieldType, String> fieldsAsString) throws ParseException {
this.fieldsAsString = fieldsAsString;
timePoint = new MillisecondsTimePoint(dateFormat.parse(this.fieldsAsString.get(FieldType.date)));
position = new DegreePosition(Double.valueOf(this.fieldsAsString.get(FieldType.latitude)),
Double.valueOf(this.fieldsAsString.get(FieldType.longitude)));
final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.sog)),
new DegreeBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.cog))));
wind = new WindImpl(position, timePoint, new KnotSpeedWithBearingImpl(Double.valueOf(this.fieldsAsString
.get(FieldType.tws)), new DegreeBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.twd)))));
gpsFix = new GPSFixMovingImpl(position, timePoint, speed);
}
public String getField(FieldType fieldType) {
return fieldsAsString.get(fieldType);
}
public Map<FieldType, String> getFieldsAsString() {
return fieldsAsString;
}
public void setFieldsAsString(Map<FieldType, String> fieldsAsString) {
this.fieldsAsString = fieldsAsString;
}
public TimePoint getTimePoint() {
return timePoint;
}
public GPSFixMoving getGpsFix() {
return gpsFix;
}
public Wind getWind() {
return wind;
}
@Override
public Position getPosition() {
return position;
}
}
@@ -0,0 +1,19 @@
package com.sap.sailing.domain.deckmanadapter.impl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import com.sap.sailing.server.trackfiles.common.GPSFixImporterRegistration;
public class Activator implements BundleActivator {
@Override
public void start(BundleContext context) throws Exception {
GPSFixImporterRegistration.register(new DeckmanGPSFixImporter(), context);
}
@Override
public void stop(BundleContext context) throws Exception {
}
}
@@ -0,0 +1,11 @@
package com.sap.sailing.domain.deckmanadapter.impl;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapter;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapterFactory;
public class DeckmanAdapterFactoryImpl implements DeckmanAdapterFactory {
@Override
public DeckmanAdapter createDeckmanAdapter() {
return new DeckmanAdapterImpl();
}
}
@@ -0,0 +1,15 @@
package com.sap.sailing.domain.deckmanadapter.impl;
import java.io.IOException;
import java.io.Reader;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapter;
import com.sap.sailing.domain.deckmanadapter.LogFile;
public class DeckmanAdapterImpl implements DeckmanAdapter {
@Override
public LogFile parseLogFile(Reader r) throws IOException {
return new LogFileImpl(r);
}
}
@@ -0,0 +1,54 @@
package com.sap.sailing.domain.deckmanadapter.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import com.sap.sailing.domain.deckmanadapter.DeckmanAdapter;
import com.sap.sailing.domain.deckmanadapter.Record;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier;
import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl;
import com.sap.sailing.domain.trackimport.FormatNotSupportedException;
import com.sap.sailing.domain.trackimport.GPSFixImporter;
import com.sap.sailing.domain.tracking.impl.GPSFixMovingImpl;
public class DeckmanGPSFixImporter implements GPSFixImporter {
@Override
public void importFixes(InputStream inputStream, Callback callback, boolean inferSpeedAndBearing, String sourceName)
throws FormatNotSupportedException, IOException {
DeckmanAdapter deckmanAdapter = DeckmanAdapterFactoryImpl.INSTANCE.createDeckmanAdapter();
TrackFileImportDeviceIdentifier device = new TrackFileImportDeviceIdentifierImpl(sourceName, getType() + "@" + new Date());
try {
for (Iterator<Record> i = deckmanAdapter.parseLogFile(new InputStreamReader(inputStream)); i.hasNext();) {
Record record = i.next();
callback.addFix(new GPSFixMovingImpl(record.getPosition(), record.getTimePoint(), record.getGpsFix().getSpeed()),
device);
}
} catch (RuntimeException e) {
if (e.getCause() != null) {
if (e.getCause() instanceof IOException) {
throw (IOException) e.getCause();
} else {
throw new FormatNotSupportedException("Error reading Deckman CSV file", e.getCause());
}
} else {
throw new FormatNotSupportedException("Error reading Deckman CSV file", e);
}
}
}
@Override
public Iterable<String> getSupportedFileExtensions() {
return Arrays.asList(new String[] { "csv" });
}
@Override
public String getType() {
return "Deckman";
}
}
@@ -0,0 +1,7 @@
package com.sap.sailing.domain.deckmanadapter.impl;
public enum FieldType {
date, race_name, leg_name, leg_score, boat_speed, heel, leeway, rudder, heading, course, depth,
tws, twa, twd, aws, awa, latitude, longitude, sog, cog, abstwa, absawa, absheel, absleeway, absrudder,
foresail, staysail, mainsail, forestay, rake, vmg, status, starboard_port, rudder2, keelang, absrudder2, abskeelang;
}
@@ -0,0 +1,66 @@
package com.sap.sailing.domain.deckmanadapter.impl;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.deckmanadapter.LogFile;
import com.sap.sailing.domain.deckmanadapter.Record;
/**
* A log file as produced by Deckman, in CSV format. The first line is expected to contain the column headers.
* Column headers not found in {@link FieldType} are ignored with a warning being logged.
*
* @author Axel Uhl (D043530)
*
*/
public class LogFileImpl implements LogFile {
private final FieldType[] fieldTypes;
private final BufferedReader bufferedReader;
private String nextLine;
/**
* Reads the header from the reader to initialize {@link #fieldTypes}. Afterwards, using the {@link #iterator},
* the records can be read one by one.
*/
public LogFileImpl(Reader r) throws IOException {
bufferedReader = new BufferedReader(r);
String header = bufferedReader.readLine();
String[] fieldNames = header.split(",");
fieldTypes = new FieldType[fieldNames.length];
for (int i=0; i<fieldNames.length; i++) {
fieldTypes[i] = FieldType.valueOf(fieldNames[i]);
}
nextLine = bufferedReader.readLine();
}
@Override
public boolean hasNext() {
return nextLine != null;
}
@Override
public Record next() {
final Map<FieldType, String> fieldsAsStrings = new HashMap<>();
final String[] fieldValues = nextLine.split(",");
try {
nextLine = bufferedReader.readLine();
for (int i = 0; i < fieldValues.length; i++) {
fieldsAsStrings.put(fieldTypes[i], fieldValues[i]);
}
final Record result = new Record(fieldsAsStrings);
return result;
} catch (ParseException | IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove() is not supported on a Deckman log file");
}
}
@@ -8,4 +8,5 @@ Bundle-Vendor: SAP
Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.junit4;bundle-version="4.8.2", Require-Bundle: org.junit4;bundle-version="4.8.2",
com.sap.sailing.domain.common, com.sap.sailing.domain.common,
com.sap.sailing.mongodb com.sap.sailing.mongodb,
com.sap.sse.common
@@ -12,11 +12,11 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.datatypes.AntHrm; import com.sap.sailing.domain.igtimiadapter.datatypes.AntHrm;
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix; import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
import com.sap.sailing.domain.igtimiadapter.datatypes.GpsLatLong; import com.sap.sailing.domain.igtimiadapter.datatypes.GpsLatLong;
import com.sap.sailing.domain.igtimiadapter.datatypes.GpsQualitySatCount; import com.sap.sailing.domain.igtimiadapter.datatypes.GpsQualitySatCount;
import com.sap.sse.common.Util;
public class FixFactoryTest { public class FixFactoryTest {
private static final String demoJson = "{\n"+ private static final String demoJson = "{\n"+
@@ -10,10 +10,10 @@ import org.apache.http.client.ClientProtocolException;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory; import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
import com.sap.sailing.mongodb.MongoDBConfiguration; import com.sap.sailing.mongodb.MongoDBConfiguration;
import com.sap.sailing.mongodb.MongoDBService; import com.sap.sailing.mongodb.MongoDBService;
import com.sap.sse.common.Util;
public class WebSocketServerListTest { public class WebSocketServerListTest {
@Test @Test
@@ -6,8 +6,8 @@ import static org.junit.Assert.assertTrue;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.mongodb.MongoDBConfiguration; import com.sap.sailing.mongodb.MongoDBConfiguration;
import com.sap.sse.common.Util;
public class IgtimiPersistenceTest { public class IgtimiPersistenceTest {
private MongoObjectFactory mongoObjectFactory; private MongoObjectFactory mongoObjectFactory;
@@ -21,7 +21,6 @@ import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow; import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
import com.sap.sailing.domain.igtimiadapter.Group; import com.sap.sailing.domain.igtimiadapter.Group;
import com.sap.sailing.domain.igtimiadapter.Permission; import com.sap.sailing.domain.igtimiadapter.Permission;
@@ -32,6 +31,7 @@ import com.sap.sailing.domain.igtimiadapter.datatypes.AWA;
import com.sap.sailing.domain.igtimiadapter.datatypes.AWS; import com.sap.sailing.domain.igtimiadapter.datatypes.AWS;
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix; import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
import com.sap.sailing.domain.igtimiadapter.datatypes.Type; import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
import com.sap.sse.common.Util;
public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection { public class BasicIgtimiAdapterTest extends AbstractTestWithIgtimiConnection {
@Test @Test
@@ -17,7 +17,6 @@ import org.junit.Test;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow; import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
import com.sap.sailing.domain.igtimiadapter.Permission; import com.sap.sailing.domain.igtimiadapter.Permission;
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix; import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
@@ -26,6 +25,7 @@ import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.GPSFixMoving; import com.sap.sailing.domain.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.Track; import com.sap.sailing.domain.tracking.Track;
import com.sap.sailing.domain.tracking.Wind; import com.sap.sailing.domain.tracking.Wind;
import com.sap.sse.common.Util;
/** /**
* Igtimi fixes come as isolated single fixes from separate sensors, and even if they are attached to the same device, * Igtimi fixes come as isolated single fixes from separate sensors, and even if they are attached to the same device,
@@ -9,10 +9,10 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix; import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
import com.sap.sailing.domain.igtimiadapter.datatypes.Type; import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
import com.sap.sailing.domain.igtimiadapter.impl.FixFactory; import com.sap.sailing.domain.igtimiadapter.impl.FixFactory;
import com.sap.sse.common.Util;
public class LatestDatumTest { public class LatestDatumTest {
@@ -30,7 +30,6 @@ import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.junit.Test; import org.junit.Test;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.Account; import com.sap.sailing.domain.igtimiadapter.Account;
import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver; import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver;
import com.sap.sailing.domain.igtimiadapter.Client; import com.sap.sailing.domain.igtimiadapter.Client;
@@ -43,6 +42,7 @@ import com.sap.sailing.domain.igtimiadapter.impl.IgtimiConnectionFactoryImpl;
import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory; import com.sap.sailing.domain.igtimiadapter.persistence.PersistenceFactory;
import com.sap.sailing.mongodb.MongoDBConfiguration; import com.sap.sailing.mongodb.MongoDBConfiguration;
import com.sap.sailing.mongodb.MongoDBService; import com.sap.sailing.mongodb.MongoDBService;
import com.sap.sse.common.Util;
public class WebSocketTest { public class WebSocketTest {
private static final Logger logger = Logger.getLogger(WebSocketTest.class.getName()); private static final Logger logger = Logger.getLogger(WebSocketTest.class.getName());
@@ -15,7 +15,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
com.sap.sailing.domain.igtimiadapter.persistence, com.sap.sailing.domain.igtimiadapter.persistence,
com.sap.sailing.domain.shared.android, com.sap.sailing.domain.shared.android,
com.sap.sailing.domain, com.sap.sailing.domain,
com.sap.sailing.declination com.sap.sailing.declination,
com.sap.sse.common
Import-Package: javax.ws.rs;version="1.1.1", Import-Package: javax.ws.rs;version="1.1.1",
javax.ws.rs.core;version="1.1.1", javax.ws.rs.core;version="1.1.1",
javax.ws.rs.ext;version="1.1.1", javax.ws.rs.ext;version="1.1.1",
@@ -15,10 +15,10 @@ import org.json.simple.JSONObject;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.Sensor; import com.sap.sailing.domain.igtimiadapter.Sensor;
import com.sap.sailing.domain.igtimiadapter.datatypes.Fix; import com.sap.sailing.domain.igtimiadapter.datatypes.Fix;
import com.sap.sailing.domain.igtimiadapter.datatypes.Type; import com.sap.sailing.domain.igtimiadapter.datatypes.Type;
import com.sap.sse.common.Util;
public class FixFactory { public class FixFactory {
private static final Logger logger = Logger.getLogger(FixFactory.class.getName()); private static final Logger logger = Logger.getLogger(FixFactory.class.getName());
@@ -20,7 +20,6 @@ import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.igtimiadapter.Account; import com.sap.sailing.domain.igtimiadapter.Account;
import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver; import com.sap.sailing.domain.igtimiadapter.BulkFixReceiver;
import com.sap.sailing.domain.igtimiadapter.DataAccessWindow; import com.sap.sailing.domain.igtimiadapter.DataAccessWindow;
@@ -41,6 +40,7 @@ import com.sap.sailing.domain.tracking.DynamicTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.DynamicTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackImpl;
import com.sap.sse.common.Util;
public class IgtimiConnectionImpl implements IgtimiConnection { public class IgtimiConnectionImpl implements IgtimiConnection {
private static final Logger logger = Logger.getLogger(IgtimiConnectionImpl.class.getName()); private static final Logger logger = Logger.getLogger(IgtimiConnectionImpl.class.getName());
@@ -11,7 +11,6 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.MillisecondsTimePoint; import com.sap.sailing.domain.common.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.igtimiadapter.Account; import com.sap.sailing.domain.igtimiadapter.Account;
import com.sap.sailing.domain.igtimiadapter.IgtimiConnection; import com.sap.sailing.domain.igtimiadapter.IgtimiConnection;
import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory; import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory;
@@ -20,12 +19,13 @@ import com.sap.sailing.domain.igtimiadapter.shared.IgtimiWindReceiver;
import com.sap.sailing.domain.tracking.AbstractWindTracker; import com.sap.sailing.domain.tracking.AbstractWindTracker;
import com.sap.sailing.domain.tracking.DynamicTrackedRace; import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.WindTracker; import com.sap.sailing.domain.tracking.WindTracker;
import com.sap.sse.common.Util;
public class IgtimiWindTracker extends AbstractWindTracker implements WindTracker { public class IgtimiWindTracker extends AbstractWindTracker implements WindTracker {
private static final Logger logger = Logger.getLogger(IgtimiWindTracker.class.getName()); private static final Logger logger = Logger.getLogger(IgtimiWindTracker.class.getName());
private static final int TIME_INTERVAL_TO_TRACK_BEFORE_RACE_START_MILLIS = 10*60*1000; // 10 minutes private static final int TIME_INTERVAL_TO_TRACK_BEFORE_RACE_START_MILLIS = 10*60*1000; // 10 minutes
private static final long TIME_INTERVAL_TO_TRACK_AFTER_END_OF_RACE_MILLIS = 60*60*1000; // 60 minutes private static final long TIME_INTERVAL_TO_TRACK_AFTER_END_OF_RACE_MILLIS = 60*60*1000; // 60 minutes
private final Map<LiveDataConnection, Pair<Iterable<String>, Account>> liveConnectionsAndDeviceSerialNumber; private final Map<LiveDataConnection, Util.Pair<Iterable<String>, Account>> liveConnectionsAndDeviceSerialNumber;
private final IgtimiWindTrackerFactory windTrackerFactory; private final IgtimiWindTrackerFactory windTrackerFactory;
private boolean stopping; private boolean stopping;
@@ -50,7 +50,7 @@ public class IgtimiWindTracker extends AbstractWindTracker implements WindTracke
IgtimiWindReceiver windReceiver = new IgtimiWindReceiver(devicesWeShouldListenTo); IgtimiWindReceiver windReceiver = new IgtimiWindReceiver(devicesWeShouldListenTo);
liveConnection.addListener(windReceiver); liveConnection.addListener(windReceiver);
windReceiver.addListener(new WindListenerSendingToTrackedRace(Collections.singleton(getTrackedRace()), windTrackerFactory)); windReceiver.addListener(new WindListenerSendingToTrackedRace(Collections.singleton(getTrackedRace()), windTrackerFactory));
liveConnectionsAndDeviceSerialNumber.put(liveConnection, new Pair<Iterable<String>, Account>(devicesWeShouldListenTo, account)); liveConnectionsAndDeviceSerialNumber.put(liveConnection, new Util.Pair<Iterable<String>, Account>(devicesWeShouldListenTo, account));
} }
} }
} catch (Exception e) { } catch (Exception e) {
@@ -114,7 +114,7 @@ public class IgtimiWindTracker extends AbstractWindTracker implements WindTracke
logger.info("Stopping Igtimi live connection "+ldc); logger.info("Stopping Igtimi live connection "+ldc);
ldc.stop(); ldc.stop();
} catch (Exception e) { } catch (Exception e) {
final Pair<Iterable<String>, Account> deviceSerialNumberAndAccount = liveConnectionsAndDeviceSerialNumber.get(ldc); final Util.Pair<Iterable<String>, Account> deviceSerialNumberAndAccount = liveConnectionsAndDeviceSerialNumber.get(ldc);
logger.log(Level.INFO, logger.log(Level.INFO,
"Exception trying to stop Igtimi live connection for wind receiver for race " "Exception trying to stop Igtimi live connection for wind receiver for race "
+ getTrackedRace().getRace() + " and device " + deviceSerialNumberAndAccount.getA() + getTrackedRace().getRace() + " and device " + deviceSerialNumberAndAccount.getA()
@@ -19,8 +19,6 @@ import com.sap.sailing.domain.common.Speed;
import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TimePoint; import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.scalablevalue.ScalableValue; import com.sap.sailing.domain.common.scalablevalue.ScalableValue;
import com.sap.sailing.domain.common.scalablevalue.impl.ScalableBearing; import com.sap.sailing.domain.common.scalablevalue.impl.ScalableBearing;
import com.sap.sailing.domain.common.scalablevalue.impl.ScalablePosition; import com.sap.sailing.domain.common.scalablevalue.impl.ScalablePosition;
@@ -45,6 +43,7 @@ import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindListener; import com.sap.sailing.domain.tracking.WindListener;
import com.sap.sailing.domain.tracking.impl.DynamicTrackImpl; import com.sap.sailing.domain.tracking.impl.DynamicTrackImpl;
import com.sap.sailing.domain.tracking.impl.WindImpl; import com.sap.sailing.domain.tracking.impl.WindImpl;
import com.sap.sse.common.Util;
/** /**
* Receives Igtimi {@link Fix}es and tries to generate a {@link Wind} object from each {@link AWS} fix. For this to * Receives Igtimi {@link Fix}es and tries to generate a {@link Wind} object from each {@link AWS} fix. For this to
@@ -180,14 +179,14 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
private Wind getWind(final TimePoint timePoint, String deviceSerialNumber) throws ClassNotFoundException, IOException, ParseException { private Wind getWind(final TimePoint timePoint, String deviceSerialNumber) throws ClassNotFoundException, IOException, ParseException {
final Wind result; final Wind result;
Pair<AWA, AWA> awaPair = getSurroundingFixes(getAwaTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<AWA, AWA> awaPair = getSurroundingFixes(getAwaTrack(deviceSerialNumber), timePoint);
Bearing awa = getAWA(timePoint, awaPair); Bearing awa = getAWA(timePoint, awaPair);
Pair<AWS, AWS> awsPair = getSurroundingFixes(getAwsTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<AWS, AWS> awsPair = getSurroundingFixes(getAwsTrack(deviceSerialNumber), timePoint);
Speed aws = getAWS(timePoint, awsPair); Speed aws = getAWS(timePoint, awsPair);
Pair<GpsLatLong, GpsLatLong> gpsPair = getSurroundingFixes(getGpsTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<GpsLatLong, GpsLatLong> gpsPair = getSurroundingFixes(getGpsTrack(deviceSerialNumber), timePoint);
Position pos = getPosition(timePoint, gpsPair); Position pos = getPosition(timePoint, gpsPair);
Pair<HDG, HDG> hdgPair = getSurroundingFixes(getHdgTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<HDG, HDG> hdgPair = getSurroundingFixes(getHdgTrack(deviceSerialNumber), timePoint);
Pair<HDGM, HDGM> hdgmPair = getSurroundingFixes(getHdgmTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<HDGM, HDGM> hdgmPair = getSurroundingFixes(getHdgmTrack(deviceSerialNumber), timePoint);
Bearing heading = getHeading(timePoint, hdgPair, hdgmPair, pos); Bearing heading = getHeading(timePoint, hdgPair, hdgmPair, pos);
if (awa != null && aws != null && pos != null && heading != null) { if (awa != null && aws != null && pos != null && heading != null) {
Bearing apparentWindDirection = heading.add(awa); Bearing apparentWindDirection = heading.add(awa);
@@ -215,9 +214,9 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
* So again, my personal preference would be to work with the data that should be the most accurate * So again, my personal preference would be to work with the data that should be the most accurate
* (COG/SOG) and consider algorithms that handle smoothing of that data best." * (COG/SOG) and consider algorithms that handle smoothing of that data best."
*/ */
Pair<SOG, SOG> sogPair = getSurroundingFixes(getSogTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<SOG, SOG> sogPair = getSurroundingFixes(getSogTrack(deviceSerialNumber), timePoint);
Speed sog = getSOG(timePoint, sogPair); Speed sog = getSOG(timePoint, sogPair);
Pair<COG, COG> cogPair = getSurroundingFixes(getCogTrack(deviceSerialNumber), timePoint); com.sap.sse.common.Util.Pair<COG, COG> cogPair = getSurroundingFixes(getCogTrack(deviceSerialNumber), timePoint);
Bearing cog = getCOG(timePoint, cogPair); Bearing cog = getCOG(timePoint, cogPair);
SpeedWithBearing sogCog = new KnotSpeedWithBearingImpl(sog.getKnots(), cog); SpeedWithBearing sogCog = new KnotSpeedWithBearingImpl(sog.getKnots(), cog);
SpeedWithBearing trueWindSpeedAndDirection = apparentWindSpeedWithDirection.add(sogCog); SpeedWithBearing trueWindSpeedAndDirection = apparentWindSpeedWithDirection.add(sogCog);
@@ -228,7 +227,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return result; return result;
} }
private Bearing getAWA(TimePoint timePoint, Pair<AWA, AWA> awaPair) { private Bearing getAWA(TimePoint timePoint, com.sap.sse.common.Util.Pair<AWA, AWA> awaPair) {
final Bearing awaFrom; final Bearing awaFrom;
if (awaPair.getA() == null) { if (awaPair.getA() == null) {
if (awaPair.getB() == null) { if (awaPair.getB() == null) {
@@ -248,7 +247,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return awaFrom == null ? null : awaFrom.reverse(); return awaFrom == null ? null : awaFrom.reverse();
} }
private Speed getAWS(TimePoint timePoint, Pair<AWS, AWS> awsPair) { private Speed getAWS(TimePoint timePoint, com.sap.sse.common.Util.Pair<AWS, AWS> awsPair) {
final Speed aws; final Speed aws;
if (awsPair.getA() == null) { if (awsPair.getA() == null) {
if (awsPair.getB() == null) { if (awsPair.getB() == null) {
@@ -268,7 +267,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return aws; return aws;
} }
private Speed getSOG(TimePoint timePoint, Pair<SOG, SOG> sogPair) { private Speed getSOG(TimePoint timePoint, com.sap.sse.common.Util.Pair<SOG, SOG> sogPair) {
final Speed sog; final Speed sog;
if (sogPair.getA() == null) { if (sogPair.getA() == null) {
if (sogPair.getB() == null) { if (sogPair.getB() == null) {
@@ -288,7 +287,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return sog; return sog;
} }
private Bearing getCOG(TimePoint timePoint, Pair<COG, COG> cogPair) { private Bearing getCOG(TimePoint timePoint, com.sap.sse.common.Util.Pair<COG, COG> cogPair) {
final Bearing sog; final Bearing sog;
if (cogPair.getA() == null) { if (cogPair.getA() == null) {
if (cogPair.getB() == null) { if (cogPair.getB() == null) {
@@ -308,7 +307,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return sog; return sog;
} }
private Position getPosition(TimePoint timePoint, Pair<GpsLatLong, GpsLatLong> gpsPair) { private Position getPosition(TimePoint timePoint, com.sap.sse.common.Util.Pair<GpsLatLong, GpsLatLong> gpsPair) {
final Position pos; final Position pos;
if (gpsPair.getA() == null) { if (gpsPair.getA() == null) {
if (gpsPair.getB() == null) { if (gpsPair.getB() == null) {
@@ -328,7 +327,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return pos; return pos;
} }
private Bearing getHDG(TimePoint timePoint, Pair<HDG, HDG> hdgPair) { private Bearing getHDG(TimePoint timePoint, com.sap.sse.common.Util.Pair<HDG, HDG> hdgPair) {
final Bearing hdg; final Bearing hdg;
if (hdgPair.getA() == null) { if (hdgPair.getA() == null) {
if (hdgPair.getB() == null) { if (hdgPair.getB() == null) {
@@ -348,7 +347,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return hdg; return hdg;
} }
private Bearing getHDGM(TimePoint timePoint, Pair<HDGM, HDGM> hdgmPair) { private Bearing getHDGM(TimePoint timePoint, com.sap.sse.common.Util.Pair<HDGM, HDGM> hdgmPair) {
final Bearing hdgm; final Bearing hdgm;
if (hdgmPair.getA() == null) { if (hdgmPair.getA() == null) {
if (hdgmPair.getB() == null) { if (hdgmPair.getB() == null) {
@@ -368,7 +367,7 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return hdgm; return hdgm;
} }
private Bearing getHeading(TimePoint timePoint, Pair<HDG, HDG> hdgPair, Pair<HDGM, HDGM> hdgmPair, Position position) throws ClassNotFoundException, IOException, ParseException { private Bearing getHeading(TimePoint timePoint, com.sap.sse.common.Util.Pair<HDG, HDG> hdgPair, com.sap.sse.common.Util.Pair<HDGM, HDGM> hdgmPair, Position position) throws ClassNotFoundException, IOException, ParseException {
final Bearing trueHeading; final Bearing trueHeading;
Bearing hdg = getHDG(timePoint, hdgPair); Bearing hdg = getHDG(timePoint, hdgPair);
if (hdg != null) { if (hdg != null) {
@@ -397,10 +396,10 @@ public class IgtimiWindReceiver implements BulkFixReceiver {
return acc; return acc;
} }
private <T extends Timed> Pair<T, T> getSurroundingFixes(Track<T> track, TimePoint timePoint) { private <T extends Timed> com.sap.sse.common.Util.Pair<T, T> getSurroundingFixes(Track<T> track, TimePoint timePoint) {
T left = track.getLastFixAtOrBefore(timePoint); T left = track.getLastFixAtOrBefore(timePoint);
T right = track.getFirstFixAtOrAfter(timePoint); T right = track.getFirstFixAtOrAfter(timePoint);
Pair<T, T> result = new Pair<>(left, right); com.sap.sse.common.Util.Pair<T, T> result = new com.sap.sse.common.Util.Pair<>(left, right);
return result; return result;
} }
Loaded 100 of 1496 files, more files were not shown because too many files have changed in this diff. Show more