Merge branch 'master' into bug5774

This commit is contained in:
Axel Uhl
2023-12-31 19:36:41 +01:00
331 changed files with 74256 additions and 7314 deletions
+1
View File
@@ -45,3 +45,4 @@ SailingServer (No Proxy) Chargebee.launch
## SAC Showcase, HDI Container
mta_archives/
db/.env
+1
View File
@@ -1,4 +1,5 @@
# SAP Sailing Analytics
The SAP Sailing Analytics platform as seen on [sapsailing.com](https://sapsailing.com)
Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAPs involvement in the sport has transformed the sailing experience by providing tools, which:
+2 -2
View File
@@ -50,9 +50,9 @@ allprojects {
ext {
// regular
buildTools = "30.0.3"
compileSdk = 31
compileSdk = 33
minSdk = 16
targetSdk = 31
targetSdk = 33
sourceCompatibilityVersion = JavaVersion.VERSION_1_8
targetCompatibilityVersion = JavaVersion.VERSION_1_8
-615
View File
@@ -1,615 +0,0 @@
<Macro ArchiveRewrite>
Use Rewrite 172.31.47.15 8888
</Macro>
<Macro Headers>
SetEnvIf Request_Method POST REQUEST_IS_POST=1
SetEnvIf Request_URI ^/gateway.* REQUEST_IS_POST=1
SetEnvIf Request_URI ^/gwt/RegattaOverview.* REQUEST_IS_POST=1
SetEnvIf Request_URI ^/?$ REQUEST_IS_POST=1
Header set Expires "Sun, 19 Nov 1978 05:00:00 GMT" env=REQUEST_IS_POST
Header set Cache-Control no-cache,no-store,must-revalidate,post-check=0,pre-check=0 env=REQUEST_IS_POST
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/json
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/gif
AddOutputFilterByType DEFLATE image/png
AddOutputFilterByType DEFLATE image/jpeg
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AllowEncodedSlashes NoDecode
</Macro>
<Macro Rewrite $IP $PORT>
ProxyPass "/" "http://$IP:$PORT/" nocanon
ProxyPassReverse / http://$IP:$PORT/
ProxyPreserveHost On
</Macro>
<Macro SSL>
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
</Macro>
<Macro Status $HOSTNAME $PATH>
<VirtualHost *:80>
ServerName $HOSTNAME
<Location /$PATH>
SetHandler server-status
Order deny,allow
Allow from all
</Location>
CustomLog logs/services_log combined
</VirtualHost>
</Macro>
<Macro Home $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Home-SSL $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Plain $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Plain-SSL $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro HardRedirect $HOSTNAME $TARGETURL>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RedirectMatch /(.*)$ $TARGETURL/
</VirtualHost>
</Macro>
<Macro LiveCenterWithLanguageSubstitution-ARCHIVE $HOSTNAME $EVENTUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?locale=de#/event/:eventId=$EVENTUUID" [L,NE]
RewriteCond %{REQUEST_URI} "^/en$"
RewriteRule ^(/en)?$ "http://$HOSTNAME/gwt/Home.html?locale=en#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro LiveCenterWithLanguageSubstitution $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?locale=de#/event/:eventId=$EVENTUUID" [L,NE]
RewriteCond %{REQUEST_URI} "^/en$"
RewriteRule ^(/en)?$ "http://$HOSTNAME/gwt/Home.html?locale=en#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro RibDashboard $HOSTNAME $LEADERBOARD_NAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/dashboards/RibDashboard.html?leaderboardName=$LEADERBOARD_NAME&%1" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro RegattaOverview-WithLeaderboard-WithLanguage $HOSTNAME $EVENTUUID $LANG $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/RegattaOverview.html?event=$EVENTUUID&locale=$LANG&enableLeaderboard=true" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro RegattaOverview-WithLanguage $HOSTNAME $EVENTUUID $LANG $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/RegattaOverview.html?event=$EVENTUUID&locale=$LANG" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro RegattaOverview-WithLeaderboard $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/RegattaOverview.html?event=$EVENTUUID&enableLeaderboard=true" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Event $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Event-SSL-Redirect $HOSTNAME $EVENTUUID $IP $PORT>
Use RedirectPermanentToSSL $HOSTNAME
Use Event-SSL $HOSTNAME $EVENTUUID $IP $PORT
</Macro>
<Macro RedirectPermanentToSSL $HOSTNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
</Macro>
<Macro Event-SSL $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Series $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?%1#/series/:seriesId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Series-SSL $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/series/:seriesId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro EventRegattaIntro $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?%1#/regatta/overview/:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Event-WithLanguage $HOSTNAME $EVENTUUID $LANG $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?locale=$LANG#EventPlace:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Event-ARCHIVE $HOSTNAME $EVENTUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro Event-ARCHIVE-SSL $HOSTNAME $EVENTUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro RegattaOverview $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/RegattaOverview.html?event=$EVENTUUID&%1" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Events $HOSTNAME $EVENTNAME $EXTRA $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/events/$EVENTNAME/$EXTRA" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Spectator-WithParam $HOSTNAME $GROUPNAME $EXTRA $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&$EXTRA" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Spectator-WithLanguage $HOSTNAME $GROUPNAME $LANG $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true&locale=$LANG" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Spectator $HOSTNAME $GROUPNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Leaderboard $HOSTNAME $GROUPNAME $NAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Leaderboard.html?name=$NAME&leaderboardGroupName=$GROUPNAME&showRaceDetails=true&root=leaderboardGroupPanel" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Leaderboard-WithParam $HOSTNAME $GROUPNAME $NAME $EXTRA $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Leaderboard.html?name=$NAME&leaderboardGroupName=$GROUPNAME&$EXTRA" [L,NE]
Use Rewrite-ARCHIVE1
</VirtualHost>
</Macro>
<Macro Spectator-ARCHIVE $HOSTNAME $GROUPNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro Spectator-ARCHIVE-SSL $HOSTNAME $GROUPNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro Spectator-ARCHIVE-WithParam $HOSTNAME $GROUPNAME $EXTRA>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&$EXTRA" [L,NE]
Use Rewrite 172.31.30.89 8888
</VirtualHost>
</Macro>
<Macro Home-ARCHIVE $HOSTNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Event-ARCHIVE $HOSTNAME $EVENTUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html#/event/:eventId=$EVENTUUID" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Series-ARCHIVE $HOSTNAME $SERIESUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/series/events/:leaderboardGroupId=$SERIESUUID" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Spectator-DEV $HOSTNAME $GROUPNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true" [L,NE]
Use Rewrite 172.31.18.218 8888
</VirtualHost>
</Macro>
<Macro Spectator-DEV-WithParam $HOSTNAME $GROUPNAME $EXTRA>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&$EXTRA" [L,NE]
Use Rewrite 172.31.18.218 8888
</VirtualHost>
</Macro>
<Macro Events-DEV $HOSTNAME $EVENTNAME $EXTRA>
<VirtualHost *:80>
ServerName $HOSTNAME
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "http://$HOSTNAME/events/$EVENTNAME/$EXTRA" [L,NE]
Use Rewrite 172.31.18.218 8888
</VirtualHost>
</Macro>
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# Use like this:
#
# echo "MY_SECRET_ENV_VAR=\\\"some secret that may even contain blanks or = or &\\\"" | ./addSecret
#
# Copy stdin to SECRETS_TO_ADD
SECRETS_TO_ADD=$( cat )
SERVERS_PATH=/home/sailing/servers
SECRETS_PATH=/root/secrets
SECRETS_IN_APP_PATH=configuration/secrets
FIND_ANALYTICS_SERVERS_SCRIPT="$( dirname ${0} )/findSailingAnalyticsServers"
for IP in $( ${FIND_ANALYTICS_SERVERS_SCRIPT} ); do
echo "Handling server with IP ${IP} ..."
ssh root@$IP 'echo "Appending '${SECRETS_TO_ADD}' to '${SECRETS_PATH}'"
echo "'${SECRETS_TO_ADD}'" >>'${SECRETS_PATH}'
echo "Server directories:"
for i in $( ls '${SERVERS_PATH}' ); do
echo "Appending to '${SERVERS_PATH}'/${i}/'${SECRETS_IN_APP_PATH}'"
echo "'${SECRETS_TO_ADD}'" >>'${SERVERS_PATH}'/${i}/'${SECRETS_IN_APP_PATH}'
done'
done
+1
View File
@@ -1 +1,2 @@
* * * * * export PATH=/bin:/usr/bin:/usr/local/bin; sleep $(( $RANDOM * 60 / 32768 )); update_authorized_keys_for_landscape_managers_if_changed $( cat /root/ssh-key-reader.token ) https://security-service.sapsailing.com /root 2>&1 >>/var/log/sailing.err
* * * * * export PATH=/bin:/usr/bin:/usr/local/bin; switchoverArchive.sh /etc/httpd/conf.d/000-macros.conf 2 9
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
aws ec2 describe-instances --filters Name=tag-key,Values=sailing-analytics-server | jq -r '.Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddresses[].Association.PublicIp'
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
echo "
"
BODY=$( cat )
echo "${BODY}" >/tmp/github-hook-body
REF=$( echo "${BODY}" | jq -r '.ref' )
PUSHER=$( echo "${BODY}" | jq -r '.pusher.email' )
logger -t github-cgi "ref ia $REF, pusher was $PUSHER"
# For testing:
#if [ "${PUSHER}" = "axel.uhl@sap.com" -a "${REF}" = "refs/heads/translation" ]; then
if [ "${PUSHER}" = "tmsatsls+github.tools.sap_service-tip-git@sap.com" -a "${REF}" = "refs/heads/translation" ]; then
echo "Identified a push to refs/heads/translation by ${PUSHER}."
echo "Fetching translation branch from github.tools.sap and pushing it to ssh://trac@sapsailing.com/home/trac/git"
logger -t github-cgi "fetching translation branch from github.tools.sap and pushing it to ssh://trac@sapsailing.com/home/trac/git"
cd /home/wiki/gitwiki
sudo -u wiki git fetch sapsailing translation:translation 2>&1
sudo -u wiki git push origin translation:translation 2>&1
else
echo "Either pusher was not tmsatsls+github.tools.sap_service-tip-git@sap.com or ref was not refs/heads/translation. Not triggering."
fi
+4 -277
View File
@@ -1,56 +1,10 @@
# ARCHIVE, based on i3.2xlarge, 64GB RAM and 1.9TB swap
#Define ARCHIVE_IP 172.31.24.90
#Define ARCHIVE_IP 172.31.24.90
#Define ARCHIVE_IP 172.31.20.25
#Define ARCHIVE_IP 172.31.16.178
#Define ARCHIVE_IP 172.31.25.130
#Define ARCHIVE_IP 172.31.25.246
#Define ARCHIVE_IP 172.31.24.192
#Define ARCHIVE_IP 172.31.22.16
# Failover (hanging in full gc):
#Define ARCHIVE_IP 172.31.29.138
# Production (hanging in full gc):
#Define ARCHIVE_IP 172.31.18.201
# New Candidate, not really ready...
#Define ARCHIVE_IP 172.31.28.255
#Define ARCHIVE_IP 172.31.21.159
#Define ARCHIVE_IP 172.31.19.41
#Define ARCHIVE_IP 172.31.29.206
#Define ARCHIVE_IP 172.31.25.194
#Define ARCHIVE_IP 172.31.17.130
#Define ARCHIVE_IP 172.31.20.156
#Define ARCHIVE_IP 172.31.28.168
#Define ARCHIVE_IP 172.31.23.135
#Define ARCHIVE_IP 172.31.16.245
#Define ARCHIVE_IP 172.31.29.3
#Define ARCHIVE_IP 172.31.20.157
#Define ARCHIVE_IP 172.31.17.35
#Define ARCHIVE_IP 172.31.28.236
#Define ARCHIVE_IP 172.31.16.207
#Define ARCHIVE_IP 172.31.26.1
#Define ARCHIVE_IP 172.31.21.3
#Define ARCHIVE_IP 172.31.28.73
#Define ARCHIVE_IP 172.31.17.113
#Define ARCHIVE_IP 172.31.30.211
#Define ARCHIVE_IP 172.31.20.222
#Define ARCHIVE_IP 172.31.21.139
#Define ARCHIVE_IP 172.31.23.47
#Define ARCHIVE_IP 172.31.20.62
#Define ARCHIVE_IP 172.31.20.131
#Define ARCHIVE_IP 172.31.47.208
#Define ARCHIVE_IP 172.31.41.14
#Define ARCHIVE_IP 172.31.34.59
#Define ARCHIVE_IP 172.31.46.41
#Define ARCHIVE_IP 172.31.44.232
#Define ARCHIVE_IP 172.31.46.28
#Define ARCHIVE_IP 172.31.45.169
#Define ARCHIVE_IP 172.31.45.31
#Define ARCHIVE_IP 172.31.44.175
#Define ARCHIVE_IP 172.31.36.140
Define ARCHIVE_IP 172.31.46.176
Define ARCHIVE_IP 172.31.40.242
Define ARCHIVE_FAILOVER_IP 172.31.40.242
Define PRODUCTION_ARCHIVE ${ARCHIVE_IP}
<Macro ArchiveRewrite>
Use Rewrite ${ARCHIVE_IP} 8888
Use Rewrite ${PRODUCTION_ARCHIVE} 8888
</Macro>
<Macro Headers>
@@ -197,27 +151,6 @@ Define ARCHIVE_IP 172.31.46.176
ProxyPreserveHost On
</Macro>
<Macro SSL>
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
</Macro>
<Macro SSL-sail-insight>
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/sail-insight.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sail-insight.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/sail-insight.com/fullchain.pem
</Macro>
<Macro SSL-Tennis>
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/star_saptennis_com.crt
SSLCertificateKeyFile /etc/pki/tls/private/star_saptennis_com_2022.key
SSLCertificateChainFile /etc/pki/tls/certs/saptennis_chain_2022.crt
</Macro>
<Macro Status $HOSTNAME $PATH>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -230,19 +163,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Status-SSL $HOSTNAME $PATH>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
<Location /$PATH>
SetHandler server-status
Order deny,allow
Allow from all
</Location>
CustomLog logs/services_log combined
</VirtualHost>
</Macro>
<Macro Home-ARCHIVE $HOSTNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -253,50 +173,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Home-ARCHIVE-SSL-Redirect $HOSTNAME>
Use RedirectPermanentToSSL $HOSTNAME
Use Home-ARCHIVE-SSL $HOSTNAME
</Macro>
<Macro Tennis-With-SSL $HOSTNAME $IP $PORT $PATH>
<VirtualHost *:443>
ServerName $HOSTNAME
Use Headers-Tennis
Use SSL-Tennis
RewriteEngine on
RewriteRule ^(/)?$ https://$HOSTNAME/$PATH [L,NE]
RewriteRule ^/(.*)$ http://$IP:$PORT/$1 [P,L]
ProxyPassReverse / http://$IP:$PORT/
ProxyPreserveHost On
CustomLog logs/tennis_log combined
</VirtualHost>
</Macro>
<Macro Tennis-With-SSL-Plain $HOSTNAME $IP $PORT>
<VirtualHost *:443>
ServerName $HOSTNAME
Use Headers-Tennis
Use SSL-Tennis
RewriteEngine on
RewriteRule ^/(.*)$ http://$IP:$PORT/$1 [P,L]
ProxyPassReverse / http://$IP:$PORT/
ProxyPreserveHost On
CustomLog logs/tennis_log combined
</VirtualHost>
</Macro>
<Macro Home-ARCHIVE-SSL $HOSTNAME>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
# LogLevel alert rewrite:trace5
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Home $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -308,34 +184,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Home-SSL-Redirect $HOSTNAME $IP $PORT>
Use RedirectPermanentToSSL $HOSTNAME
Use Home-SSL $HOSTNAME $IP $PORT
</Macro>
<Macro Tennis-SSL-Redirect $HOSTNAME>
Use RedirectPermanentToSSL $HOSTNAME
</Macro>
<Macro Tennis-SSL-Redirect-WWW $HOSTNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://www.$HOSTNAME/
CustomLog logs/tennis_log combined
</VirtualHost>
</Macro>
<Macro Home-SSL $HOSTNAME $IP $PORT>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Plain $HOSTNAME $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -355,28 +203,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro RedirectPermanentToSSL $HOSTNAME>
<VirtualHost *:80>
ServerName $HOSTNAME
RedirectPermanent / https://$HOSTNAME/
</VirtualHost>
</Macro>
<Macro Plain-SSL-Redirect $HOSTNAME $IP $PORT>
Use RedirectPermanentToSSL $HOSTNAME
Use Plain-SSL $HOSTNAME $IP $PORT
</Macro>
<Macro Plain-SSL $HOSTNAME $IP $PORT>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro HardRedirect $HOSTNAME $TARGETURL>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -491,50 +317,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Event-SSL-Redirect $HOSTNAME $EVENTUUID $IP $PORT>
Use RedirectPermanentToSSL $HOSTNAME
Use Event-SSL $HOSTNAME $EVENTUUID $IP $PORT
</Macro>
<Macro Event-SSL $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Series-SSL $HOSTNAME $SERIESUUID $IP $PORT>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/series/events/:seriesId=$SERIESUUID" [L,NE]
Use Rewrite $IP $PORT
</VirtualHost>
</Macro>
<Macro Series-SSL-Redirect $HOSTNAME $EVENTUUID $IP $PORT>
Use RedirectPermanentToSSL $HOSTNAME
Use Series-SSL $HOSTNAME $EVENTUUID $IP $PORT
</Macro>
<Macro Series $HOSTNAME $SERIESUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -581,11 +363,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Series-ARCHIVE-SSL-Redirect $HOSTNAME $SERIESUUID>
Use RedirectPermanentToSSL $HOSTNAME
Use Series-ARCHIVE-SSL $HOSTNAME $SERIESUUID
</Macro>
<Macro Series-ARCHIVE $HOSTNAME $SERIESUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -599,25 +376,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Series-ARCHIVE-SSL $HOSTNAME $SERIESUUID>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/series/events/:leaderboardGroupId=$SERIESUUID" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Event-ARCHIVE-SSL-Redirect $HOSTNAME $EVENTUUID>
Use RedirectPermanentToSSL $HOSTNAME
Use Event-ARCHIVE-SSL $HOSTNAME $EVENTUUID
</Macro>
<Macro Event-ARCHIVE $HOSTNAME $EVENTUUID>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -631,20 +389,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Event-ARCHIVE-SSL $HOSTNAME $EVENTUUID>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
# The following matches the query string and captures it in group %1 for the RewriteRule to use before the fragment
RewriteCond %{QUERY_STRING} "^(.*)$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Home.html?%1#/event/:eventId=$EVENTUUID" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro RegattaOverview $HOSTNAME $EVENTUUID $IP $PORT>
<VirtualHost *:80>
ServerName $HOSTNAME
@@ -763,23 +507,6 @@ Define ARCHIVE_IP 172.31.46.176
</VirtualHost>
</Macro>
<Macro Spectator-ARCHIVE-SSL-Redirect $HOSTNAME $GROUPNAME>
Use RedirectPermanentToSSL $HOSTNAME
Use Spectator-ARCHIVE-SSL $HOSTNAME "$GROUPNAME"
</Macro>
<Macro Spectator-ARCHIVE-SSL $HOSTNAME $GROUPNAME>
<VirtualHost *:443>
ServerName $HOSTNAME
Use SSL
Use Headers
RewriteEngine on
RewriteCond %{REQUEST_URI} "^(/)?$"
RewriteRule ^(/)?$ "https://$HOSTNAME/gwt/Spectator.html?leaderboardGroupName=$GROUPNAME&showRaceDetails=true" [L,NE]
Use ArchiveRewrite
</VirtualHost>
</Macro>
<Macro Spectator-ARCHIVE-WithParam $HOSTNAME $GROUPNAME $EXTRA>
<VirtualHost *:80>
ServerName $HOSTNAME
-41
View File
@@ -34,16 +34,6 @@
# WWW as the default virtual host for HTTPS access to port 443 because it's listed as the first on :443
Use Home-ARCHIVE www.sapsailing.com
<VirtualHost *:443>
# a rewrite rule to map sapsailing.com to www.sapsailing.com for HTTPS requests
ServerName sapsailing.com
Use SSL
RewriteEngine on
RewriteRule ^.*$ https://www.sapsailing.com%{REQUEST_URI} [L,R=301,NE]
CustomLog logs/access_log sapsailing_httpd_redirect_combined env=!original_client_ip
CustomLog logs/access_log sapsailing_httpd_redirect_combined_first_forwarded_for_ip env=original_client_ip
</VirtualHost>
<VirtualHost *:80>
ServerName jobs.sapsailing.com
CustomLog logs/jobs_log combined env=!original_client_ip
@@ -57,27 +47,6 @@ Use Home-ARCHIVE www.sapsailing.com
</Directory>
</VirtualHost>
# sail-insight.com
<VirtualHost *:80>
ServerName sail-insight.com
ServerAlias www.sail-insight.com
RedirectPermanent / https://sail-insight.com/
</VirtualHost>
<VirtualHost *:443>
ServerName sail-insight.com
ServerAlias www.sail-insight.com
Use SSL-sail-insight
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
Alias / /home/trac/sail-insight-website/
<Directory /home/trac/sail-insight-website>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
# P2 repository
<VirtualHost *:80>
ServerName p2.sapsailing.com
@@ -160,13 +129,3 @@ Use Home-ARCHIVE www.sapsailing.com
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
</VirtualHost>
<VirtualHost *:80>
ServerName hudson.sapsailing.com
RewriteEngine on
# LogLevel alert rewrite:trace5
RewriteRule ^/(.*)$ http://172.31.28.12:8080/$1 [P]
ProxyPassReverse / http://172.31.28.12:8080/
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
</VirtualHost>
+2 -2
View File
@@ -21,8 +21,8 @@ Use Status 172.31.42.171 internal-server-status
Use Status 127.0.0.1 internal-server-status
# Uncomment the following and update the internal IP to what your Archive server candidate is
Use Plain archive-failover.sapsailing.com 172.31.44.175 8888
Use Plain archive-candidate.sapsailing.com 172.31.46.176 8888
Use Plain archive-failover.sapsailing.com 172.31.40.12 8888
Use Plain archive-candidate.sapsailing.com 172.31.46.203 8888
Use Plain my-master.sapsailing.com 172.31.24.34 8888
+8 -3
View File
@@ -3,6 +3,7 @@ ServerName git.sapsailing.com
SetEnv GIT_PROJECT_ROOT /home/trac/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
ScriptAlias /hooks/ /var/www/cgi-bin/
<Location /git/ >
Options +ExecCGI
@@ -44,7 +45,7 @@ SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:SSLv3:!RC4:!MD5:+HIGH
# pass phrase. Note that a kill -HUP will prompt again. A new
# certificate can be generated using the genkey(1) command.
#SSLCertificateFile /etc/pki/tls/certs/ca.crt
SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
#SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
# Server Private Key:
# If the key is not combined with the certificate, use this
@@ -52,7 +53,7 @@ SSLCertificateFile /etc/pki/tls/certs/star_sapsailing_com.crt
# you've both a RSA and a DSA private key you can configure
# both in parallel (to also allow the use of DSA ciphers, etc.)
#SSLCertificateKeyFile /etc/pki/tls/private/ca.key
SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
#SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
# Server Certificate Chain:
# Point SSLCertificateChainFile at a file containing the
@@ -62,7 +63,7 @@ SSLCertificateKeyFile /etc/pki/tls/private/star_sapsailing_com.key
# when the CA certificates are directly appended to the server
# certificate for convinience.
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
# Certificate Authority (CA):
# Set the CA certificate verification path where to find CA
@@ -127,6 +128,10 @@ SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
AllowOverride None
Options FollowSymLinks
Order allow,deny
Allow from all
</Directory>
# SSL Protocol Adjustments:
-261
View File
@@ -1,261 +0,0 @@
# XXX: Move to saptennis.com
Use Tennis-Plain tennis-analytics.sapsailing.com 54.234.185.60 8888
Use Tennis-Plain mobile.tennis-analytics.sapsailing.com 54.234.185.60 8888
Use Tennis-Plain api.tennis-analytics.sapsailing.com 54.234.185.60 8888
Use Tennis-Plain dev.tennis-analytics.sapsailing.com 34.242.130.58 8888
# XXX: Move these to SSL
Use Tennis-Plain saptennis.com 54.234.185.60 8888
Use Tennis-Plain draw.saptennis.com 54.234.185.60 8888
Use Tennis-Plain groupedit.saptennis.com 34.253.178.230 8888
Use Tennis-With-SSL-Plain dev.saptennis.com 34.254.157.195 8888
Use Tennis-With-SSL-Plain api.saptennis.com 54.234.185.60 8888
Use Tennis-With-SSL-Plain tpc.saptennis.com 34.242.18.47 8888
Use Tennis-With-SSL media.saptennis.com 34.240.66.211 8888 "media/mediaportal"
Use Tennis-With-SSL-Plain apps.saptennis.com 34.241.245.147 8888
# Monitoring
Use Tennis-With-SSL-Plain monitor.saptennis.com 172.31.45.221 3000
Use Tennis-Plain hellgate.saptennis.com 172.31.45.221 2003
# Piwik
Use Tennis-With-SSL-Plain analytics.saptennis.com 172.31.45.221 8999
Use Tennis-SSL-Redirect media.saptennis.com
<VirtualHost *:80>
ServerName hellgate.saptennis.com
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass http://172.31.45.221:2003/
ProxyPassReverse http://172.31.45.221:2003/
</Location>
</VirtualHost>
<VirtualHost *:443>
ServerName tpc.wta-playerzone.com
Use Headers
SSLEngine On
SSLCertificateFile /etc/pki/tls/certs/tpc.wta-playerzone.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/tpc.wta-playerzone.com.key
RewriteEngine on
RewriteRule ^(/)?$ "https://tpc.wta-playerzone.com/tpc/ui5" [L,NE]
Use Rewrite 34.242.18.47 8888
<IfModule mod_mime.c>
AddType text/css .css
AddType application/x-javascript .js
AddType text/x-component .htc
AddType text/html .html .htm
AddType text/richtext .rtf .rtx
AddType image/svg+xml .svg .svgz
AddType text/plain .txt
AddType text/xsd .xsd
AddType text/xsl .xsl
AddType text/xml .xml
AddType video/asf .asf .asx .wax .wmv .wmx
AddType video/avi .avi
AddType image/bmp .bmp
AddType application/java .class
AddType video/divx .divx
AddType application/msword .doc .docx
AddType application/vnd.ms-fontobject .eot
AddType application/x-msdownload .exe
AddType image/gif .gif
AddType application/x-gzip .gz .gzip
AddType image/x-icon .ico
AddType image/jpeg .jpg .jpeg .jpe
AddType application/vnd.ms-access .mdb
AddType audio/midi .mid .midi
AddType video/quicktime .mov .qt
AddType audio/mpeg .mp3 .m4a
AddType video/mp4 .mp4 .m4v
AddType video/mpeg .mpeg .mpg .mpe
AddType application/vnd.ms-project .mpp
AddType application/x-font-otf .otf
AddType application/vnd.oasis.opendocument.database .odb
AddType application/vnd.oasis.opendocument.chart .odc
AddType application/vnd.oasis.opendocument.formula .odf
AddType application/vnd.oasis.opendocument.graphics .odg
AddType application/vnd.oasis.opendocument.presentation .odp
AddType application/vnd.oasis.opendocument.spreadsheet .ods
AddType application/vnd.oasis.opendocument.text .odt
AddType audio/ogg .ogg
AddType application/pdf .pdf
AddType image/png .png
AddType application/vnd.ms-powerpoint .pot .pps .ppt .pptx
AddType audio/x-realaudio .ra .ram
AddType application/x-shockwave-flash .swf
AddType application/x-tar .tar
AddType image/tiff .tif .tiff
AddType application/x-font-ttf .ttf .ttc
AddType audio/wav .wav
AddType audio/wma .wma
AddType application/vnd.ms-write .wri
AddType application/vnd.ms-excel .xla .xls .xlsx .xlt .xlw
AddType application/zip .zip
</IfModule>
<IfModule mod_deflate.c>
# Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
<IfModule filter_module>
# HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/html'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/css'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/plain'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/x-component'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/javascript'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/json'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xhtml+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/rss+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/atom+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/vnd.ms-fontobject'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/svg+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/x-icon'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/gif'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/jpeg'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/png'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/x-font-ttf'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$font/opentype'"
FilterChain COMPRESS
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>
<IfModule !mod_filter.c>
# Legacy versions of Apache
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>
</IfModule>
</VirtualHost>
<VirtualHost *:80>
ServerName tpc.wta-playerzone.com
Use Headers
RewriteEngine on
RewriteRule ^(/)?$ "http://tpc.wta-playerzone.com/tpc/ui5" [L,NE]
Use Rewrite 34.242.18.47 8888
<IfModule mod_mime.c>
AddType text/css .css
AddType application/x-javascript .js
AddType text/x-component .htc
AddType text/html .html .htm
AddType text/richtext .rtf .rtx
AddType image/svg+xml .svg .svgz
AddType text/plain .txt
AddType text/xsd .xsd
AddType text/xsl .xsl
AddType text/xml .xml
AddType video/asf .asf .asx .wax .wmv .wmx
AddType video/avi .avi
AddType image/bmp .bmp
AddType application/java .class
AddType video/divx .divx
AddType application/msword .doc .docx
AddType application/vnd.ms-fontobject .eot
AddType application/x-msdownload .exe
AddType image/gif .gif
AddType application/x-gzip .gz .gzip
AddType image/x-icon .ico
AddType image/jpeg .jpg .jpeg .jpe
AddType application/vnd.ms-access .mdb
AddType audio/midi .mid .midi
AddType video/quicktime .mov .qt
AddType audio/mpeg .mp3 .m4a
AddType video/mp4 .mp4 .m4v
AddType video/mpeg .mpeg .mpg .mpe
AddType application/vnd.ms-project .mpp
AddType application/x-font-otf .otf
AddType application/vnd.oasis.opendocument.database .odb
AddType application/vnd.oasis.opendocument.chart .odc
AddType application/vnd.oasis.opendocument.formula .odf
AddType application/vnd.oasis.opendocument.graphics .odg
AddType application/vnd.oasis.opendocument.presentation .odp
AddType application/vnd.oasis.opendocument.spreadsheet .ods
AddType application/vnd.oasis.opendocument.text .odt
AddType audio/ogg .ogg
AddType application/pdf .pdf
AddType image/png .png
AddType application/vnd.ms-powerpoint .pot .pps .ppt .pptx
AddType audio/x-realaudio .ra .ram
AddType application/x-shockwave-flash .swf
AddType application/x-tar .tar
AddType image/tiff .tif .tiff
AddType application/x-font-ttf .ttf .ttc
AddType audio/wav .wav
AddType audio/wma .wma
AddType application/vnd.ms-write .wri
AddType application/vnd.ms-excel .xla .xls .xlsx .xlt .xlw
AddType application/zip .zip
</IfModule>
<IfModule mod_deflate.c>
# Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
</IfModule>
</IfModule>
<IfModule filter_module>
# HTML, TXT, CSS, JavaScript, JSON, XML, HTC:
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/html'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/css'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/plain'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$text/x-component'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/javascript'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/json'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/xhtml+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/rss+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/atom+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/vnd.ms-fontobject'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/svg+xml'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/x-icon'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/gif'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/jpeg'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$image/png'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$application/x-font-ttf'"
FilterProvider COMPRESS DEFLATE "%{Content_Type} = '$font/opentype'"
FilterChain COMPRESS
FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no
</IfModule>
<IfModule !mod_filter.c>
# Legacy versions of Apache
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype
</IfModule>
</IfModule>
</VirtualHost>
@@ -0,0 +1,28 @@
# sail-insight.com
<VirtualHost *:80>
ServerName sail-insight.com
ServerAlias www.sail-insight.com
RedirectPermanent / https://sail-insight.com/
</VirtualHost>
<Macro SSL-sail-insight>
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/sail-insight.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sail-insight.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/sail-insight.com/fullchain.pem
</Macro>
<VirtualHost *:443>
ServerName sail-insight.com
ServerAlias www.sail-insight.com
Use SSL-sail-insight
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
Alias / /home/trac/sail-insight-website/
<Directory /home/trac/sail-insight-website>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
@@ -0,0 +1 @@
Use Event-ARCHIVE 49erEuros2023.sapsailing.com ebe42774-76e1-4f9d-8e3a-829cc263088e
-1
View File
@@ -25,7 +25,6 @@ Alias /unique-visitors/ "/var/log/old/cache/unique-ips-per-referrer/stats/"
#
<VirtualHost *:80>
ServerName awstats.sapsailing.com
Use SSL
CustomLog logs/awstats_access_log combined
ErrorLog logs/awstats_error_log
@@ -0,0 +1 @@
Use Home-ARCHIVE bundesliga2023.sapsailing.com
@@ -0,0 +1 @@
Use Event-ARCHIVE cnr2023.sapsailing.com 4e2b2383-ec2c-4a12-ae1d-61ba170b1b6f
@@ -0,0 +1 @@
Use Home-ARCHIVE danishleague2023.sapsailing.com
@@ -0,0 +1 @@
Use Home-ARCHIVE finalregionalny2023.sapsailing.com
@@ -0,0 +1 @@
Use Event-ARCHIVE frenchleague2023.sapsailing.com 289ee506-e8de-42e3-b726-f339fdba3b31
@@ -0,0 +1 @@
Use Home-ARCHIVE norwegianleague2023.sapsailing.com
@@ -1,49 +0,0 @@
LoadModule perl_module modules/mod_perl.so
#
# Mod_perl incorporates a Perl interpreter into the Apache web server,
# so that the Apache web server can directly execute Perl code.
# Mod_perl links the Perl runtime library into the Apache web server
# and provides an object-oriented Perl interface for Apache's C
# language API. The end result is a quicker CGI script turnaround
# process, since no external Perl interpreter has to be started.
#
# Uncomment this line to globally enable warnings, which will be
# written to the server's error log. Warnings should be enabled
# during the development process, but should be disabled on a
# production server as they affect performance.
#
#PerlSwitches -w
# Uncomment this line to enable taint checking globally. When Perl is
# running in taint mode various checks are performed to reduce the
# risk of insecure data being passed to a subshell or being used to
# modify the filesystem. Unfortunately many Perl modules are not
# taint-safe, so you should exercise care before enabling it on a
# production server.
#
#PerlSwitches -T
# This will allow execution of mod_perl to compile your scripts to
# subroutines which it will execute directly, avoiding the costly
# compile process for most requests.
#
#Alias /perl /var/www/perl
#<Directory /var/www/perl>
# SetHandler perl-script
# PerlResponseHandler ModPerl::Registry
# PerlOptions +ParseHeaders
# Options +ExecCGI
#</Directory>
# This will allow remote server configuration reports, with the URL of
# http://servername/perl-status
# Change the ".example.com" to match your domain to enable.
#
#<Location /perl-status>
# SetHandler perl-script
# PerlResponseHandler Apache2::Status
# Order deny,allow
# Deny from all
# Allow from .example.com
#</Location>
@@ -0,0 +1 @@
Use Home-ARCHIVE scl2023.sapsailing.com
@@ -0,0 +1 @@
Use Home-ARCHIVE trojmiejskaliga2023.sapsailing.com
@@ -1,6 +1,9 @@
<VirtualHost *:443>
# The problem with this is that Wordpress seems to redirect to https,
# leading to an endless redirect loop when the ALB then receives the
# https request, does the SSL handling and forwards as an http request
# to here again...
<VirtualHost *:80>
ServerName blog.sapsailing.com
Use SSL
CustomLog logs/blog_log combined
DocumentRoot /home/wordpress/wordpress
<Directory /home/wordpress/wordpress>
@@ -0,0 +1 @@
Use Home-ARCHIVE wow2023.sapsailing.com
+3 -3
View File
@@ -55,12 +55,12 @@ clean_httpd_logs() {
echo "Clearing httpd logs" >>/var/log/sailing.err
service httpd stop
rm -rf /var/log/httpd/*
rm /etc/httpd/conf.d/001-internals.conf
rm -f /etc/httpd/conf.d/001-internals.conf
}
clean_startup_logs() {
echo "Clearing bootstrap logs" >>/var/log/sailing.err
rm /var/log/sailing*
rm -f /var/log/sailing*
# Ensure that upon the next boot the reboot indicator is not present, indicating that it's the first boot
rm "${REBOOT_INDICATOR}"
}
@@ -95,7 +95,7 @@ finalize() {
else
# Only clean ${LOGON_USER_HOME}/.ssh directory and /tmp/image-upgrade-finished if the next step is shutdown / image creation
clean_root_ssh_dir_and_tmp
rm /var/log/sailing.err
rm -f /var/log/sailing.err
shutdown -h now &
fi
}
+114
View File
@@ -0,0 +1,114 @@
#!/bin/bash
# Purpose: Script is used to switch to the failover archive if the primary is unhealthy, by altering the macros
# file and then reloading Httpd.
# Crontab for every minute: * * * * * /path/to/switchoverArchive.sh
help() {
echo "$0 PATH_TO_HTTPD_MACROS_FILE TIMEOUT_FIRST_CURL_SECONDS TIMEOUT_SECOND_CURL_SECONDS"
echo ""
echo "Script used to automatically update the archive location (to the failover) in httpd if the primary is down."
echo "Pass in the path to the macros file containing the archive definitions;"
echo "the timeout of the first curl check in seconds; and the timeout of the second curl check, also in seconds."
echo "Make sure the combined time taken is not longer than the crontab."
exit 2
}
# $# is the number of arguments
if [ $# -eq 0 ]; then
help
fi
#The names of the variables in the macros file.
ARCHIVE_IP_NAME="ARCHIVE_IP"
ARCHIVE_FAILOVER_IP_NAME="ARCHIVE_FAILOVER_IP"
PRODUCTION_ARCHIVE_NAME="PRODUCTION_ARCHIVE"
ARCHIVE_PORT=8888
MACROS_PATH=$1
# The amount of time (in seconds) that must have elapsed, since the last httpd macros email, before notifying operators again.
TIME_CHECK_SECONDS=$((15*60))
# Connection timeouts for curl requests (the time waited for a connection to be established). The second should be longer
# as we want to be confident the main archive is in fact "down" before switching.
TIMEOUT1_IN_SECONDS=$2
TIMEOUT2_IN_SECONDS=$3
CACHE_LOCATION="/var/cache/lastIncorrectMacroUnixTime"
# The following line checks if all the strings in "search" are present at the beginning of their own line. Note: grep uses BRE by default,
# so the plus symbol must be escaped to refer to "one or more" of the previous character.
for i in "^Define ${PRODUCTION_ARCHIVE_NAME}\>" \
"^Define ${ARCHIVE_IP_NAME} [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$" \
"^Define ${ARCHIVE_FAILOVER_IP_NAME} [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$"
do
if ! grep -q "${i}" "${MACROS_PATH}"; then
currentUnixTime=$(date +"%s")
if [[ ! -f ${CACHE_LOCATION} || $((currentUnixTime - $(cat "${CACHE_LOCATION}") )) -gt "$TIME_CHECK_SECONDS" ]]; then
date +"%s" > "${CACHE_LOCATION}"
echo "Macros file does not contain proper definitions for the archive and failover IPs. Expression ${i} not matched." | notify-operators "Incorrect httpd macros"
fi
logger -t archive "Necessary variable assignment pattern ${i} not found in macros"
exit 1
fi
done
# These next lines get the current ip values for the archive and failover, plus they store the value of production,
# which is a variable pointing to either the primary or failover value.
archiveIp="$(sed -n -e "s/^Define ${ARCHIVE_IP_NAME} \(.*\)/\1/p" ${MACROS_PATH} | tr -d '[:space:]')"
failoverIp="$(sed -n -e "s/^Define ${ARCHIVE_FAILOVER_IP_NAME} \(.*\)/\1/p" ${MACROS_PATH} | tr -d '[:space:]')"
productionIp="$(sed -n -e "s/^Define ${PRODUCTION_ARCHIVE_NAME} \(.*\)/\1/p" ${MACROS_PATH} | tr -d '[:space:]')"
# Checks if the macro.conf is set as healthy or unhealthy currently.
if [[ "${productionIp}" == "\${${ARCHIVE_IP_NAME}}" ]]
then
alreadyHealthy=1
logger -t archive "currently healthy"
else
alreadyHealthy=0
logger -t archive "currently unhealthy"
fi
setProduction() {
# parameter $1: the name of the variable holding the IP of the archive instance to switch to
sed -i -e "s/^Define ${PRODUCTION_ARCHIVE_NAME}\>.*$/Define ${PRODUCTION_ARCHIVE_NAME} \${${1}}/" ${MACROS_PATH}
}
# Sets the production value to point to the variable defining the main archive IP, provided it isn't already set.
setProductionMainIfNotSet() {
if [[ $alreadyHealthy -eq 0 ]]
then
# currently unhealthy
# set production to archive
logger -t archive "Healthy: setting production to main archive"
setProduction ${ARCHIVE_IP_NAME}
systemctl reload httpd
echo "The main archive server is healthy again. Switching to it." | notify-operators "Healthy: main archive online"
else
# If already healthy then no reload or notification occurs.
logger -t archive "Healthy: already set, no change needed"
fi
}
setFailoverIfNotSet() {
if [[ $alreadyHealthy -eq 1 ]]
then
# Set production to failover if not already. Separate if statement in case the curl statement
# fails but the production is already set to point to the backup
setProduction ${ARCHIVE_FAILOVER_IP_NAME}
logger -t archive "Unhealthy: second check failed, switching to failover"
systemctl reload httpd
echo "Main archive is unhealthy. Switching to failover. Please urgently take a look at ${archiveIp}." | notify-operators "Unhealthy: main archive offline, failover in place"
else
logger -t archive "Unhealthy: second check still fails, failover already in use"
fi
}
logger -t archive "begin check"
# --fail option ensures that, if a server error is returned (ie. 5xx/4xx status code), then the status code (stored in $?) will be non zero.
# -L follows redirects
curl -s -L --fail --connect-timeout ${TIMEOUT1_IN_SECONDS} "http://${archiveIp}:${ARCHIVE_PORT}/gwt/status" >> /dev/null
if [[ $? -ne 0 ]]
then
logger -t archive "first check failed"
curl -s -L --fail --connect-timeout ${TIMEOUT2_IN_SECONDS} "http://${archiveIp}:${ARCHIVE_PORT}/gwt/status" >> /dev/null
if [[ $? -ne 0 ]]
then
setFailoverIfNotSet
else
setProductionMainIfNotSet
fi
else
setProductionMainIfNotSet
fi
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
ADMIN_EMAIL="axel.uhl@sap.com jan.hamann@sapsailing.com"
cd /home/wiki/gitwiki
git pull >/tmp/wiki-git.out 2>/tmp/wiki-git.err
if [ "$?" != "0" ]; then
cat /tmp/wiki-git.out /tmp/wiki-git.err | mail -s "Wiki git problem" $ADMIN_EMAIL
fi
git push >>/tmp/wiki-git.out 2>/tmp/wiki-git.err
if [ "$?" != "0" ]; then
cat /tmp/wiki-git.out /tmp/wiki-git.err | mail -s "Wiki git problem" $ADMIN_EMAIL
fi
+31
View File
@@ -392,15 +392,45 @@ https://event3.tractrac.com/events/event_20221211_TestOceanR/jsonservice.php
https://event3.tractrac.com/events/event_20230223_TheOceanRa/jsonservice.php
https://event3.tractrac.com/events/event_20230328_TrofeoSARP/jsonservice.php
https://event3.tractrac.com/events/event_20230329_AllianzReg/jsonservice.php
https://event3.tractrac.com/events/event_20230329_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230420_TheOceanRa/jsonservice.php
https://event3.tractrac.com/events/event_20230421_FrenchOlym/jsonservice.php
https://event3.tractrac.com/events/event_20230427_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230505_NorskSeils/jsonservice.php
https://event3.tractrac.com/events/event_20230511_SegelBunde/jsonservice.php
https://event3.tractrac.com/events/event_20230517_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230520_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230603_TheOceanRa/jsonservice.php
https://event3.tractrac.com/events/event_20230607_HelgaCup/jsonservice.php
https://event3.tractrac.com/events/event_20230609_Sejlsports1/jsonservice.php
https://event3.tractrac.com/events/event_20230614_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230614_TheOceanRa/jsonservice.php
https://event3.tractrac.com/events/event_20230616_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230621_NorskSeils/jsonservice.php
https://event3.tractrac.com/events/event_20230629_TheOceanRa/jsonservice.php
https://event3.tractrac.com/events/event_20230706_ParisOlymp/jsonservice.php
https://event3.tractrac.com/events/event_20230721_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230727_SegelBunde/jsonservice.php
https://event3.tractrac.com/events/event_20230801_NorskSeils/jsonservice.php
https://event3.tractrac.com/events/event_20230809_AllianzPar/jsonservice.php
https://event3.tractrac.com/events/event_20230809_AllianzSai1/jsonservice.php
https://event3.tractrac.com/events/event_20230812_CopyofSejl/jsonservice.php
https://event3.tractrac.com/events/event_20230812_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230818_SegelBunde/jsonservice.php
https://event3.tractrac.com/events/event_20230818_Ungdomslig/jsonservice.php
https://event3.tractrac.com/events/event_20230826_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230831_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230902_Sejlsports/jsonservice.php
https://event3.tractrac.com/events/event_20230913_SailingCha1/jsonservice.php
https://event3.tractrac.com/events/event_20230914_SegelBunde/jsonservice.php
https://event3.tractrac.com/events/event_20230922_NorskSeils/jsonservice.php
https://event3.tractrac.com/events/event_20230923_XYachtsSta/jsonservice.php
https://event3.tractrac.com/events/event_20230930_Ungdomslig/jsonservice.php
https://event3.tractrac.com/events/event_20231005_CopyofSege/jsonservice.php
https://event3.tractrac.com/events/event_20231011_LigueNatio/jsonservice.php
https://event3.tractrac.com/events/event_20231012_MesternesM/jsonservice.php
https://event3.tractrac.com/events/event_20231018_SegelBunde/jsonservice.php
https://event3.tractrac.com/events/event_20231105_Europeaner/jsonservice.php
https://event.tractrac.com/events/event_20170727_Travemnder2/jsonservice.php
https://event.tractrac.com/events/event_20171013_DSLPokalGl/jsonservice.php
https://event.tractrac.com/events/event_20181012_MstarnasMs/jsonservice.php
@@ -475,6 +505,7 @@ https://event.tractrac.com/events/event_20211017_KornatiCup/jsonservice.php
https://event.tractrac.com/events/event_20211115_ererFxNacr/jsonservice.php
https://event.tractrac.com/events/event_20211210_YouthSaili/jsonservice.php
https://event.tractrac.com/events/event_20220626_KielerWoch/jsonservice.php
https://event.tractrac.com/events/event_20230324_SAILINGCha/jsonservice.php
https://event.tractrac.com/events/event_20230531_ERERFXNACR/jsonservice.php
https://event.tractrac.com/events/event_20230611_KielerWoch/jsonservice.php
https://event.tractrac.com/events/event_20230622_KielerWoch/jsonservice.php
+1 -1
View File
@@ -1,4 +1,4 @@
FROM docker.sapsailing.com/sapjvm8:8.1.095
FROM docker.sapsailing.com/sapjvm8:8.1.096
ARG RELEASE
LABEL maintainer=axel.uhl@sap.com
# Download and extract the release
+1 -1
View File
@@ -1,5 +1,5 @@
FROM buildpack-deps:bullseye
ARG SAPJVM_VERSION=8.1.095
ARG SAPJVM_VERSION=8.1.096
LABEL maintainer=axel.uhl@sap.com
# Download and extract the SAP JVM 8
ENV PATH=${PATH}:/opt/sapjvm_8/bin
+1 -1
View File
@@ -1,4 +1,4 @@
ARG SAPJVM_VERSION=8.1.095
ARG SAPJVM_VERSION=8.1.096
FROM docker.sapsailing.com/sapjvm8:${SAPJVM_VERSION}
LABEL maintainer=axel.uhl@sap.com
# Download and extract the release
+1 -1
View File
@@ -1,7 +1,7 @@
version: "3.9"
services:
sailing-analytics:
image: "docker.sapsailing.com:443/sapsailing:latest"
image: "docker.sapsailing.com/sapsailing:latest"
ports:
- "8888:8888"
- "6666:6666"
+1
View File
@@ -26,6 +26,7 @@ SAP is at the center of todays technology revolution, developing innovations
* [[User Management|wiki/info/landscape/usermanagement]]
* [[Development Environment|wiki/info/landscape/development-environment]]
* [[Production Environment|wiki/info/landscape/production-environment]]
* [[Internationalization (i18n)|wiki/howto/development/i18n]]
* [[Typical Development Scenarios|wiki/info/landscape/typical-development-scenarios]]
* [[RaceLog Tracking Server Architecture|wiki/info/landscape/server]]
* Environment Overview [[PDF|wiki/info/mobile/event-tracking/architecture.pdf]] | [[SVG|wiki/info/mobile/event-tracking/architecture.svg]]
@@ -1,6 +1,7 @@
package com.sap.sailing.competitorimport;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -32,7 +33,7 @@ public interface CompetitorProvider extends Named {
* competitor names. Should the value for a key be <code>null</code>, competitors for the event may still
* be available, only they may not be keyed per regatta in that case.
*/
Map<String, Set<String>> getHasCompetitorsForRegattasInEvent() throws IOException;
Map<String, Set<String>> getHasCompetitorsForRegattasInEvent() throws IOException, URISyntaxException;
/**
* Obtains competitor records from the source of import
@@ -44,7 +45,7 @@ public interface CompetitorProvider extends Named {
* <code>eventName</code>, or a regatta name as provided in the value set for the key
* <code>eventName</code> as returned by {@link #getHasCompetitorsForRegattasInEvent()}.
*/
Iterable<CompetitorDescriptor> getCompetitorDescriptors(String eventName, String regattaName) throws JAXBException, IOException;
Iterable<CompetitorDescriptor> getCompetitorDescriptors(String eventName, String regattaName) throws JAXBException, IOException, URISyntaxException;
/**
* A hint for users about this competitor provider; ideally mapped to the user's locale with i18n support.
@@ -0,0 +1,30 @@
package com.sap.sailing.datamining.shared;
import com.sap.sse.common.Duration;
import com.sap.sse.common.settings.SerializableSettings;
public class TackTypeSegmentsDataMiningSettings extends SerializableSettings {
private static final long serialVersionUID = 3239182650750480678L;
private final Duration minimumTackTypeSegmentDuration;
private final Duration minimumDurationBetweenAdjacentTackTypeSegments;
public TackTypeSegmentsDataMiningSettings(Duration minimumTackTypeSegmentDuration, Duration minimumDurationBetweenAdjacentTackTypeSegments) {
super();
this.minimumTackTypeSegmentDuration = minimumTackTypeSegmentDuration;
this.minimumDurationBetweenAdjacentTackTypeSegments = minimumDurationBetweenAdjacentTackTypeSegments;
}
public Duration getMinimumTackTypeSegmentDuration() {
return minimumTackTypeSegmentDuration;
}
public Duration getMinimumDurationBetweenAdjacentTackTypeSegments() {
return minimumDurationBetweenAdjacentTackTypeSegments;
}
public static TackTypeSegmentsDataMiningSettings createDefaultSettings() {
return new TackTypeSegmentsDataMiningSettings(
/* minimumTackTypeSegmentDuration */ null,
/* minimumDurationBetweenAdjacentTackTypeSegments */ null);
}
}
@@ -12,5 +12,8 @@ Import-Package: junit.framework;version="4.8.2",
Require-Bundle: org.mockito.mockito-core;bundle-version="4.8.1",
org.hamcrest;bundle-version="2.2.0",
com.sap.sse.common,
org.objenesis;bundle-version="2.1.0"
org.objenesis;bundle-version="2.1.0",
net.bytebuddy.byte-buddy;bundle-version="1.12.18",
net.bytebuddy.byte-buddy-agent;bundle-version="1.12.18",
com.sap.sailing.domain.test
Automatic-Module-Name: com.sap.sailing.datamining.test
@@ -0,0 +1,194 @@
package com.sap.sailing.datamining.impl.components;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
import com.sap.sailing.datamining.impl.data.LeaderboardWithContext;
import com.sap.sailing.datamining.impl.data.RaceOfCompetitorWithContext;
import com.sap.sailing.datamining.impl.data.TrackedRaceWithContext;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.CompetitorWithBoat;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.impl.DegreePosition;
import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
import com.sap.sailing.domain.test.StoredTrackBasedTest;
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Distance.NullDistance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.DegreeBearingImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class TestSegmentsTackType extends StoredTrackBasedTest {
private DynamicTrackedRaceImpl trackedRace;
private CompetitorWithBoat competitorA;
private HasRaceOfCompetitorContext raceOfCompContext;
private TackTypeSegmentRetrievalProcessor resultTTSegmentsRetrieval;
@Before
public void setup() {
competitorA = createCompetitorWithBoat("A");
trackedRace = createTestTrackedRace("TestRegatta", "TestRace", "F18", createCompetitorAndBoatsMap(competitorA),
MillisecondsTimePoint.now(), /* useMarkPassingCalculator */ true, null,
OneDesignRankingMetric::new);
final Leaderboard leaderboard = new FlexibleLeaderboardImpl("Test",
new ThresholdBasedResultDiscardingRuleImpl(new int[0]), new LowPoint(),
new CourseAreaImpl("Here", UUID.randomUUID(), /* centerPosition */ null, /* radius */ null));
final HasLeaderboardContext leaderboardContext = new LeaderboardWithContext(leaderboard, null);
final HasTrackedRaceContext trackedRaceContext = new TrackedRaceWithContext(leaderboardContext,
trackedRace.getTrackedRegatta().getRegatta(), null, null, trackedRace);
raceOfCompContext = new RaceOfCompetitorWithContext(trackedRaceContext, competitorA, TackTypeSegmentsDataMiningSettings.createDefaultSettings());
resultTTSegmentsRetrieval = new TackTypeSegmentRetrievalProcessor(null, Collections.emptySet(), TackTypeSegmentsDataMiningSettings.createDefaultSettings(), 0, null);
}
private Iterable<HasTackTypeSegmentContext> retrieveData() {
return resultTTSegmentsRetrieval.retrieveData(raceOfCompContext);
}
@Test
public void testingSegmentsAreNotNull() {
// set up GPS fixes for competitor, as well as mark passings:
DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorATrack = trackedRace.getTrack(competitorA);
final KnotSpeedWithBearingImpl sogCog = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45));
TimePoint timePoint = trackedRace.getStartOfTracking().plus(10);
GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog);
final Duration timeBetweenFixes = Duration.ofMillis(490);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCog.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog);
}
TimePoint markPassingTimePoint = trackedRace.getStartOfTracking().plus(20);
final List<MarkPassing> markPassingsForCompetitor = new ArrayList<>();
final Duration legDuration = Duration.ofSeconds(60);
for (Waypoint waypoint : trackedRace.getRace().getCourse().getWaypoints()) {
markPassingsForCompetitor.add(new MarkPassingImpl(markPassingTimePoint, waypoint, competitorA));
markPassingTimePoint = markPassingTimePoint.plus(legDuration);
}
trackedRace.updateMarkPassings(competitorA, markPassingsForCompetitor);
assertNotNull(trackedRace.getEndOfRace());
// now run the actual test:
final Iterable<HasTackTypeSegmentContext> allTTSegments = retrieveData();
Distance sumDistance = new NullDistance();
for (HasTackTypeSegmentContext oneTTSegment : allTTSegments) {
if (oneTTSegment != null) {
sumDistance = sumDistance.add(oneTTSegment.getDistance());
}
}
assertTrue(sumDistance.compareTo(Distance.NULL) > 0);
}
@Test
public void testingMissingMarkPassing() {
// set up GPS fixes for competitor, but no mark passings:
DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorATrack = trackedRace.getTrack(competitorA);
final KnotSpeedWithBearingImpl sogCog = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45));
TimePoint timePoint = trackedRace.getStartOfTracking().plus(10);
GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(54.4680424, 10.234451), timePoint, sogCog);
final Duration timeBetweenFixes = Duration.ofMillis(490);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCog.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCog);
}
// now run the actual test:
final Iterable<HasTackTypeSegmentContext> allTTSegments = retrieveData();
assertTrue(Util.isEmpty(allTTSegments));
}
@Test
public void testingFixExactlyOnMarkPassingAndRaceOpenEnded() {
final List<TimePoint> expectedSegmentStarts = new ArrayList<>();
// set up GPS fixes for competitor, as well as mark passings:
DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorATrack = trackedRace.getTrack(competitorA);
// start on port tack:
final KnotSpeedWithBearingImpl sogCogPortTackUpwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(45));
TimePoint timePoint = trackedRace.getStartOfTracking().plus(10);
final Position middleOfStartLine = trackedRace.getApproximatePosition(trackedRace.getRace().getCourse().getFirstWaypoint(), timePoint);
final Position topMarkPosition = trackedRace.getApproximatePosition(Util.get(trackedRace.getRace().getCourse().getWaypoints(), 1), timePoint);
// start straight "under" the top mark
GPSFixMovingImpl currentGPS = new GPSFixMovingImpl(new DegreePosition(middleOfStartLine.getLatDeg(), topMarkPosition.getLngDeg()), timePoint, sogCogPortTackUpwind);
expectedSegmentStarts.add(timePoint);
final Duration timeBetweenFixes = Duration.ofMillis(490);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCogPortTackUpwind.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind);
}
// now tack onto starboard tack:
final KnotSpeedWithBearingImpl sogCogStarboardTackUpwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(315));
expectedSegmentStarts.add(timePoint);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCogStarboardTackUpwind.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogStarboardTackUpwind);
}
final List<MarkPassing> markPassingsForCompetitor = new ArrayList<>();
final TimePoint startMarkPassingTimePoint = trackedRace.getStartOfTracking().plus(20);
markPassingsForCompetitor.add(new MarkPassingImpl(startMarkPassingTimePoint, trackedRace.getRace().getCourse().getFirstWaypoint(), competitorA));
final TimePoint windwardMarkPassingTimePoint = timePoint; // exactly the time point of the last fix
markPassingsForCompetitor.add(new MarkPassingImpl(windwardMarkPassingTimePoint, Util.get(trackedRace.getRace().getCourse().getWaypoints(), 1), competitorA));
trackedRace.updateMarkPassings(competitorA, markPassingsForCompetitor);
// continue sailing downwind:
// start on starboard tack:
final KnotSpeedWithBearingImpl sogCogStarboardTackDownwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(225));
expectedSegmentStarts.add(timePoint);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCogStarboardTackDownwind.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackUpwind);
}
// now gybe onto port tack:
final KnotSpeedWithBearingImpl sogCogPortTackDownwind = new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(135));
expectedSegmentStarts.add(timePoint);
for (int i=0; i<20; i++) {
competitorATrack.addGPSFix(currentGPS);
final Position currentPosition = sogCogPortTackDownwind.travelTo(currentGPS.getPosition(), timeBetweenFixes);
timePoint = timePoint.plus(timeBetweenFixes);
currentGPS = new GPSFixMovingImpl(currentPosition, timePoint, sogCogPortTackDownwind);
}
// now run the actual test:
final Iterable<HasTackTypeSegmentContext> allTTSegments = retrieveData();
assertEquals(4, Util.size(allTTSegments));
// assert that all segments are of similar distance; they are not exactly equal
// because due to smoothing of COG/SOG, tack type transitions are not exactly where COG goes from 45 to, say, 315
final Distance distanceFirstSegment = allTTSegments.iterator().next().getDistance();
for (final HasTackTypeSegmentContext ttSegment : allTTSegments) {
assertEquals(distanceFirstSegment.getMeters(), ttSegment.getDistance().getMeters(), distanceFirstSegment.scale(0.2).getMeters() /* allow for 20% tolerance */);
}
}
}
@@ -24,7 +24,7 @@ Team=Team
SearchTag=Search Tag
LeaderboardSailingDomainRetrieverChain=Leaderboards
RaceSailingDomainRetrieverChain=Races
LegSailingDomainRetrieverChain=Legs
LegOfCompetitorSailingDomainRetrieverChain=Legs of Competitors
GPSFixSailingDomainRetrieverChain=GPS Fixes
BravoFixSailingDomainRetrieverChain=Bravo Fixes
BravoFixTrackSailingDomainRetrieverChain=Bravo Tracks
@@ -254,4 +254,21 @@ CompetitorDaySailingDomainRetrieverChain=Competitor-Day for race
LowestSpeed=Lowest Speed
SpeedChange=Speed Change
MaximumTurningRate=Maximum turning rate (°/s)
AverageTurningRate=Average turning rate (°/s)
AverageTurningRate=Average turning rate (°/s)
LengthOfTheLeg=Length of the Leg
LegSailingDomainRetrieverChain=Leg
TackType=Long / short tack
getTackTypeofRace=Long / short tack of the race
tackTypeSegmentsRetrieverChainDefinition=Long/Short tack segments
TackTypeSegments=Long/Short segments
TackTypeSegmentName=Long/Short tack segments name
TackTypeDuration=Long/Short tack duration
TackTypeDistance=Long/Short tack distance
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
RatioDistanceLongVsShortTack=Ratio distance long tack / short tack
RatioDurationLongVsShortTack=Ratio duration long tack / short tack
@@ -24,7 +24,7 @@ Team=Tým
SearchTag=Hledací znak
LeaderboardSailingDomainRetrieverChain=Výsledkové tabule
RaceSailingDomainRetrieverChain=Rozjížďky
LegSailingDomainRetrieverChain=Úseky
LegOfCompetitorSailingDomainRetrieverChain=Úseky závodníků
GPSFixSailingDomainRetrieverChain=Záznamy polohy GPS
BravoFixSailingDomainRetrieverChain=Záznamy polohy Bravo
BravoFixTrackSailingDomainRetrieverChain=Dráhy Bravo
@@ -255,3 +255,13 @@ LowestSpeed=Nejnižší rychlost
SpeedChange=Změna rychlosti
MaximumTurningRate=Maximální tempo změny kurzu (°/s)
AverageTurningRate=Průměrné tempo změny kurzu (°/s)
LengthOfTheLeg=Délka úseku
LegSailingDomainRetrieverChain=Úsek
TackType=Dlouhý/krátký obrat
getTackTypeofRace=Dlouhý/krátký obrat rozjížďky
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Team
SearchTag=Søgetag
LeaderboardSailingDomainRetrieverChain=Ranglister
RaceSailingDomainRetrieverChain=Sejladser
LegSailingDomainRetrieverChain=Ben
LegOfCompetitorSailingDomainRetrieverChain=Ben for konkurrenter
GPSFixSailingDomainRetrieverChain=GPS-registreringer
BravoFixSailingDomainRetrieverChain=Bravo-registreringer
BravoFixTrackSailingDomainRetrieverChain=Bravo-spor
@@ -255,3 +255,13 @@ LowestSpeed=Laveste hastighed
SpeedChange=Hastighedsændring
MaximumTurningRate=Maks. drejehastighed (°/s)
AverageTurningRate=Gennemsnitlig drejehastighed (°/s)
LengthOfTheLeg=Længde på benet
LegSailingDomainRetrieverChain=Ben
TackType=Lang/kort stagvende
getTackTypeofRace=Lang/kort stagvende for kapsejladsen
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -10,8 +10,8 @@ Acronym=Abkürzung
SailID=Segelnummer
BoatName=Bootsname
Color=Farbe
LegNumber=Nummer des Schenkels
LegType=Art des Schenkels
LegNumber=Nummer des Bahnschenkels
LegType=Art des Bahnschenkels
Year=Jahr
Regatta=Regatta
CourseArea=Regattabahn
@@ -21,7 +21,7 @@ RaceColumn=Rennspalte
Race=Rennen
LeaderboardSailingDomainRetrieverChain=Leaderboards
RaceSailingDomainRetrieverChain=Rennen
LegSailingDomainRetrieverChain=Schenkel
LegOfCompetitorSailingDomainRetrieverChain=Bahnschenkel eines Teilnehmers
GPSFixSailingDomainRetrieverChain=GPS-Fixes
BravoFixSailingDomainRetrieverChain=Bravo-Fixes
BravoFixTrackSailingDomainRetrieverChain=Bravo Messreihen
@@ -35,9 +35,9 @@ RaceOfCompetitorSailingDomainRetrieverChain=Rennen eines Teilnehmers
ManeuverSailingDomainRetrieverChain=Manöver
LeaderboardGroup=Ranglisten Gruppe
Leaderboard=Rangliste
Leg=Schenkel
Leg=Bahnschenkel
MarkPassing=Tonnenrundung
LegOfCompetitor=Schenkel eines Teilnehmers
LegOfCompetitor=Bahnschenkel eines Teilnehmers
GpsFix=GPS-Fix
BravoFix=Bravo-Fix
LineLengthAtStart=Länge der Startlinie zum Startzeitpunkt
@@ -117,7 +117,7 @@ RankThirtySecondsAfterStart=Absolute Platzierung 30s nach dem Startzeitpunkt
WindwardDistanceToAdvantageousEndOfLineAtStartOfRace=Windwärtige Distanz zum Bevorteilten Ende der Startlinie zum Start des Rennens
WindwardDistanceToAdvantageousEndOfLineAtStartOfCompetitor=Windwärtige Distanz zum Bevorteilten Ende der Startlinie zum Start des Teilnehmers
AbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor=Absolute Windwärtige Distanz zur Steuerbordseite beim Start des Teilnehmers
RankAfterHalfOfTheFirstLeg=Platzierung nach der Hälfte des ersten Schenkels
RankAfterHalfOfTheFirstLeg=Platzierung nach der Hälfte des ersten Bahnschenkels
AdvantageousEndOfLine=Bevorteiltes Ende der Startlinie
AdvantageOfStarboardSideOfStartLine=Vorteil der Steuerbord-Seite der Startlinie
TrueWindAngleOfStartLineSeenFromStarboardSide=Winkel der Startlinie zum wahren Wind vom Steuerbord-Ende aus gesehen
@@ -257,4 +257,16 @@ CompetitorDaySailingDomainRetrieverChain=Teilnehmer-Tag für Wettfahrt
LowestSpeed=Niedrigste Geschwindigkeit
SpeedChange=Geschwindigkeits-Änderung
MaximumTurningRate=Maximale Drehgeschwindigkeit (°/s)
AverageTurningRate=Durchschnittliche Drehgeschwindigkeit (°/s)
AverageTurningRate=Durchschnittliche Drehgeschwindigkeit (°/s)
LengthOfTheLeg=Länge eines Bahnschenkels
LegSailingDomainRetrieverChain=Bahnschenkel
TackType=Streck-/Holebug
getTackTypeofRace=Streck-/Holebug des Rennens
InRace=In der Wettfahrt
InTrackingInterval=Im Tracking-Zeitraum der Wettfahrt
NumberOfCompetitors=Anzahl Teilnehmer
CompetitorInLeaderboard=Teilnehmer aus Rangliste
CompetitorSailingDomainRetrieverChain=Teilnehmer in Ranglisten
SmoothedSpeed=Geglättete Geschwindigkeit
RatioDistanceLongVsShortTack=Verhältnis gesegelte Distanz auf Streck- zu Holebug
RatioDurationLongVsShortTack=Verhältnis gesegelte Dauer auf Streck- zu Holebug
@@ -16,15 +16,15 @@ Regatta=Regata
CourseArea=Zona de regata
BoatClass=Clase de bote
Fleet=Flota
RaceColumn=Columna de carrera
Race=Carrera
RaceColumn=Columna de prueba
Race=Prueba
Competitor=Competidor
Boat=Bote
Team=Equipo
SearchTag=Etiqueta de búsqueda
LeaderboardSailingDomainRetrieverChain=Clasificaciones
RaceSailingDomainRetrieverChain=Carreras
LegSailingDomainRetrieverChain=Tramos
RaceSailingDomainRetrieverChain=Pruebas
LegOfCompetitorSailingDomainRetrieverChain=Tramos de competidores
GPSFixSailingDomainRetrieverChain=Puntos de GPS
BravoFixSailingDomainRetrieverChain=Puntos de Bravo
BravoFixTrackSailingDomainRetrieverChain=Seguimientos Bravo
@@ -32,12 +32,12 @@ FoilingSegmentsSailingDomainRetrieverChain=Apéndices de foil
FoilingSegmentName=Nombre de apéndice de foil
WindFixSailingDomainRetrieverChain=Puntos de viento
MarkPassingSailingDomainRetrieverChain=Superaciones de marca
TrackedRaceResultOfCompetitorRetrieverChain=Carreras
RaceResultSailingDomainRetrieverChain=Resultados de la carrera
RaceOfCompetitorSailingDomainRetrieverChain=Carreras de los competidores
TrackedRaceResultOfCompetitorRetrieverChain=Pruebas
RaceResultSailingDomainRetrieverChain=Resultados de la prueba
RaceOfCompetitorSailingDomainRetrieverChain=Pruebas de los competidores
ManeuverSailingDomainRetrieverChain=Maniobra
LeaderboardGroup=Grupo de clasificación
LineLengthAtStart=Longitud de línea de salida al inicio de carrera
LineLengthAtStart=Longitud de línea de salida al inicio de prueba
Leaderboard=Clasificación
Leg=Tramo
MarkPassing=Superación de marca
@@ -63,7 +63,7 @@ Bft11=Temporal duro
Bft12=Huracán
RelativeScore=Puntuación relativa (0 mejor; 1 peor)
RelativeScoreInPercent=Puntuación relativa en %
RelativeScoreInRaceInPercent=Puntuación relativa en carrera en %
RelativeScoreInRaceInPercent=Puntuación relativa en prueba en %
AbsoluteRank=Posición absoluta
AbsoluteRankAfterFirstQuarter=Posición absoluta tras el primer cuarto
AbsoluteRankAfterSecondQuarter=Posición absoluta tras el segundo cuarto
@@ -87,7 +87,7 @@ SpeedWhenStarting=Velocidad al inicio
SpeedTenSecondsBeforeStart=Velocidad 10 s antes del inicio
RankAtFirstMark=Posición en la primera marca
NumberOfManeuvers=Número de maniobras
NumberOfTacks=Número de amuras
NumberOfTacks=Número de bordos
NumberOfJibes=Número de viradas en redondo
NumberOfPenaltyCircles=Número de círculos de sanción
RankGainsOrLosses=Aumentos y pérdidas de posición
@@ -101,7 +101,7 @@ NumberOfCompetitorFixes=Número de puntos del competidor
NumberOfMarkFixes=Número de puntos de la marca
NumberOfWindFixes=Número de correcciones de viento
ManeuverType=Tipo de maniobra
Tack=Amura
Tack=Bordo
WindSpeedVsManeuverLoss=Velocidad de viento en nudos (X) vs. Pérdida en maniobra en metros (Y)
SpeedBefore=Velocidad antes de maniobra
SpeedAfter=Velocidad después de maniobra
@@ -112,10 +112,10 @@ ToSide=Al lado (babor / estribor)
ManeuverLoss=Pérdida en maniobra
Waypoint=Punto de ruta
PassingSide=Vía de paso
TackAtStart=Amura al inicio
TackAtStart=Bordo al inicio
SpeedTenSecondsAfterStart=Velocidad 10 s después del inicio
RankThirtySecondsAfterStart=Posición 30 segundos después del inicio
WindwardDistanceToAdvantageousEndOfLineAtStartOfRace=Distancia a barlovento hasta extremo favorable al inicio de carrera
WindwardDistanceToAdvantageousEndOfLineAtStartOfRace=Distancia a barlovento hasta extremo favorable al inicio de prueba
WindwardDistanceToAdvantageousEndOfLineAtStartOfCompetitor=Distancia a barlovento a banda de estribor de línea al inicio de competidor
RankAfterHalfOfTheFirstLeg=Posición tras la mitad del primer tramo
AdvantageousEndOfLine=Extremo favorable
@@ -125,11 +125,11 @@ StartLineLength=Longitud de línea de salida
FinishLineLength=Longitud de línea de llegada
TimeSpentInSeconds=Tiempo empleado en segundos
MedalRace=Medal Race
WindwardDistanceToAdvantageousEndOfLineAtStartOfRaceVsRelativeDistanceToAdvantageousEndOfLine=Distancia a barlovento hasta extremo favorable al inicio de carrera (X) vs. distancia relativa hasta extremo favorable al inicio de carrera (Y)
WindwardDistanceToAdvantageousEndOfLineAtStartOfRaceVsRelativeDistanceToAdvantageousEndOfLine=Distancia a barlovento hasta extremo favorable al inicio de prueba (X) vs. distancia relativa hasta extremo favorable al inicio de prueba (Y)
WindSourceType=Tipo de fuente de viento
AbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor=Distancia a barlovento absoluta a banda de estribor de la línea al inicio del competidor
WindSourceName=Nombre de fuente de viento
RelativeDistanceToAdvantageousEndOfLineAtStartOfRace=Distancia relativa hasta extremo favorable al inicio de carrera
RelativeDistanceToAdvantageousEndOfLineAtStartOfRace=Distancia relativa hasta extremo favorable al inicio de prueba
windFrom=Dirección del viento real (TWD)
windSpeedKnots=Velocidad del viento real (nudos)
speedInKnots=Velocidad (nudos)
@@ -211,7 +211,7 @@ RelativeBearingToNextMarkAfterManeuver=Rumbo relativo a la siguiente marca tras
AbsRelativeBearingToNextMarkBeforeManeuver=Rumbo relativo absoluto a la siguiente marca antes de la maniobra
AbsRelativeBearingToNextMarkAfterManeuver=Rumbo relativo absoluto a la siguiente marca tras la maniobra
JibingCount=Recuento de trasluchadas
TackingCount=Recuento de viradas
TackingCount=Recuento de bordos
AbsTwaAtMaxTurningRate=TWA absoluto en velocidad máxima de giro
AbsTwaAtLowestSpeed=TWA absoluto en velocidad mínima
AbsTwaAtHighestSpeed=TWA absoluto en velocidad máxima
@@ -220,31 +220,31 @@ PercentageOfMainCurveProgressUntilHighestSpeed=Porcentaje de progreso de curva p
PercentageOfMainCurveProgressUntilMaxTurningRate=Porcentaje de progreso de curva principal hasta velocidad máxima de giro
AbsTwaAtManeuverMiddle=TWA absoluto en mitad de maniobra
GpsSamplingRate=Velocidad de muestreo de GPS
RaceDuration=Duración de carrera
DistanceToAdvantageousSideAtStartOfRaceVsRankAtFirstMark=Distancia relativa hasta extremo favorable al inicio de la carrera (X) frente a posición con calificación más alta (Y)
DistanceToAdvantageousSideAtStartOfRaceVsFinalRank=Distancia relativa hasta extremo favorable al inicio de la carrera (X) frente a posición final (Y)
AverageRaceWindSpeed=Velocidad media de viento para la carrera
VMG5SecondsBeforeStartOfRace=VMG 5 segundos antes del inicio de la carrera
VMGAtStartOfRace=VMG al inicio de la carrera
RaceDuration=Duración de prueba
DistanceToAdvantageousSideAtStartOfRaceVsRankAtFirstMark=Distancia relativa hasta extremo favorable al inicio de la prueba (X) frente a posición con calificación más alta (Y)
DistanceToAdvantageousSideAtStartOfRaceVsFinalRank=Distancia relativa hasta extremo favorable al inicio de la prueba (X) frente a posición final (Y)
AverageRaceWindSpeed=Velocidad media de viento para la prueba
VMG5SecondsBeforeStartOfRace=VMG 5 segundos antes del inicio de la prueba
VMGAtStartOfRace=VMG al inicio de la prueba
FinalRank=Posición final
VMG5SecondsAfterStartOfRace=VMG 5 segundos tras el inicio de la carrera
RankSixtySecondsAfterStart=Posición 60 segundos tras el inicio de la carrera
RankNinetySecondsAfterStart=Posición 90 segundos tras el inicio de la carrera
DistanceToStarboardSideAtStartOfRace=Distancia relativa hasta la banda de estribor en inicio de carrera
BiasAtStartOfRace=Distorsión de línea de salida al inicio de la carrera en metros (negativo: PUERTO, positivo: ESTRIBOR)
Bias30SecondsAfterRaceStart=Distorsión de línea de salida 30 segundos tras el inicio de la carrera en metros (negativo: PUERTO, positivo: ESTRIBOR)
VMG5SecondsAfterStartOfRace=VMG 5 segundos tras el inicio de la prueba
RankSixtySecondsAfterStart=Posición 60 segundos tras el inicio de la prueba
RankNinetySecondsAfterStart=Posición 90 segundos tras el inicio de la prueba
DistanceToStarboardSideAtStartOfRace=Distancia relativa hasta la banda de estribor en inicio de prueba
BiasAtStartOfRace=Distorsión de línea de salida al inicio de la prueba en metros (negativo: BABOR, positivo: ESTRIBOR)
Bias30SecondsAfterRaceStart=Distorsión de línea de salida 30 segundos tras el inicio de la prueba en metros (negativo: BABOR, positivo: ESTRIBOR)
RankAtFirstMarkVsFinalRank=Posición en la primera marca (X) frente a posición final (Y)
DistanceToStarboardSideOfStartLineProjectedOntoLineAtStart=Distancia a la banda de estribor de la línea de salida proyectada en la línea en la salida
NormalizedDistanceToStarboardSideOfStartLineProjectedOntoLineAtStart=Distancia a la banda de estribor de la línea de salida proyectada en la línea en la salida dividida por la longitud de la línea de salida
DistanceToNextBoatToPortProjectedToStartLineAtStartOfRace=Distancia a la siguiente embarcación a babor en el inicio de la carrera, proyectada sobre la línea de salida
DistanceToNextBoatToStarboardProjectedToStartLineAtStartOfRace=Distancia a la siguiente embarcación a estribor en el inicio de la carrera, proyectada sobre la línea de salida
WindwardDistanceToNextBoatToPortAtStartOfRace=Distancia a barlovento a siguiente embarcación a babor en el inicio de la carrera
WindwardDistanceToNextBoatToStarboardAtStartOfRace=Distancia a barlovento a siguiente embarcación a estribor en el inicio de la carrera
DistanceToNextBoatToPortAtStartOfRacePerpendicularToStartLine=Distancia a la siguiente embarcación a babor en el inicio de la carrera, perpendicular a la línea de salida
DistanceToNextBoatToStarboardAtStartOfRacePerpendicularToStartLine=Distancia a la siguiente embarcación a estribor en el inicio de la carrera, perpendicular a la línea de salida
TotalDistanceToNeighboursPerpendicularToStarLineAtStartOfRace=Total de distancias absolutas para los vecinos en la línea de salida en el inicio de la carrera, perpendiculares en la línea de salida
TotalWindwardDistanceToNeighboursAtStartOfRace=Total de distancias absolutas a barlovento para los vecinos en la línea de salida en el inicio de la carrera
TotalDistanceToNeighboursProjectedToStartLineAtStartOfRace=Total de distancias a lo largo de la línea para los vecinos en la línea de salida (o en posición final, respectivamente) en el inicio de la carrera
DistanceToNextBoatToPortProjectedToStartLineAtStartOfRace=Distancia a la siguiente embarcación a babor en el inicio de la prueba, proyectada sobre la línea de salida
DistanceToNextBoatToStarboardProjectedToStartLineAtStartOfRace=Distancia a la siguiente embarcación a estribor en el inicio de la prueba, proyectada sobre la línea de salida
WindwardDistanceToNextBoatToPortAtStartOfRace=Distancia a barlovento a siguiente embarcación a babor en el inicio de la prueba
WindwardDistanceToNextBoatToStarboardAtStartOfRace=Distancia a barlovento a siguiente embarcación a estribor en el inicio de la prueba
DistanceToNextBoatToPortAtStartOfRacePerpendicularToStartLine=Distancia a la siguiente embarcación a babor en el inicio de la prueba, perpendicular a la línea de salida
DistanceToNextBoatToStarboardAtStartOfRacePerpendicularToStartLine=Distancia a la siguiente embarcación a estribor en el inicio de la prueba, perpendicular a la línea de salida
TotalDistanceToNeighboursPerpendicularToStarLineAtStartOfRace=Total de distancias absolutas para los vecinos en la línea de salida en el inicio de la prueba, perpendiculares en la línea de salida
TotalWindwardDistanceToNeighboursAtStartOfRace=Total de distancias absolutas a barlovento para los vecinos en la línea de salida en el inicio de la prueba
TotalDistanceToNeighboursProjectedToStartLineAtStartOfRace=Total de distancias a lo largo de la línea para los vecinos en la línea de salida (o en posición final, respectivamente) en el inicio de la prueba
IRM=Código IRM (OCS, DNC, DNF, etc.)
XTE=Error de recorrido
AbsoluteXTE=Error de recorrido absoluto
@@ -255,3 +255,13 @@ LowestSpeed=Velocidad más baja
SpeedChange=Cambio de velocidad
MaximumTurningRate=Velocidad máxima de giro (°/s)
AverageTurningRate=Velocidad media de giro (°/s)
LengthOfTheLeg=Longitud del tramo
LegSailingDomainRetrieverChain=Tramo
TackType=Bordo largo/corto
getTackTypeofRace=Bordo largo/corto de la prueba
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Équipe
SearchTag=Balise de recherche
LeaderboardSailingDomainRetrieverChain=Palmarès
RaceSailingDomainRetrieverChain=Courses
LegSailingDomainRetrieverChain=Portions de parcours
LegOfCompetitorSailingDomainRetrieverChain=Portions de parcours des concurrents
GPSFixSailingDomainRetrieverChain=Positions GPS
BravoFixSailingDomainRetrieverChain=Positions Bravo
BravoFixTrackSailingDomainRetrieverChain=Enregistrements Bravo
@@ -249,9 +249,19 @@ IRM=Code IRM (OCS, DNC, DNF, etc.)
XTE=Écart de route
AbsoluteXTE=Écart de route absolu
Day=Jour
CompetitorDay=Jour des concurrents
CompetitorDaySailingDomainRetrieverChain=Jour des concurrents pour la course
CompetitorDay=Jours par concurrent
CompetitorDaySailingDomainRetrieverChain=Jours par concurrent pour la course
LowestSpeed=Vitesse la plus basse
SpeedChange=Changement de vitesse
MaximumTurningRate=Vitesse angulaire maximale (°/s)
AverageTurningRate=Vitesse angulaire moyenne (°/s)
LengthOfTheLeg=Longueur de la portion de parcours
LegSailingDomainRetrieverChain=Portion de parcours
TackType=Virement long/court
getTackTypeofRace=Virement long/court de la course
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Squadra
SearchTag=Tag di ricerca
LeaderboardSailingDomainRetrieverChain=Classifiche
RaceSailingDomainRetrieverChain=Gare
LegSailingDomainRetrieverChain=Tratte
LegOfCompetitorSailingDomainRetrieverChain=Tratte dei concorrenti
GPSFixSailingDomainRetrieverChain=Punti nave GPS
BravoFixSailingDomainRetrieverChain=Punti nave Bravo
BravoFixTrackSailingDomainRetrieverChain=Tracce Bravo
@@ -249,9 +249,19 @@ IRM=Codice IRM (OCS, DNC, DNF, ecc.)
XTE=Errore di fuori rotta
AbsoluteXTE=Errore assoluto di fuori rotta
Day=Giorno
CompetitorDay=Giorno del concorrente
CompetitorDaySailingDomainRetrieverChain=Giorno di gara del concorrente
CompetitorDay=Giorno concorrente
CompetitorDaySailingDomainRetrieverChain=Giorni concorrente per ciascuna gara
LowestSpeed=Velocità più bassa
SpeedChange=Cambio di velocità
MaximumTurningRate=Velocità di virata massima (°/s)
AverageTurningRate=Velocità di virata media (°/s)
LengthOfTheLeg=Lunghezza della tratta
LegSailingDomainRetrieverChain=Tratta
TackType=Bordo lungo/corto
getTackTypeofRace=Bordo lungo/corto della gara
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=チーム
SearchTag=検索タグ
LeaderboardSailingDomainRetrieverChain=リーダーボード
RaceSailingDomainRetrieverChain=レース
LegSailingDomainRetrieverChain=レグ
LegOfCompetitorSailingDomainRetrieverChain=競技者のレグ
GPSFixSailingDomainRetrieverChain=GPS フィックス
BravoFixSailingDomainRetrieverChain=Bravo フィックス
BravoFixTrackSailingDomainRetrieverChain=Bravo トラック
@@ -255,3 +255,13 @@ LowestSpeed=最低速度
SpeedChange=速度変更
MaximumTurningRate=最大回転率 (°/s)
AverageTurningRate=平均回転率 (°/s)
LengthOfTheLeg=レグの長さ
LegSailingDomainRetrieverChain=レグ
TackType=ロング/ショートタック
getTackTypeofRace=レースのロング/ショートタック
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Equipe
SearchTag=Etiqueta de pesquisa
LeaderboardSailingDomainRetrieverChain=Painéis de classificação
RaceSailingDomainRetrieverChain=Corridas
LegSailingDomainRetrieverChain=Pernas
LegOfCompetitorSailingDomainRetrieverChain=Pernas de competidores
GPSFixSailingDomainRetrieverChain=Pontos fixos de GPS
BravoFixSailingDomainRetrieverChain=Pontos fixos Bravo
BravoFixTrackSailingDomainRetrieverChain=Pistas Bravo
@@ -255,3 +255,13 @@ LowestSpeed=Velocidade mais baixa
SpeedChange=Mudança de velocidade
MaximumTurningRate=Taxa de viragem máxima (°/s)
AverageTurningRate=Taxa de viragem média (°/s)
LengthOfTheLeg=Comprimento da perna
LegSailingDomainRetrieverChain=Perna
TackType=Cambada longa/curta
getTackTypeofRace=Cambada longa/curta da corrida
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Команда
SearchTag=Тег поиска
LeaderboardSailingDomainRetrieverChain=Таблицы лидеров
RaceSailingDomainRetrieverChain=Гонки
LegSailingDomainRetrieverChain=Отрезки
LegOfCompetitorSailingDomainRetrieverChain=Отрезки участников
GPSFixSailingDomainRetrieverChain=Замеры GPS
BravoFixSailingDomainRetrieverChain=Замеры Bravo
BravoFixTrackSailingDomainRetrieverChain=Отслеживания Bravo
@@ -255,3 +255,13 @@ LowestSpeed=Наименьшая скорость
SpeedChange=Изменение скорости
MaximumTurningRate=Максимальная скорость поворота (°/c)
AverageTurningRate=Средняя скорость поворота (°/c)
LengthOfTheLeg=Длина отрезка
LegSailingDomainRetrieverChain=Отрезок
TackType=Длинный /короткий галс
getTackTypeofRace=Длинный /короткий галс гонки
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=Ekipa
SearchTag=Oznaka iskanja
LeaderboardSailingDomainRetrieverChain=Lestvice vodilnih
RaceSailingDomainRetrieverChain=Plovi
LegSailingDomainRetrieverChain=Stranice
LegOfCompetitorSailingDomainRetrieverChain=Stranice tekmovalcev
GPSFixSailingDomainRetrieverChain=GPS-položaj
BravoFixSailingDomainRetrieverChain=Bravo-položaji
BravoFixTrackSailingDomainRetrieverChain=Bravo-sledi
@@ -255,3 +255,13 @@ LowestSpeed=Najnižja hitrost
SpeedChange=Sprememba hitrosti
MaximumTurningRate=Maksimalna hitrost obračanja (°/s)
AverageTurningRate=Povprečna hitrost obračanja (°/s)
LengthOfTheLeg=Dolžina stranice
LegSailingDomainRetrieverChain=Stranica
TackType=Dolgo/kratko prečenje
getTackTypeofRace=Dolgo/kratko prečenje plova
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -24,7 +24,7 @@ Team=团队
SearchTag=搜索标记
LeaderboardSailingDomainRetrieverChain=积分榜
RaceSailingDomainRetrieverChain=比赛轮次
LegSailingDomainRetrieverChain=航段
LegOfCompetitorSailingDomainRetrieverChain=参赛队的航段
GPSFixSailingDomainRetrieverChain=GPS 修复
BravoFixSailingDomainRetrieverChain=Bravo 修复
BravoFixTrackSailingDomainRetrieverChain=Bravo 跟踪
@@ -249,9 +249,19 @@ IRM=IRM 代码(OCS、DNC、DNF 等)
XTE=交叉轨道误差
AbsoluteXTE=绝对交叉轨道误差
Day=
CompetitorDay=参赛队
CompetitorDaySailingDomainRetrieverChain=比赛轮次的参赛队
CompetitorDay=参赛队
CompetitorDaySailingDomainRetrieverChain=比赛轮次的参赛队
LowestSpeed=最低速度
SpeedChange=速度变化
MaximumTurningRate=最大回转率 (°/s)
AverageTurningRate=平均回转率 (°/s)
LengthOfTheLeg=航段长度
LegSailingDomainRetrieverChain=航段
TackType=长程/短程迎风转向
getTackTypeofRace=比赛轮次的长程/短程迎风转向
InRace=In race
InTrackingInterval=In tracking interval
NumberOfCompetitors=Number of Competitors
CompetitorInLeaderboard=Competitor in Leaderboard
CompetitorSailingDomainRetrieverChain=Competitors in Leaderboards
SmoothedSpeed=Smoothed Speed
@@ -10,6 +10,7 @@ import org.osgi.framework.BundleContext;
import com.sap.sailing.datamining.data.HasBravoFixContext;
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
import com.sap.sailing.datamining.data.HasCompetitorContext;
import com.sap.sailing.datamining.data.HasCompetitorDayContext;
import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
@@ -21,6 +22,7 @@ import com.sap.sailing.datamining.data.HasManeuverSpeedDetailsContext;
import com.sap.sailing.datamining.data.HasMarkPassingContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
@@ -111,6 +113,7 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
internalClasses.add(HasBravoFixContext.class);
internalClasses.add(HasBravoFixTrackContext.class);
internalClasses.add(HasFoilingSegmentContext.class);
internalClasses.add(HasTackTypeSegmentContext.class);
internalClasses.add(HasManeuverContext.class);
internalClasses.add(HasManeuverSpeedDetailsContext.class);
internalClasses.add(HasCompleteManeuverCurveWithEstimationDataContext.class);
@@ -119,6 +122,7 @@ public class Activator extends AbstractDataMiningActivatorWithPredefinedQueries
internalClasses.add(HasCompetitorDayContext.class);
internalClasses.add(HasLeaderboardGroupContext.class);
internalClasses.add(HasLeaderboardContext.class);
internalClasses.add(HasCompetitorContext.class);
return internalClasses;
}
@@ -5,6 +5,7 @@ import java.util.Collection;
import com.sap.sailing.datamining.data.HasBravoFixContext;
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
import com.sap.sailing.datamining.data.HasCompetitorContext;
import com.sap.sailing.datamining.data.HasCompetitorDayContext;
import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
@@ -16,6 +17,7 @@ import com.sap.sailing.datamining.data.HasManeuverSpeedDetailsContext;
import com.sap.sailing.datamining.data.HasMarkPassingContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
@@ -25,6 +27,7 @@ import com.sap.sailing.datamining.impl.components.BravoFixRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.BravoFixTrackRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompetitorDayRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompetitorRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompleteManeuverCurveWithEstimationDataRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.FoilingSegmentRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
@@ -34,6 +37,7 @@ import com.sap.sailing.datamining.impl.components.ManeuverRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.ManeuverSpeedDetailsRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TackTypeSegmentRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TrackedLegRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TrackedRaceRetrievalProcessor;
@@ -44,6 +48,7 @@ import com.sap.sailing.datamining.shared.ManeuverSettings;
import com.sap.sailing.datamining.shared.ManeuverSettingsImpl;
import com.sap.sailing.datamining.shared.ManeuverSpeedDetailsSettings;
import com.sap.sailing.datamining.shared.ManeuverSpeedDetailsSettingsImpl;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.server.interfaces.RacingEventService;
import com.sap.sse.datamining.components.DataRetrieverChainDefinition;
import com.sap.sse.datamining.impl.components.SimpleDataRetrieverChainDefinition;
@@ -59,6 +64,12 @@ public class SailingDataRetrievalChainDefinitions {
leaderboardRetrieverChainDefinition.startWith(LeaderboardGroupRetrievalProcessor.class, HasLeaderboardGroupContext.class, "LeaderboardGroup");
leaderboardRetrieverChainDefinition.endWith(LeaderboardGroupRetrievalProcessor.class, LeaderboardRetrievalProcessor.class,
HasLeaderboardContext.class, "Leaderboard");
dataRetrieverChainDefinitions.add(leaderboardRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasCompetitorContext> competitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
leaderboardRetrieverChainDefinition, HasCompetitorContext.class, "CompetitorSailingDomainRetrieverChain");
competitorRetrieverChainDefinition.endWith(LeaderboardRetrievalProcessor.class, CompetitorRetrievalProcessor.class, HasCompetitorContext.class, "CompetitorInLeaderboard");
dataRetrieverChainDefinitions.add(competitorRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasTrackedRaceContext> trackedRaceResultOfCompetitorRetrieverChainDefinition =
new SimpleDataRetrieverChainDefinition<>(leaderboardRetrieverChainDefinition, HasTrackedRaceContext.class, "TrackedRaceResultOfCompetitorRetrieverChain");
@@ -78,7 +89,9 @@ public class SailingDataRetrievalChainDefinitions {
//
final DataRetrieverChainDefinition<RacingEventService, HasRaceOfCompetitorContext> raceOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
trackedRaceRetrieverChainDefinition, HasRaceOfCompetitorContext.class, "RaceOfCompetitorSailingDomainRetrieverChain");
raceOfCompetitorRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, RaceOfCompetitorRetrievalProcessor.class, HasRaceOfCompetitorContext.class, "Competitor");
// use TackTypeSegmentsDataMiningSettings here to support the per-leg statistics about tack type segments
raceOfCompetitorRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, RaceOfCompetitorRetrievalProcessor.class, HasRaceOfCompetitorContext.class,
TackTypeSegmentsDataMiningSettings.class, TackTypeSegmentsDataMiningSettings.createDefaultSettings(), "Competitor");
dataRetrieverChainDefinitions.add(raceOfCompetitorRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasCompetitorDayContext> competitorDayRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
@@ -98,11 +111,23 @@ public class SailingDataRetrievalChainDefinitions {
HasFoilingSegmentContext.class, FoilingSegmentsDataMiningSettings.class, FoilingSegmentsDataMiningSettings.createDefaultSettings(), "FoilingSegments");
dataRetrieverChainDefinitions.add(foilingSegmentsRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasTackTypeSegmentContext> tackTypeSegmentsRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
raceOfCompetitorRetrieverChainDefinition, HasTackTypeSegmentContext.class, "tackTypeSegmentsRetrieverChainDefinition");
tackTypeSegmentsRetrieverChainDefinition.endWith(RaceOfCompetitorRetrievalProcessor.class, TackTypeSegmentRetrievalProcessor.class,
HasTackTypeSegmentContext.class, TackTypeSegmentsDataMiningSettings.class, TackTypeSegmentsDataMiningSettings.createDefaultSettings(), "TackTypeSegments");
dataRetrieverChainDefinitions.add(tackTypeSegmentsRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasTrackedLegContext> legRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
trackedRaceRetrieverChainDefinition, HasTrackedLegContext.class, "LegSailingDomainRetrieverChain");
legRetrieverChainDefinition.endWith(TrackedRaceRetrievalProcessor.class, TrackedLegRetrievalProcessor.class,
HasTrackedLegContext.class, "Leg");
dataRetrieverChainDefinitions.add(legRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasTrackedLegOfCompetitorContext> legOfCompetitorRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
trackedRaceRetrieverChainDefinition, HasTrackedLegOfCompetitorContext.class, "LegSailingDomainRetrieverChain");
legOfCompetitorRetrieverChainDefinition.addAfter(TrackedRaceRetrievalProcessor.class, TrackedLegRetrievalProcessor.class, HasTrackedLegContext.class, "Leg");
legRetrieverChainDefinition, HasTrackedLegOfCompetitorContext.class, "LegOfCompetitorSailingDomainRetrieverChain");
// use TackTypeSegmentsDataMiningSettings here to support the per-leg statistics about tack type segments
legOfCompetitorRetrieverChainDefinition.endWith(TrackedLegRetrievalProcessor.class, TrackedLegOfCompetitorRetrievalProcessor.class,
HasTrackedLegOfCompetitorContext.class, "LegOfCompetitor");
HasTrackedLegOfCompetitorContext.class, TackTypeSegmentsDataMiningSettings.class, TackTypeSegmentsDataMiningSettings.createDefaultSettings(), "LegOfCompetitor");
dataRetrieverChainDefinitions.add(legOfCompetitorRetrieverChainDefinition);
//
final DataRetrieverChainDefinition<RacingEventService, HasGPSFixContext> gpsFixRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
@@ -0,0 +1,12 @@
package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sse.datamining.annotations.Connector;
public interface HasCompetitorContext {
@Connector(messageKey="Leaderboard")
HasLeaderboardContext getLeaderboardContext();
@Connector
Competitor getCompetitor();
}
@@ -2,18 +2,24 @@ package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TackType;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Speed;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
public interface HasGPSFixContext {
@Connector(scanForStatistics = false)
public HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
HasTrackedLegOfCompetitorContext getTrackedLegOfCompetitorContext();
@Connector(ordinal = 1)
public GPSFixMoving getGPSFix();
GPSFixMoving getGPSFix();
@Dimension(messageKey="TackType", ordinal=6)
TackType getTackType() throws NoWindException;
@Statistic(messageKey = "TrueWindAngle")
Bearing getTrueWindAngle() throws NoWindException;
@@ -29,4 +35,7 @@ public interface HasGPSFixContext {
@Statistic(messageKey = "AbsoluteXTE", resultDecimals = 2)
Distance getAbsoluteXTE();
@Statistic(messageKey = "SmoothedSpeed", resultDecimals = 2)
Speed getSmoothedSpeed();
}
@@ -0,0 +1,13 @@
package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sse.datamining.annotations.Connector;
public interface HasGPSFixTrackContext {
@Connector(scanForStatistics=false)
HasRaceOfCompetitorContext getRaceOfCompetitorContext();
GPSFixTrack<Competitor, GPSFixMoving> getGPSFixTrack();
}
@@ -2,8 +2,10 @@ package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sse.common.Util;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
public interface HasLeaderboardContext {
@Connector(scanForStatistics=false)
@@ -15,9 +17,14 @@ public interface HasLeaderboardContext {
default String getName() {
return getLeaderboard().getName();
}
@Connector(messageKey="BoatClass", ordinal=2)
default BoatClass getBoatClass() {
return getLeaderboard().getBoatClass();
}
@Statistic(messageKey="NumberOfCompetitors", ordinal=3)
default int getNumberOfCompetitors() {
return Util.size(getLeaderboard().getCompetitors());
}
}
@@ -172,4 +172,10 @@ public interface HasRaceOfCompetitorContext {
@Statistic(messageKey="AverageRaceWindSpeed")
Speed getAverageRaceWindSpeed();
@Statistic(messageKey="RatioDurationLongVsShortTack", resultDecimals=2)
public double getRatioDurationLongVsShortTack();
@Statistic(messageKey="RatioDistanceLongVsShortTack", resultDecimals=2)
public double getRatioDistanceLongVsShortTack();
}
@@ -0,0 +1,38 @@
package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TackType;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
public interface HasTackTypeSegmentContext {
@Connector(scanForStatistics=false)
HasGPSFixTrackContext getGPSFixTrackContext();
TimePoint getStartOfTackTypeSegment();
TimePoint getEndOfTackTypeSegment();
@Dimension(messageKey="TackType")
TackType getTackType();
@Dimension(messageKey="LegType")
LegType getLegType() throws NoWindException;
@Dimension(messageKey="LegNumber")
int getLegNumber();
@Dimension(messageKey="TackTypeSegmentName")
String getName();
@Statistic(messageKey="TackTypeDuration")
Duration getDuration();
@Statistic(messageKey="TackTypeDistance")
Distance getDistance();
}
@@ -2,8 +2,10 @@ package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sse.common.Distance;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
public interface HasTrackedLegContext {
@@ -16,5 +18,6 @@ public interface HasTrackedLegContext {
public LegType getLegType();
@Dimension(messageKey="LegNumber", ordinal=7)
public int getLegNumber();
@Statistic(messageKey = "LengthOfTheLeg", resultDecimals = 2)
Distance getLegLength();
}
@@ -109,4 +109,10 @@ public interface HasTrackedLegOfCompetitorContext extends HasWindOnTrackedLeg {
@Statistic(messageKey="VMG", resultDecimals=2)
public Speed getVelocityMadeGood();
@Statistic(messageKey="RatioDurationLongVsShortTack", resultDecimals=2)
public double getRatioDurationLongVsShortTack();
@Statistic(messageKey="RatioDistanceLongVsShortTack", resultDecimals=2)
public double getRatioDistanceLongVsShortTack();
}
@@ -19,6 +19,12 @@ public interface HasWindFixContext extends HasWind {
@Statistic(messageKey="windSpeedKnots", resultDecimals=1, ordinal=2)
double getWindSpeedInKnots();
@Dimension(messageKey="InTrackingInterval")
boolean isInTrackingInterval();
@Dimension(messageKey="InRace")
boolean isInRace();
@Override
default TimePoint getTimePoint() {
@@ -0,0 +1,25 @@
package com.sap.sailing.datamining.impl.components;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasCompetitorContext;
import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.datamining.impl.data.CompetitorWithContext;
import com.sap.sse.common.Util;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class CompetitorRetrievalProcessor extends AbstractRetrievalProcessor<HasLeaderboardContext, HasCompetitorContext> {
public CompetitorRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasCompetitorContext, ?>> resultReceivers, int retrievalLevel,
String retrievedDataTypeMessageKey) {
super(HasLeaderboardContext.class, HasCompetitorContext.class, executor, resultReceivers, retrievalLevel,
retrievedDataTypeMessageKey);
}
@Override
protected Iterable<HasCompetitorContext> retrieveData(HasLeaderboardContext element) {
return Util.map(element.getLeaderboard().getCompetitors(), c->new CompetitorWithContext(c, element));
}
}
@@ -51,7 +51,7 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
TimePoint startOfSegment = null;
bravoFixTrack.lockForRead();
try {
for (final BravoFix bravoFix : bravoFixTrack.getFixes(startOfRace, /* fromInclusive */ true, end, /* toInclusive */ false)) {
for (final BravoFix bravoFix : bravoFixTrack.getFixes(startOfRace, /* fromInclusive */ true, end, /* toInclusive */ false)) { //geht ganzes Rennen durch
if (isAborted()) {
break;
}
@@ -61,10 +61,10 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
element.getTrackedRaceContext().getTrackedRace().getTrack(element.getCompetitor()).getEstimatedSpeed(bravoFix.getTimePoint())) <= 0)) ||
(settings.getMaximumSpeedNotFoiling() != null && settings.getMaximumSpeedNotFoiling().compareTo(
element.getTrackedRaceContext().getTrackedRace().getTrack(element.getCompetitor()).getEstimatedSpeed(bravoFix.getTimePoint())) <= 0);
if (currentFixIsFoiling != isFoiling) {
if (currentFixIsFoiling) {
if (currentFixIsFoiling != isFoiling) { //checken ob boot zum loop davor mit voherigem fix immernoch am fliegen ist, wenn nicht dann muss segment gemacht werden, wenn ja dann wird es zum segment ergänzt
if (currentFixIsFoiling) { //wenn ich vorher nicht am fliegen war und jetzt schon start von segment
startOfSegment = bravoFix.getTimePoint();
} else {
} else { // wenn ich vorher am fliegen war und jetzt nicht mehr, segment muss gebildet werden!!!!!
if (settings.getMinimumFoilingSegmentDuration() == null ||
startOfSegment.until(last).compareTo(settings.getMinimumFoilingSegmentDuration()) >= 0) {
addOrMergeFoilingSegment(element, foilingSegments, bravoFixTrack, startOfSegment,
@@ -72,7 +72,7 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
}
startOfSegment = null;
}
isFoiling = currentFixIsFoiling;
isFoiling = currentFixIsFoiling; //aktualisiert das es vorher nicht gleich war also entweder fliegen zuende oder gerade beginnt
}
last = bravoFix.getTimePoint();
}
@@ -26,17 +26,17 @@ public class GPSFixRetrievalProcessor extends AbstractRetrievalProcessor<HasTrac
@Override
protected Iterable<HasGPSFixContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
Collection<HasGPSFixContext> gpsFixesWithContext = new ArrayList<>();
final Collection<HasGPSFixContext> gpsFixesWithContext = new ArrayList<>();
final GPSFixTrack<Competitor, GPSFixMoving> competitorTrack = element.getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getTrack(element.getCompetitor());
competitorTrack.lockForRead();
try {
TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
final TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
for (GPSFixMoving gpsFix : competitorTrack.getFixes(trackedLegOfCompetitor.getStartTime(), true, trackedLegOfCompetitor.getFinishTime(), true)) {
if (isAborted()) {
break;
}
HasGPSFixContext gpsFixWithContext = new GPSFixWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
final HasGPSFixContext gpsFixWithContext = new GPSFixWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), gpsFix.getTimePoint()), gpsFix);
gpsFixesWithContext.add(gpsFixWithContext);
}
@@ -7,17 +7,26 @@ import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
import com.sap.sailing.datamining.impl.data.RaceOfCompetitorWithContext;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class RaceOfCompetitorRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedRaceContext, HasRaceOfCompetitorContext> {
/**
* Settings will be used to control the retrieval of tack type segments for the
* corresponding statistics such as distance/duration relation between long and
* short tack for the race of the competitor
*/
private final TackTypeSegmentsDataMiningSettings settings;
public RaceOfCompetitorRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasRaceOfCompetitorContext, ?>> resultReceivers, int retrievalLevel,
String retrievedDataTypeMessageKey) {
super(HasTrackedRaceContext.class, HasRaceOfCompetitorContext.class, executor, resultReceivers, retrievalLevel,
Collection<Processor<HasRaceOfCompetitorContext, ?>> resultReceivers,
TackTypeSegmentsDataMiningSettings settings, int retrievalLevel, String retrievedDataTypeMessageKey) {
super(HasTrackedRaceContext.class,
HasRaceOfCompetitorContext.class, executor, resultReceivers, retrievalLevel,
retrievedDataTypeMessageKey);
this.settings = settings;
}
@Override
@@ -28,7 +37,7 @@ public class RaceOfCompetitorRetrievalProcessor extends AbstractRetrievalProcess
if (isAborted()) {
break;
}
HasRaceOfCompetitorContext raceOfCompetitorWithContext = new RaceOfCompetitorWithContext(element, competitor);
HasRaceOfCompetitorContext raceOfCompetitorWithContext = new RaceOfCompetitorWithContext(element, competitor, settings);
raceOfCompetitorsWithContext.add(raceOfCompetitorWithContext);
}
}
@@ -0,0 +1,141 @@
package com.sap.sailing.datamining.impl.components;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.impl.data.GPSFixTrackWithContext;
import com.sap.sailing.datamining.impl.data.TackTypeSegmentWithContext;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TackType;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.MarkPassing;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.TimePoint;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class TackTypeSegmentRetrievalProcessor extends AbstractRetrievalProcessor<HasRaceOfCompetitorContext, HasTackTypeSegmentContext> {
private final TackTypeSegmentsDataMiningSettings settings;
public TackTypeSegmentRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasTackTypeSegmentContext, ?>> resultReceivers,
TackTypeSegmentsDataMiningSettings settings, int retrievalLevel, String retrievedDataTypeMessageKey) {
super(HasRaceOfCompetitorContext.class, HasTackTypeSegmentContext.class, executor, resultReceivers,
retrievalLevel, retrievedDataTypeMessageKey);
this.settings = settings;
}
@Override
public Iterable<HasTackTypeSegmentContext> retrieveData(HasRaceOfCompetitorContext element) {
List<HasTackTypeSegmentContext> tackTypeSegments = new ArrayList<>();
final TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace();
final TimePoint startOfRace = element.getTrackedRaceContext().getTrackedRace().getStartOfRace();
final Competitor competitor = element.getCompetitor();
if (startOfRace != null) {
final GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack = trackedRace.getTrack(element.getCompetitor());
if (gpsFixTrack != null) {
final Iterator<MarkPassing> markPassingIterator = trackedRace.getMarkPassings(competitor).iterator();
if (markPassingIterator.hasNext()) { // only search for tack type segments if the competitor has started the race
MarkPassing legStartMarkPassing = markPassingIterator.next();
TrackedLegOfCompetitor trackedLegOfCompetitor = trackedRace.getTrackedLegStartingAt(legStartMarkPassing.getWaypoint()).getTrackedLeg(competitor);
MarkPassing nextMarkPassing = markPassingIterator.hasNext() ? markPassingIterator.next() : null;
final Waypoint finish = trackedRace.getRace().getCourse().getLastWaypoint();
TackType currentTackType = null;
boolean segmentEmpty = true;
TackType nextTackType = null;
TimePoint startOfCurrentSegment = legStartMarkPassing.getTimePoint();
GPSFix gpsFix = null;
gpsFixTrack.lockForRead();
try {
// run through all of the competitor's fixes, starting at the first mark passing and finishing when there are
// no more fixes left or the finish mark passing has been reached
for (final Iterator<GPSFixMoving> i=gpsFixTrack.getFixesIterator(startOfCurrentSegment, /* fromInclusive */ true);
i.hasNext() && legStartMarkPassing.getWaypoint() != finish; ) {
if (isAborted()) {
break;
}
gpsFix = i.next();
while (nextMarkPassing != null && !gpsFix.getTimePoint().before(nextMarkPassing.getTimePoint())) {
// reached leg's end; complete the current segment if not empty and move through mark passings
// iterator until having found the leg the gpsFix is in, while moving the trackedLegOfCompetitor along
legStartMarkPassing = nextMarkPassing;
if (!segmentEmpty) {
addOrMergeTackTypeSegment(element, tackTypeSegments, gpsFixTrack, startOfCurrentSegment,
nextMarkPassing.getTimePoint(), currentTackType);
segmentEmpty = gpsFix.getTimePoint().equals(nextMarkPassing.getTimePoint()); // if the fix is exactly at leg start
startOfCurrentSegment = nextMarkPassing.getTimePoint();
}
// if nextMarkPassing is last MarkPassing there will be no leg after, trackedLeg is null
trackedLegOfCompetitor = nextMarkPassing.getWaypoint()==finish ? null : trackedRace.getTrackedLegStartingAt(nextMarkPassing.getWaypoint()).getTrackedLeg(competitor);
nextMarkPassing = markPassingIterator.hasNext() ? markPassingIterator.next() : null;
}
try {
// no null case like line 87, because for loop checks that mark passing at leg start is not finish mark passing
nextTackType = trackedLegOfCompetitor == null ? null : trackedLegOfCompetitor.getTackType(gpsFix.getTimePoint());
} catch (NoWindException e) {
nextTackType = null;
}
// invariant: nextMarkPassing is either null or after gpsFix's time and representing the passing of the mark at the end
// of the leg gpsFix is in; trackedLegOfCompetitor corresponds to the leg gpsFix is in
if (!segmentEmpty && nextTackType != currentTackType) {
addOrMergeTackTypeSegment(element, tackTypeSegments, gpsFixTrack, startOfCurrentSegment,
gpsFix.getTimePoint() /* don't include the last interval ending at the non-TackType fix */, currentTackType);
segmentEmpty = true; // because gpsFix is now exactly at the beginning of the new segment
startOfCurrentSegment = gpsFix.getTimePoint();
} else {
segmentEmpty = false; // gpsFix is in the current segment
}
currentTackType = nextTackType;
}
} finally {
gpsFixTrack.unlockAfterRead();
}
if (!segmentEmpty) {
addOrMergeTackTypeSegment(element, tackTypeSegments, gpsFixTrack, startOfCurrentSegment, gpsFix.getTimePoint(), currentTackType);
// no need to update segmentEmpty / startOfCurrentSegment / lastTackType because now we're done
}
}
}
}
return tackTypeSegments;
}
private void addOrMergeTackTypeSegment(HasRaceOfCompetitorContext element,
List<HasTackTypeSegmentContext> tackTypeSegments, final GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack,
TimePoint startOfSegment, TimePoint endOfSegment, TackType tackType) {
if (settings.getMinimumTackTypeSegmentDuration() == null || startOfSegment.until(endOfSegment)
.compareTo(settings.getMinimumTackTypeSegmentDuration()) >= 0) {
if (tackTypeSegments.isEmpty() || settings.getMinimumDurationBetweenAdjacentTackTypeSegments() == null) {
tackTypeSegments.add(createTackTypeSegment(startOfSegment, endOfSegment, element, gpsFixTrack, tackType));
} else {
// we wouldn't want to merge segments with different tack types; different from foiling segments where you *would* want to join to closely-adjacent foiled segments
final HasTackTypeSegmentContext previousSegment = tackTypeSegments.get(tackTypeSegments.size()-1);
final TimePoint previousEnd = previousSegment.getEndOfTackTypeSegment();
if (previousSegment.getTackType() == tackType && previousEnd.until(startOfSegment).compareTo(settings.getMinimumDurationBetweenAdjacentTackTypeSegments()) < 0) {
// merge:
tackTypeSegments.set(tackTypeSegments.size()-1, createTackTypeSegment(previousSegment.getStartOfTackTypeSegment(), endOfSegment, element, gpsFixTrack, tackType));
} else {
// add; duration between the segments is large enough or tack type is different
tackTypeSegments.add(createTackTypeSegment(startOfSegment, endOfSegment, element, gpsFixTrack, tackType));
}
}
}
}
private HasTackTypeSegmentContext createTackTypeSegment(TimePoint startOfSegment, TimePoint endOfSegment,
HasRaceOfCompetitorContext raceOfCompetitorContext, GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack, TackType tackType) {
return new TackTypeSegmentWithContext(new GPSFixTrackWithContext(raceOfCompetitorContext, gpsFixTrack), startOfSegment, endOfSegment, tackType);
}
}
@@ -7,17 +7,25 @@ import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.datamining.impl.data.TrackedLegOfCompetitorWithContext;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class TrackedLegOfCompetitorRetrievalProcessor extends AbstractRetrievalProcessor<HasTrackedLegContext, HasTrackedLegOfCompetitorContext> {
/**
* Settings will be used to control the retrieval of tack type segments for the
* corresponding statistics such as distance/duration relation between long and
* short tack for the leg of the competitor
*/
private final TackTypeSegmentsDataMiningSettings settings;
public TrackedLegOfCompetitorRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasTrackedLegOfCompetitorContext, ?>> resultReceivers, int retrievalLevel,
String retrievedDataTypeMessageKey) {
Collection<Processor<HasTrackedLegOfCompetitorContext, ?>> resultReceivers,
TackTypeSegmentsDataMiningSettings settings, int retrievalLevel, String retrievedDataTypeMessageKey) {
super(HasTrackedLegContext.class, HasTrackedLegOfCompetitorContext.class, executor, resultReceivers,
retrievalLevel, retrievedDataTypeMessageKey);
this.settings = settings;
}
@Override
@@ -27,7 +35,7 @@ public class TrackedLegOfCompetitorRetrievalProcessor extends AbstractRetrievalP
if (isAborted()) {
break;
}
HasTrackedLegOfCompetitorContext trackedLegOfCompetitorWithContext = new TrackedLegOfCompetitorWithContext(element, element.getTrackedLeg().getTrackedLeg(competitor));
HasTrackedLegOfCompetitorContext trackedLegOfCompetitorWithContext = new TrackedLegOfCompetitorWithContext(element, element.getTrackedLeg().getTrackedLeg(competitor), settings);
trackedLegOfCompetitorsWithContext.add(trackedLegOfCompetitorWithContext);
}
return trackedLegOfCompetitorsWithContext;
@@ -17,9 +17,10 @@ import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class TrackedRaceRetrievalProcessor extends AbstractRetrievalProcessor<HasLeaderboardContext, HasTrackedRaceContext> {
public TrackedRaceRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasTrackedRaceContext, ?>> resultReceivers, int retrievalLevel,
String retrievedDataTypeMessageKey) {
super(HasLeaderboardContext.class, HasTrackedRaceContext.class, executor, resultReceivers, retrievalLevel,
Collection<Processor<HasTrackedRaceContext, ?>> resultReceivers,
int retrievalLevel, String retrievedDataTypeMessageKey) {
super(HasLeaderboardContext.class,
HasTrackedRaceContext.class, executor, resultReceivers, retrievalLevel,
retrievedDataTypeMessageKey);
}
@@ -38,5 +38,4 @@ public class CompetitorDayWithContext implements HasCompetitorDayContext {
public String getDayAsISO() {
return raceOfCompetitor.getTrackedRaceContext().getDayAsISO();
}
}
@@ -0,0 +1,51 @@
package com.sap.sailing.datamining.impl.data;
import com.sap.sailing.datamining.data.HasCompetitorContext;
import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.domain.base.Competitor;
public class CompetitorWithContext implements HasCompetitorContext {
private final Competitor competitor;
private final HasLeaderboardContext leaderboardContext;
public CompetitorWithContext(Competitor competitor, HasLeaderboardContext leaderboardContext) {
super();
this.competitor = competitor;
this.leaderboardContext = leaderboardContext;
}
@Override
public Competitor getCompetitor() {
return competitor;
}
@Override
public HasLeaderboardContext getLeaderboardContext() {
return leaderboardContext;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((competitor == null) ? 0 : competitor.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CompetitorWithContext other = (CompetitorWithContext) obj;
if (competitor == null) {
if (other.competitor != null)
return false;
} else if (!competitor.equals(other.competitor))
return false;
return true;
}
}
@@ -0,0 +1,29 @@
package com.sap.sailing.datamining.impl.data;
import com.sap.sailing.datamining.data.HasGPSFixTrackContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
public class GPSFixTrackWithContext implements HasGPSFixTrackContext {
private final HasRaceOfCompetitorContext raceOfCompetitorContext;
private final GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack;
public GPSFixTrackWithContext(HasRaceOfCompetitorContext raceOfCompetitorContext, GPSFixTrack<Competitor, GPSFixMoving> gpsFixTrack) {
this.raceOfCompetitorContext = raceOfCompetitorContext;
this.gpsFixTrack = gpsFixTrack;
}
@Override
public HasRaceOfCompetitorContext getRaceOfCompetitorContext() {
return raceOfCompetitorContext;
}
@Override
public GPSFixTrack<Competitor, GPSFixMoving> getGPSFixTrack() {
return gpsFixTrack;
}
}
@@ -4,10 +4,12 @@ import com.sap.sailing.datamining.data.HasGPSFixContext;
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.SpeedWithBearing;
import com.sap.sailing.domain.common.TackType;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Speed;
import com.sap.sse.common.TimePoint;
/**
@@ -89,4 +91,20 @@ public class GPSFixWithContext implements HasGPSFixContext {
public Distance getAbsoluteXTE() {
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getAbsoluteCrossTrackError(getTimePoint());
}
@Override
public TackType getTackType() throws NoWindException {
return getTrackedLegOfCompetitorContext().getTrackedLegOfCompetitor().getTackType(getTimePoint());
}
@Override
public Speed getSmoothedSpeed() {
final SpeedWithBearing result;
if (getGPSFix().isEstimatedSpeedCached()) {
result = getGPSFix().getCachedEstimatedSpeed();
} else {
result = getTrackedLegOfCompetitorContext().getTrackedRace().getTrack(getTrackedLegOfCompetitorContext().getCompetitor()).getEstimatedSpeed(getTimePoint());
}
return result;
}
}
@@ -11,7 +11,10 @@ import java.util.function.BiFunction;
import com.sap.sailing.datamining.Activator;
import com.sap.sailing.datamining.SailingClusterGroups;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.data.HasTrackedRaceContext;
import com.sap.sailing.datamining.impl.components.TackTypeSegmentRetrievalProcessor;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
@@ -53,10 +56,12 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
private final HasTrackedRaceContext trackedRaceContext;
private final Competitor competitor;
private final TackTypeSegmentsDataMiningSettings settings;
public RaceOfCompetitorWithContext(HasTrackedRaceContext trackedRaceContext, Competitor competitor) {
public RaceOfCompetitorWithContext(HasTrackedRaceContext trackedRaceContext, Competitor competitor, TackTypeSegmentsDataMiningSettings settings) {
this.trackedRaceContext = trackedRaceContext;
this.competitor = competitor;
this.settings = settings;
}
@Override
@@ -662,4 +667,51 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
Integer rank = getTrackedRace().getRank(getCompetitor(), timePoint);
return rank == 0 ? null : rank;
}
@Override
public double getRatioDurationLongVsShortTack() {
final TackTypeRatioCollector<Duration> resultProcessor = new TackTypeRatioCollector<Duration>(Duration.NULL) {
@Override
protected Duration add(Duration a, Duration b) {
return a.plus(b);
}
@Override
protected double divide(Duration a, Duration b) {
return a.divide(b);
}
@Override
protected Duration getAddable(HasTackTypeSegmentContext element) {
return element.getDuration();
}
};
final TackTypeSegmentRetrievalProcessor tackTypeSegmentRetriever = new TackTypeSegmentRetrievalProcessor(
/* executor */ null,
Collections.emptySet(), settings, 0, "TackTypeSegments");
return Util.stream(tackTypeSegmentRetriever.retrieveData(this)).collect(resultProcessor);
}
@Override
public double getRatioDistanceLongVsShortTack() {
final TackTypeRatioCollector<Distance> resultProcessor = new TackTypeRatioCollector<Distance>(Distance.NULL) {
@Override
protected Distance add(Distance a, Distance b) {
return a.add(b);
}
@Override
protected double divide(Distance a, Distance b) {
return a.divide(b);
}
@Override
protected Distance getAddable(HasTackTypeSegmentContext element) {
return element.getDistance();
}
};
final TackTypeSegmentRetrievalProcessor tackTypeSegmentRetriever = new TackTypeSegmentRetrievalProcessor(/* executor */ null,
Collections.emptySet(), settings, 0, "TackTypeSegments");
return Util.stream(tackTypeSegmentRetriever.retrieveData(this)).collect(resultProcessor);
}
}
@@ -0,0 +1,78 @@
package com.sap.sailing.datamining.impl.data;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.domain.common.TackType;
public abstract class TackTypeRatioCollector<ADDABLE> implements Collector<HasTackTypeSegmentContext, Map<TackType, ADDABLE>, Double> {
private final ADDABLE nullValue;
public TackTypeRatioCollector(ADDABLE nullValue) {
this.nullValue = nullValue;
}
@Override
public Supplier<Map<TackType, ADDABLE>> supplier() {
return ()->{
final Map<TackType, ADDABLE> result = new HashMap<>();
for (final TackType tt : TackType.values()) {
result.put(tt, nullValue);
}
return result;
};
}
@Override
public BiConsumer<Map<TackType, ADDABLE>, HasTackTypeSegmentContext> accumulator() {
return (sumPerTackType, element)->{
final TackType tt = element.getTackType();
synchronized (this) {
sumPerTackType.put(tt, add(sumPerTackType.get(tt), getAddable(element)));
}
};
}
@Override
public BinaryOperator<Map<TackType, ADDABLE>> combiner() {
return (r1, r2) -> {
for (final Entry<TackType, ADDABLE> e : r1.entrySet()) {
r2.put(e.getKey(), add(e.getValue(), r2.get(e.getKey())));
}
return r2;
};
}
@Override
public Function<Map<TackType, ADDABLE>, Double> finisher() {
return sumPerTackType->{
final ADDABLE shortTackSum = sumPerTackType.get(TackType.SHORTTACK);
return shortTackSum.equals(nullValue) ? null : divide(sumPerTackType.get(TackType.LONGTACK), shortTackSum);
};
}
@Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
protected abstract ADDABLE add(ADDABLE a, ADDABLE b);
protected abstract double divide(ADDABLE a, ADDABLE b);
protected abstract ADDABLE getAddable(HasTackTypeSegmentContext element);
}
@@ -0,0 +1,106 @@
package com.sap.sailing.datamining.impl.data;
import java.text.SimpleDateFormat;
import com.sap.sailing.datamining.data.HasGPSFixTrackContext;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TackType;
import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
public class TackTypeSegmentWithContext implements HasTackTypeSegmentContext {
private final HasGPSFixTrackContext gpsFixTrackContext;
private final TimePoint startOfTackTypeSegment;
private final TimePoint endOfTackTypeSegment; // TODO is this exclusive or inclusive? Suggestion: it should be exclusive, as usual in most Java interval specifications; please comment accordingly
private final TackType tackType;
private static final SimpleDateFormat TIMEPOINT_FORMATTER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public TackTypeSegmentWithContext(GPSFixTrackWithContext gpsFixTrackWithContext, TimePoint startOfTackTypeSegment,
TimePoint endOfTackTypeSegment, TackType tackType) {
super();
this.gpsFixTrackContext = gpsFixTrackWithContext;
this.startOfTackTypeSegment = startOfTackTypeSegment;
this.endOfTackTypeSegment = endOfTackTypeSegment;
this.tackType = tackType;
}
@Override
public String getName() {
return gpsFixTrackContext.getRaceOfCompetitorContext().getCompetitor().getName() + "@"
+ TIMEPOINT_FORMATTER.format(startOfTackTypeSegment.asDate());
}
@Override
public HasGPSFixTrackContext getGPSFixTrackContext() {
return gpsFixTrackContext;
}
@Override
public TimePoint getStartOfTackTypeSegment() {
return startOfTackTypeSegment;
}
@Override
public TimePoint getEndOfTackTypeSegment() {
return endOfTackTypeSegment;
}
@Override
public Duration getDuration() {
return getStartOfTackTypeSegment().until(getEndOfTackTypeSegment());
}
@Override
public Distance getDistance() {
return getGpsFixTrack().
getDistanceTraveled(getStartOfTackTypeSegment(), getEndOfTackTypeSegment());
}
private GPSFixTrack<Competitor, GPSFixMoving> getGpsFixTrack() {
return getTrackedRace().getTrack(getCompetitor());
}
private Competitor getCompetitor() {
return getGPSFixTrackContext().getRaceOfCompetitorContext().getCompetitor();
}
private TrackedRace getTrackedRace() {
return getGPSFixTrackContext().getRaceOfCompetitorContext().getTrackedRaceContext().getTrackedRace();
}
@Override
public TackType getTackType() {
return tackType;
}
@Override
public LegType getLegType() throws NoWindException {
return getTrackedLeg().getLegType(
getStartOfTackTypeSegment().plus(getStartOfTackTypeSegment().until(getEndOfTackTypeSegment()).divide(2)));
}
@Override
public int getLegNumber() {
final TrackedLeg trackedLeg = getTrackedLeg();
return trackedLeg == null ? 0 : getTrackedRace().getRace().getCourse().getIndexOfWaypoint(trackedLeg.getLeg().getTo());
}
private TrackedLeg getTrackedLeg() {
return getTrackedRace().getTrackedLeg(getCompetitor(), getStartOfTackTypeSegment()).getTrackedLeg();
}
@Override
public String toString() {
return "TackTypeSegmentWithContext [gpsFixTrackContext=" + gpsFixTrackContext + ", startOfTackTypeSegment="
+ startOfTackTypeSegment + ", endOfTackTypeSegment=" + endOfTackTypeSegment + ", tackType=" + tackType
+ "]";
}
}
@@ -10,8 +10,11 @@ import java.util.function.Supplier;
import com.sap.sailing.datamining.Activator;
import com.sap.sailing.datamining.SailingClusterGroups;
import com.sap.sailing.datamining.data.HasTackTypeSegmentContext;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.datamining.impl.components.TackTypeSegmentRetrievalProcessor;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Leg;
@@ -44,6 +47,7 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
private static final long serialVersionUID = 5944904146286262768L;
private final HasTrackedLegContext trackedLegContext;
private final TackTypeSegmentsDataMiningSettings settings;
private final TrackedLegOfCompetitor trackedLegOfCompetitor;
private final Competitor competitor;
@@ -54,10 +58,11 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
private boolean isRankAtFinishInitialized;
private Wind wind;
public TrackedLegOfCompetitorWithContext(HasTrackedLegContext trackedLegContext, TrackedLegOfCompetitor trackedLegOfCompetitor) {
public TrackedLegOfCompetitorWithContext(HasTrackedLegContext trackedLegContext, TrackedLegOfCompetitor trackedLegOfCompetitor, TackTypeSegmentsDataMiningSettings settings) {
this.trackedLegContext = trackedLegContext;
this.trackedLegOfCompetitor = trackedLegOfCompetitor;
this.competitor = trackedLegOfCompetitor.getCompetitor();
this.settings = settings;
}
@Override
@@ -516,4 +521,56 @@ public class TrackedLegOfCompetitorWithContext implements HasTrackedLegOfCompeti
final TimePoint finishTime = getTrackedLegOfCompetitor().getFinishTime();
return getTrackedLegOfCompetitor().getAverageVelocityMadeGood(finishTime == null ? TimePoint.now() : finishTime);
}
@Override
public double getRatioDurationLongVsShortTack() {
final TackTypeRatioCollector<Duration> resultProcessor = new TackTypeRatioCollector<Duration>(Duration.NULL) {
@Override
protected Duration add(Duration a, Duration b) {
return a.plus(b);
}
@Override
protected double divide(Duration a, Duration b) {
return a.divide(b);
}
@Override
protected Duration getAddable(HasTackTypeSegmentContext element) {
return element.getDuration();
}
};
final TackTypeSegmentRetrievalProcessor tackTypeSegmentRetriever = new TackTypeSegmentRetrievalProcessor(
/* executor */ null,
Collections.emptySet(), settings, 0, "TackTypeSegments");
return Util.stream(tackTypeSegmentRetriever.retrieveData(
new RaceOfCompetitorWithContext(getTrackedLegContext().getTrackedRaceContext(), competitor, settings)))
.filter(tt->tt.getLegNumber() == getTrackedLegContext().getLegNumber()).collect(resultProcessor);
}
@Override
public double getRatioDistanceLongVsShortTack() {
final TackTypeRatioCollector<Distance> resultProcessor = new TackTypeRatioCollector<Distance>(Distance.NULL) {
@Override
protected Distance add(Distance a, Distance b) {
return a.add(b);
}
@Override
protected double divide(Distance a, Distance b) {
return a.divide(b);
}
@Override
protected Distance getAddable(HasTackTypeSegmentContext element) {
return element.getDistance();
}
};
final TackTypeSegmentRetrievalProcessor tackTypeSegmentRetriever = new TackTypeSegmentRetrievalProcessor(
/* executor */ null,
Collections.emptySet(), settings, 0, "TackTypeSegments");
return Util.stream(tackTypeSegmentRetriever.retrieveData(
new RaceOfCompetitorWithContext(getTrackedLegContext().getTrackedRaceContext(), competitor, settings)))
.filter(tt->tt.getLegNumber() == getTrackedLegContext().getLegNumber()).collect(resultProcessor);
}
}
@@ -3,6 +3,7 @@ package com.sap.sailing.datamining.impl.data;
import java.util.function.BiFunction;
import com.sap.sailing.datamining.data.HasTrackedLegContext;
import com.sap.sailing.datamining.shared.TackTypeSegmentsDataMiningSettings;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sse.common.TimePoint;
@@ -26,7 +27,7 @@ public class TrackedLegOfCompetitorWithSpecificTimePointWithContext extends Trac
public TrackedLegOfCompetitorWithSpecificTimePointWithContext(HasTrackedLegContext trackedLegContext,
TrackedLegOfCompetitor trackedLegOfCompetitor, TimePoint timePoint) {
super(trackedLegContext, trackedLegOfCompetitor);
super(trackedLegContext, trackedLegOfCompetitor, TackTypeSegmentsDataMiningSettings.createDefaultSettings());
this.timePoint = timePoint;
}
@@ -6,6 +6,7 @@ import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.tracking.TrackedLeg;
import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sse.common.Distance;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
@@ -97,5 +98,9 @@ public class TrackedLegWithContext implements HasTrackedLegContext {
}
return at;
}
@Override
public Distance getLegLength() {
return getTrackedLeg().getWindwardDistance();
}
}
@@ -3,6 +3,8 @@ package com.sap.sailing.datamining.impl.data;
import com.sap.sailing.datamining.data.HasWindFixContext;
import com.sap.sailing.datamining.data.HasWindTrackContext;
import com.sap.sailing.domain.common.Wind;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.impl.TimeRangeImpl;
/**
* Equality is based on the {@link #getWind() wind fix} only.
@@ -72,6 +74,18 @@ public class WindFixWithContext implements HasWindFixContext {
return windSourceType;
}
@Override
public boolean isInTrackingInterval() {
final TrackedRace trackedRace = getWindTrackContext().getTrackedRaceContext().getTrackedRace();
return trackedRace != null && new TimeRangeImpl(trackedRace.getStartOfTracking(), trackedRace.getEndOfTracking()).includes(getTimePoint());
}
@Override
public boolean isInRace() {
final TrackedRace trackedRace = getWindTrackContext().getTrackedRaceContext().getTrackedRace();
return trackedRace != null && new TimeRangeImpl(trackedRace.getStartOfRace(), trackedRace.getEndOfRace()).includes(getTimePoint());
}
@Override
public String toString() {
return "WindFixWithContext [trackedRaceContext=" + windTrackContext + ", windSourceType=" + windSourceType
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/com.sap.sailing.declination/src/com/sap/sailing/declination/impl/DeclinationStore.java"/>
</listAttribute>
@@ -8,6 +9,6 @@
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.sap.sailing.declination.impl.DeclinationStore"/>
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="com.sap.sailing.declination"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="2022 2022 1"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="2024 2024 1"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.declination"/>
</launchConfiguration>
File diff suppressed because it is too large Load Diff
@@ -89,15 +89,17 @@ public class AbstractPosition implements Position {
@Override
public Bearing getBearingGreatCircle(Position p) {
Bearing bearing = null;
final Bearing bearing;
if (p != null) {
double result = Math.atan2(Math.sin(p.getLngRad() - getLngRad()) * Math.cos(p.getLatRad()),
Math.cos(getLatRad()) * Math.sin(p.getLatRad()) - Math.sin(getLatRad()) * Math.cos(p.getLatRad())
* Math.cos(p.getLngRad() - getLngRad()));
Math.cos(getLatRad()) * Math.sin(p.getLatRad())
- Math.sin(getLatRad()) * Math.cos(p.getLatRad()) * Math.cos(p.getLngRad() - getLngRad()));
if (result < 0) {
result = result + 2 * Math.PI;
}
bearing = new RadianBearingImpl(result);
} else {
bearing = null;
}
return bearing;
}
@@ -24,6 +24,7 @@ import com.sap.sse.security.shared.HasPermissions.Action;
*
*/
public enum DetailType implements Serializable {
LEG_TACKTYPE_LONGTACK_SHORTTACK(0, ASCENDING, PREMIUM_LEADERBOARD_INFORMATION, "TACKTYPE"),
LEG_DISTANCE_TRAVELED(0, ASCENDING, PREMIUM_LEADERBOARD_INFORMATION, "DISTANCE_TRAVELED"),
LEG_DISTANCE_TRAVELED_INCLUDING_GATE_START(0, ASCENDING, null, "DISTANCE_TRAVELED_INCLUDING_GATE_START"),
LEG_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS(2, DESCENDING, PREMIUM_LEADERBOARD_INFORMATION, "AVERAGE_SPEED_OVER_GROUND_IN_KNOTS"),
@@ -220,6 +221,13 @@ public enum DetailType implements Serializable {
private final String[] oldNames;
/**
* @param precision
* the number of decimal digits in which they are usually provided and should be formatted
* @param premiumAction
* If not {@code null} then the user must have permission to execute this action on the leaderboard to
* which it is applied.
*/
DetailType(int precision, SortingOrder defaultSortingOrder, Action premiumAction, String... oldNames) {
this.oldNames = oldNames;
this.precision = precision;
@@ -227,6 +235,9 @@ public enum DetailType implements Serializable {
this.defaultSortingOrder = defaultSortingOrder;
}
/**
* @return the number of decimal digits in which they are usually provided and should be formatted
*/
public int getPrecision() {
return precision;
}
@@ -274,6 +285,7 @@ public enum DetailType implements Serializable {
*/
public static Collection<DetailType> getAutoplayDetailTypesForChart() {
final Collection<DetailType> availableDetailsTypes = new LinkedHashSet<>();
availableDetailsTypes.add(DetailType.LEG_TACKTYPE_LONGTACK_SHORTTACK);
availableDetailsTypes.add(DetailType.CHART_WINDWARD_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD);
availableDetailsTypes.add(DetailType.LEG_CURRENT_SPEED_OVER_GROUND_IN_KNOTS);
availableDetailsTypes.add(DetailType.LEG_DISTANCE_TRAVELED);
@@ -0,0 +1,14 @@
package com.sap.sailing.domain.common;
/**
* The TackType describes how the boat is driving in relation to the next mark.
*/
public enum TackType {
/**
* The long tack takes you back towards the windline that goes though the next mark. It is the longer tack in a leg.
*/
LONGTACK,
/**
* The short tack takes you away from the windline that goes though the next mark. It is the shorter tack in a leg.
*/
SHORTTACK
}
@@ -55,7 +55,7 @@ public class DataImportProgressImpl implements DataImportProgress {
@Override
public void setCurrentSubProgress(DataImportSubProgress subProgress) {
if (subProgress != currentSubProgress) {
logger.info("Master data import with operation ID "+getOperationId()+" moving from stage "+currentSubProgressPct+" to "+subProgress);
logger.info("Master data import with operation ID "+getOperationId()+" moving from stage "+currentSubProgress+" to "+subProgress);
}
currentSubProgress = subProgress;
}
@@ -35,6 +35,7 @@ public class WindImpl extends KnotSpeedWithBearingImpl implements Wind {
public static int hashCode(double latDeg, double lngDeg, long timePointAsMillis) {
return (31 * (int) (timePointAsMillis & Integer.MAX_VALUE)) ^ (int) (Math.round(latDeg)*Math.round(lngDeg));
}
/**
* Wind hash is determined based on time point and position only to speed this up a little.
*/
@@ -66,7 +66,8 @@ public class SecuredDomainType extends HasPermissionsImpl {
EXPORT,
SIMULATOR,
VIEWSTREAMLETS,
VIEWANALYSISCHARTS;
VIEWANALYSISCHARTS,
COLORED_TAILS;
private static final Action[] ALL_ACTIONS = DefaultActions.plus(TrackedRaceActions.values());
@@ -28,6 +28,8 @@ public class PremiumRole extends RolePrototype {
.withActions(SecuredSecurityTypes.UserActions.BE_PREMIUM).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.TRACKED_RACE)
.withActions(SecuredDomainType.TrackedRaceActions.VIEWANALYSISCHARTS).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.TRACKED_RACE)
.withActions(SecuredDomainType.TrackedRaceActions.COLORED_TAILS).build(),
WildcardPermission.builder().withTypes(SecuredDomainType.LEADERBOARD)
.withActions(SecuredDomainType.LeaderboardActions.PREMIUM_LEADERBOARD_INFORMATION).build());
}
@@ -46,4 +46,5 @@ public interface BravoFix extends SensorFix {
@Statistic(messageKey = "heel", resultDecimals = 1)
Bearing getHeel();
}
@@ -41,8 +41,6 @@ public class Activator implements BundleActivator {
private static final Logger logger = Logger.getLogger(Activator.class.getName());
private static Activator INSTANCE;
private static final String DEFAULT_CLIENT_ID = "d29eae61621af3057db0e638232a027e96b1d2291b1b89a1481dfcac075b0bf4";
private static final String DEFAULT_CLIENT_SECRET = "537dbd14a84fcb470c91d85e8c4f8f7a356ac5ffc8727594d1bfe900ee5942ef";
private static final String DEFAULT_REDIRECT_PROTOCOL = "https";
private static final String DEFAULT_REDIRECT_HOST = "www.sapsailing.com";
private static final String DEFAULT_REDIRECT_PORT = null; // port==null means default
@@ -60,8 +58,8 @@ public class Activator implements BundleActivator {
public Activator() throws ClientProtocolException, IllegalStateException, IOException, ParseException {
logger.info(getClass().getName()+" constructor");
final String clientId = System.getProperty(CLIENT_ID_PROPERTY_NAME, DEFAULT_CLIENT_ID);
final String clientSecret = System.getProperty(CLIENT_SECRET_PROPERTY_NAME, DEFAULT_CLIENT_SECRET);
final String clientId = System.getProperty(CLIENT_ID_PROPERTY_NAME);
final String clientSecret = System.getProperty(CLIENT_SECRET_PROPERTY_NAME);
final String clientRedirectProtocol = System.getProperty(CLIENT_REDIRECT_PROTOCOL_PROPERTY_NAME, DEFAULT_REDIRECT_PROTOCOL);
final String clientRedirectHost = System.getProperty(CLIENT_REDIRECT_HOST_PROPERTY_NAME, DEFAULT_REDIRECT_HOST);
final String clientRedirectPort = System.getProperty(CLIENT_REDIRECT_PORT_PROPERTY_NAME, DEFAULT_REDIRECT_PORT);
@@ -17,7 +17,8 @@ Require-Bundle: com.sap.sailing.domain,
com.sap.sailing.xrr.schema,
com.sap.sailing.domain.shared.android,
com.sun.xml.bind.jaxb-impl;bundle-version="2.3.0",
com.sap.sse.security.common
com.sap.sse.security.common,
com.sap.sailing.manage2sail
Export-Package: com.sap.sailing.domain.swisstimingadapter,
com.sap.sailing.domain.swisstimingadapter.impl;x-friends:="com.sap.sailing.server.test,com.sap.sailing.mongodb.test,com.sap.sailing.domain.swisstimingadapter.persistence"
Import-Package: com.sap.sailing.xrr.schema,
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.swisstimingadapter;
import java.io.IOException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.List;
import javax.xml.bind.JAXBException;
@@ -19,8 +18,6 @@ public interface SwissTimingAdapter {
String NAME = "SwissTiming";
String DEFAULT_URL = null;
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname, int port) throws InterruptedException, UnknownHostException, IOException, ParseException;
/**
* @param regattaToAddTo
* if <code>null</code>, an existing regatta by the name of the TracTrac event with the boat class name
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.DecimalFormat;
@@ -568,7 +569,7 @@ public abstract class AbstractSailMasterConnector extends SailMasterTransceiverI
+ " which seems to be OK. I think we're connected in "+this+"!");
}
}
} catch (IOException e) {
} catch (IOException | URISyntaxException e) {
logger.log(Level.INFO, "Exception trying to establish connection in "+this+". Trying again in 1s.", e);
disconnectAndWaitABit();
}
@@ -576,7 +577,7 @@ public abstract class AbstractSailMasterConnector extends SailMasterTransceiverI
}
}
protected abstract void connect() throws IOException;
protected abstract void connect() throws IOException, URISyntaxException;
protected abstract boolean isConnected() throws IOException;
@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
@@ -12,6 +13,7 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.common.TrackedRaceStatusEnum;
import com.sap.sailing.domain.swisstimingadapter.MessageType;
import com.sap.sailing.manage2sail.Activator;
import com.sap.sse.util.HttpUrlConnectionHelper;
/**
@@ -67,9 +69,9 @@ public class SailMasterConnectorForUrlDownload extends AbstractSailMasterConnect
}
@Override
protected void connect() throws IOException {
protected void connect() throws IOException, URISyntaxException {
logger.info("Connecting to "+raceDataUrl);
urlConnection = HttpUrlConnectionHelper.redirectConnection(raceDataUrl);
urlConnection = HttpUrlConnectionHelper.redirectConnection(Activator.getInstance().addAccessTokenToManage2SailUrl(raceDataUrl));
}
@Override
@@ -4,8 +4,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -58,14 +56,6 @@ public class SwissTimingAdapterImpl implements SwissTimingAdapter {
return swissTimingFactory;
}
@Override
public List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> getSwissTimingRaceRecords(String hostname,
int port) throws InterruptedException, UnknownHostException, IOException, ParseException {
List<com.sap.sailing.domain.swisstimingadapter.RaceRecord> result = new ArrayList<com.sap.sailing.domain.swisstimingadapter.RaceRecord>();
// TODO --> Frank: this needs to come from Manage2Sail and its JSON document somehow...
return result;
}
@Override
public RaceHandle addSwissTimingRace(TrackerManager trackerManager, RegattaIdentifier regattaToAddTo, String raceID,
String raceName, String raceDescription, BoatClass boatClass, String hostname, int port,
@@ -35,7 +35,9 @@ Require-Bundle: com.sap.sailing.domain,
org.mongodb.driver-sync;bundle-version="4.3.1",
org.apache.commons.math3;bundle-version="3.5.0",
org.apache.shiro.core;bundle-version="1.2.2",
org.hamcrest;bundle-version="2.2.0"
org.hamcrest;bundle-version="2.2.0",
net.bytebuddy.byte-buddy;bundle-version="1.12.18",
net.bytebuddy.byte-buddy-agent;bundle-version="1.12.18"
Export-Package: com.sap.sailing.domain.test,
com.sap.sailing.domain.test.mock
Import-Package: org.apache.commons.math;version="2.1.0",
@@ -13,6 +13,7 @@ import org.junit.Test;
import com.sap.sse.common.MultiTimeRange;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.MultiTimeRangeImpl;
public class MultiTimeRangeTest {
@@ -104,4 +105,36 @@ public class MultiTimeRangeTest {
assertEquals(createMulti(100, 120, 350, 400), createMulti(100, 200, 300, 400).subtract(createMulti(120, 350)));
assertEquals(createMulti(100, 120, 350, 360, 370, 400), createMulti(100, 200, 300, 400).subtract(createMulti(120, 350, 360, 370)));
}
@Test
public void testOrderingWithOf() {
final MillisecondsTimePoint _10 = new MillisecondsTimePoint(10);
final MillisecondsTimePoint _20 = new MillisecondsTimePoint(20);
final MillisecondsTimePoint _100 = new MillisecondsTimePoint(100);
final MillisecondsTimePoint _200 = new MillisecondsTimePoint(200);
final MultiTimeRange mtr = MultiTimeRange.of(TimeRange.create(_100, _200), TimeRange.create(_10, _20));
assertEquals(TimeRange.create(_10, _20), Util.get(mtr, 0));
assertEquals(TimeRange.create(_100, _200), Util.get(mtr, 1));
}
@Test
public void testOrderingWithUnion() {
final MillisecondsTimePoint _10 = new MillisecondsTimePoint(10);
final MillisecondsTimePoint _20 = new MillisecondsTimePoint(20);
final MillisecondsTimePoint _100 = new MillisecondsTimePoint(100);
final MillisecondsTimePoint _200 = new MillisecondsTimePoint(200);
final MultiTimeRange mtr = MultiTimeRange.of(TimeRange.create(_100, _200)).union(TimeRange.create(_10, _20));
assertEquals(TimeRange.create(_10, _20), Util.get(mtr, 0));
assertEquals(TimeRange.create(_100, _200), Util.get(mtr, 1));
}
@Test
public void testEmptyTimeRangeRemoval() {
final MillisecondsTimePoint _10 = new MillisecondsTimePoint(10);
final MillisecondsTimePoint _100 = new MillisecondsTimePoint(100);
final MillisecondsTimePoint _200 = new MillisecondsTimePoint(200);
final MultiTimeRange mtr = MultiTimeRange.of(TimeRange.create(_100, _200)).union(TimeRange.create(_10, _10));
assertEquals(1, Util.size(mtr));
assertEquals(TimeRange.create(_100, _200), Util.get(mtr, 0));
}
}
@@ -22,7 +22,7 @@ public class CalculateImageSizeFromUrlTest {
public void calculateImageSizeFromUrl() throws IOException {
int width = 350;
int height = 150;
ImageSize size = calculate("http://placekitten.com/" + width + "/" + height);
ImageSize size = calculate("http://via.placeholder.com/" + width + "x" + height);
assertTrue(size.getWidth() == width);
assertTrue(size.getHeight() == height);
}

Some files were not shown because too many files have changed in this diff Show More