mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-15 06:49:56 +00:00
Merge branch 'master' into bug5185
This commit is contained in:
commit
ef4e7f1224
320 files changed
+7497
-2854
No files matched your search
+37
-36
@@ -1,36 +1,37 @@
|
||||
/target
|
||||
www-test
|
||||
war
|
||||
build.log
|
||||
reporting.log
|
||||
.metadata
|
||||
*.class
|
||||
*.swp
|
||||
*~
|
||||
manifest.txt
|
||||
java/com.sap.sailing.gwt.ui/gwt-unitCache/*
|
||||
java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/*
|
||||
java/com.sap.sse.security.ui/WEB-INF/deploy/*
|
||||
sailing_debug0*
|
||||
dist
|
||||
build
|
||||
.DS_Store
|
||||
java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml
|
||||
/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT.launch
|
||||
|
||||
## Android Studio and Intellij and Android in general
|
||||
gen/
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
out/
|
||||
.gradle
|
||||
local.properties
|
||||
git.xml
|
||||
mobile/github-advrecyclerview_lib/bin
|
||||
captures
|
||||
/.recommenders/
|
||||
/java/.recommenders/
|
||||
/target
|
||||
www-test
|
||||
war
|
||||
build.log
|
||||
reporting.log
|
||||
.metadata
|
||||
*.class
|
||||
*.swp
|
||||
*~
|
||||
manifest.txt
|
||||
java/com.sap.sailing.gwt.ui/gwt-unitCache/*
|
||||
java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/*
|
||||
java/com.sap.sse.security.ui/WEB-INF/deploy/*
|
||||
sailing_debug0*
|
||||
dist
|
||||
build
|
||||
.DS_Store
|
||||
java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml
|
||||
/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT.launch
|
||||
|
||||
## Android Studio and Intellij and Android in general
|
||||
gen/
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
out/
|
||||
.gradle
|
||||
local.properties
|
||||
git.xml
|
||||
mobile/github-advrecyclerview_lib/bin
|
||||
captures
|
||||
/.recommenders/
|
||||
/java/.recommenders/
|
||||
java/com.sap.sailing.selenium.test/com.sap.sailing.selenium.test (No Proxy) individual.launch
|
||||
@@ -27,6 +27,15 @@ find_project_home ()
|
||||
echo $(correct_file_path "$1")
|
||||
}
|
||||
|
||||
clean_gwt_artifacts ()
|
||||
{
|
||||
cd $PROJECT_HOME/java
|
||||
rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.* com.sap.$PROJECT_TYPE.gwt.ui/.generated
|
||||
rm -rf com.sap.sailing.dashboards.gwt/com.sap.sailing.dashboards.gwt.* com.sap.sailing.dashboards.gwt/.generated
|
||||
rm -rf com.sap.sse.security.ui/com.sap.sse.security.ui.* com.sap.sse.security.ui/.generated
|
||||
rm -rf com.sap.sse.gwt/com.sap.sse.gwt.* com.sap.sse.gwt/.generated
|
||||
}
|
||||
|
||||
# this holds for default installation
|
||||
USER_HOME=~
|
||||
START_DIR="`pwd`"
|
||||
@@ -207,10 +216,7 @@ if [[ "$@" == "clean" ]]; then
|
||||
if [[ $? != 0 ]]; then
|
||||
exit 100
|
||||
fi
|
||||
cd $PROJECT_HOME/java
|
||||
rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*
|
||||
rm -rf com.sap.sailing.dashboards.gwt/com.sap.sailing.dashboards.gwt.*
|
||||
rm -rf com.sap.sse.security.ui/com.sap.sse.security.ui.*
|
||||
clean_gwt_artifacts
|
||||
cd $PROJECT_HOME
|
||||
echo "Using following command: mvn $extra -DargLine=\"$APP_PARAMETERS\" -fae -s $MAVEN_SETTINGS $clean"
|
||||
echo "Maven version used: `mvn --version`"
|
||||
@@ -559,27 +565,26 @@ if [[ "$@" == "build" ]] || [[ "$@" == "all" ]]; then
|
||||
cd $PROJECT_HOME/java
|
||||
if [ $gwtcompile -eq 1 ] && [[ "$clean" == "clean" ]]; then
|
||||
echo "INFO: Compiling GWT (rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*)"
|
||||
rm -rf com.sap.$PROJECT_TYPE.gwt.ui/com.sap.$PROJECT_TYPE.*
|
||||
GWT_XML_FILES=`find . -name '*.gwt.xml'`
|
||||
if [ $onegwtpermutationonly -eq 1 ]; then
|
||||
echo "INFO: Patching .gwt.xml files such that only one GWT permutation needs to be compiled"
|
||||
for i in $GWT_XML_FILES; do
|
||||
echo "INFO: Patching $i files such that only one GWT permutation needs to be compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/AllPermutations/SinglePermutation/' >$i.sed
|
||||
mv $i.sed $i
|
||||
done
|
||||
else
|
||||
echo "INFO: Patching .gwt.xml files such that all GWT permutations are compiled"
|
||||
for i in $GWT_XML_FILES; do
|
||||
echo "INFO: Patching $i files such that all GWT permutations are compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/SinglePermutation/AllPermutations/' >$i.sed
|
||||
mv $i.sed $i
|
||||
|
||||
done
|
||||
fi
|
||||
|
||||
clean_gwt_artifacts
|
||||
GWT_XML_FILES=`find . -name '*.gwt.xml'`
|
||||
if [ $onegwtpermutationonly -eq 1 ]; then
|
||||
echo "INFO: Patching .gwt.xml files such that only one GWT permutation needs to be compiled"
|
||||
for i in $GWT_XML_FILES; do
|
||||
echo "INFO: Patching $i files such that only one GWT permutation needs to be compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/AllPermutations/SinglePermutation/' >$i.sed
|
||||
mv $i.sed $i
|
||||
done
|
||||
else
|
||||
echo "INFO: Patching .gwt.xml files such that all GWT permutations are compiled"
|
||||
for i in $GWT_XML_FILES; do
|
||||
echo "INFO: Patching $i files such that all GWT permutations are compiled"
|
||||
cp $i $i.bak
|
||||
cat $i | sed -e 's/SinglePermutation/AllPermutations/' >$i.sed
|
||||
mv $i.sed $i
|
||||
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo "INFO: GWT Compilation disabled"
|
||||
extra="$extra -Pdebug.no-gwt-compile"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
AWS=/root/.local/bin/aws
|
||||
REGION=eu-west-1
|
||||
#HUDSON_SLAVE_AMI_ID=ami-0812bc35c7464732e
|
||||
HUDSON_SLAVE_AMI_ID=ami-04956fe5a5293da6f
|
||||
#HUDSON_SLAVE_AMI_ID=ami-04956fe5a5293da6f
|
||||
HUDSON_SLAVE_AMI_ID=ami-0251a199f8d4a4729
|
||||
echo Launching instance...
|
||||
instanceid=`$AWS ec2 run-instances --image-id $HUDSON_SLAVE_AMI_ID --count 1 --instance-type c5d.4xlarge --key-name Axel --security-groups "Sailing Analytics App" --region $REGION --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=Hudson Ubuntu Slave}]' --instance-initiated-shutdown-behavior terminate | tee /tmp/slavelaunch.out | jq .Instances[0].InstanceId | sed -e 's/"//g'`
|
||||
if [ "$instanceid" = "" ]; then
|
||||
@@ -17,7 +17,7 @@ else
|
||||
echo Instance $instanceid seems running now
|
||||
private_ip=`$AWS ec2 describe-instances --region $REGION --instance-ids $instanceid | jq .Reservations[0].Instances[0].PrivateIpAddress | sed -e 's/"//g'`
|
||||
echo Probing for SSH on private IP $private_ip
|
||||
while su - hudson -c "ssh -o ConnectTimeout=10,StrictHostKeyChecking=no hudson@$private_ip ls >/dev/null"; do
|
||||
while su - hudson -c "ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no hudson@$private_ip ls >/dev/null"; do
|
||||
echo SSH daemon not reachable yet. Trying again...
|
||||
done
|
||||
echo SSH daemon reached. State should be ready to connect to now.
|
||||
|
||||
@@ -16,7 +16,7 @@ else
|
||||
echo Instance $instanceid seems running now
|
||||
private_ip=`$AWS ec2 describe-instances --region $REGION --instance-ids $instanceid | jq .Reservations[0].Instances[0].PrivateIpAddress | sed -e 's/"//g'`
|
||||
echo Probing for SSH on private IP $private_ip
|
||||
while su - hudson -c "ssh -o ConnectTimeout=10,StrictHostKeyChecking=no hudson@$private_ip ls >/dev/null"; do
|
||||
while su - hudson -c "ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no hudson@$private_ip ls >/dev/null"; do
|
||||
echo SSH daemon not reachable yet. Trying again...
|
||||
done
|
||||
echo SSH daemon reached. State should be ready to connect to now.
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// Taken from https://github.com/sirceljm/AWS-SES-simple-mail-forward/blob/master/mail_forward.js
|
||||
// Install as an AWS Lambda according to https://github.com/sirceljm/AWS-SES-simple-mail-forward
|
||||
// and configure the to_address environment variable as a JSON array of strings representing
|
||||
// the recipients' e-mail addresses. Subscribe the lambda to your SNS topic that receives the
|
||||
// notification messages about your inbound e-mail. Use mail_forward_policy.json for the IAM role's
|
||||
// security policy.
|
||||
var AWS = require("aws-sdk");
|
||||
var ses = new AWS.SES();
|
||||
|
||||
exports.handler = (event, context, callback) => {
|
||||
let data = JSON.parse(event.Records[0].Sns.Message);
|
||||
let source = data.content;
|
||||
|
||||
source = source.replace(/^DKIM-Signature/im, "X-Original-DKIM-Signature");
|
||||
// source = source.replace(/^From/im, "X-Original-From");
|
||||
// source = source.replace(/^Source/im, "X-Original-Source");
|
||||
// source = source.replace(/^Sender/im, "X-Original-Sender");
|
||||
// source = source.replace(/^Return-Path/im, "X-Original-Return-Path");
|
||||
source = source.replace(/^Domainkey-Signature/im, "X-Original-Domainkey-Signature");
|
||||
// source = `From: AWS SES Mail Forwarding <${data.mail.destination}>\n` + source;
|
||||
|
||||
if (!process.env.to_address) {
|
||||
console.log("You need to supply to_address enviromnent variable");
|
||||
} else if (data.mail.destination == process.env.to_address) {
|
||||
console.log("MAIL SEND ABORTED! - Forwarded mail address and to_address are the same - THIS CAN CAUSE AN INFINITE LOOP!");
|
||||
} else {
|
||||
ses.sendRawEmail({
|
||||
RawMessage: {
|
||||
Data: source,
|
||||
},
|
||||
Destinations: JSON.parse(process.env.to_address),
|
||||
}, function (err, data) {
|
||||
if (err) {
|
||||
console.error(err, err.stack);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,117 @@
|
||||
# Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
#
|
||||
# This file is licensed under the Apache License, Version 2.0 (the "License").
|
||||
# You may not use this file except in compliance with the License. A copy of the
|
||||
# License is located at
|
||||
#
|
||||
# http://aws.amazon.com/apache2.0/
|
||||
#
|
||||
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||
# OF ANY KIND, either express or implied. See the License for the specific
|
||||
# language governing permissions and limitations under the License.
|
||||
|
||||
import os
|
||||
import boto3
|
||||
import email
|
||||
import re
|
||||
import json
|
||||
from botocore.exceptions import ClientError
|
||||
from email.parser import Parser
|
||||
from email.policy import default
|
||||
|
||||
region = os.environ['Region']
|
||||
|
||||
def get_message_from_s3(bucket_name, object_key):
|
||||
# Create a new S3 client.
|
||||
client_s3 = boto3.client("s3")
|
||||
# Get the email object from the S3 bucket.
|
||||
object_s3 = client_s3.get_object(Bucket=bucket_name, Key=object_key)
|
||||
# Read the content of the message.
|
||||
file = object_s3['Body'].read()
|
||||
return file
|
||||
|
||||
def create_message(file):
|
||||
senderMap = json.loads(os.environ["MailSenderJSON"])
|
||||
recipientMap = json.loads(os.environ["MailRecipientsJSON"])
|
||||
mailobject = email.message_from_string(file.decode('utf-8'))
|
||||
# Define sender, either from 'To'-Header or from 'Cc'-Header
|
||||
sender = None
|
||||
# Check 'To'-Header
|
||||
toHeader = Parser(policy=default).parsestr('To: ' + mailobject['To'])
|
||||
for x in toHeader['to'].addresses:
|
||||
if x.addr_spec in recipientMap:
|
||||
recipientList = recipientMap.get(x.addr_spec)
|
||||
sender = senderMap.get(x.addr_spec, x.addr_spec)
|
||||
# Check 'Cc'-Header
|
||||
if sender is None:
|
||||
if mailobject['Cc']:
|
||||
ccHeader = Parser(policy=default).parsestr('Cc: ' + mailobject['Cc'])
|
||||
for x in ccHeader['cc'].addresses:
|
||||
if x.addr_spec in recipientMap:
|
||||
recipientList = recipientMap.get(x.addr_spec)
|
||||
sender = senderMap.get(x.addr_spec, x.addr_spec)
|
||||
# Bcc mail, there is no header so find address from 'Received'-Header
|
||||
else:
|
||||
receivedString = re.search(r'\<(.*?)\>', ''.join(mailobject.get_all('Received'))).group(1)
|
||||
if receivedString in recipientMap:
|
||||
recipientList = recipientMap.get(receivedString)
|
||||
sender = senderMap.get(receivedString, receivedString)
|
||||
# Change original headers to X-
|
||||
mailobject['X-From'] = mailobject['From']
|
||||
if not mailobject['Reply-To']:
|
||||
mailobject['Reply-To'] = mailobject['From']
|
||||
mailobject['X-To'] = mailobject['To']
|
||||
mailobject['X-Return-Path'] = mailobject['Return-Path']
|
||||
# Replace original headers and set to SES Value
|
||||
del mailobject['DKIM-Signature']
|
||||
mailobject.replace_header('From', sender)
|
||||
mailobject.replace_header('Return-Path', sender)
|
||||
mailobject.replace_header('To', ','.join(recipientList))
|
||||
message = {
|
||||
"Source": sender,
|
||||
"Destinations": recipientList,
|
||||
"Data" : mailobject.as_string()
|
||||
}
|
||||
return message
|
||||
|
||||
def send_email(message):
|
||||
# Create a new SES client.
|
||||
client_ses = boto3.client('ses', region)
|
||||
# Send the email.
|
||||
try:
|
||||
#Provide the contents of the email.
|
||||
response = client_ses.send_raw_email(
|
||||
Source=message['Source'],
|
||||
Destinations=
|
||||
message['Destinations']
|
||||
,
|
||||
RawMessage={
|
||||
'Data':message['Data']
|
||||
}
|
||||
)
|
||||
# Display an error if something goes wrong.
|
||||
except ClientError as e:
|
||||
output = e.response['Error']['Message']
|
||||
else:
|
||||
# Modify output message
|
||||
if re.search(r'\<(.*?)\>', message['Source']):
|
||||
fromString = ','.join(re.findall(r'\<(.*?)\>', message['Source']))
|
||||
else:
|
||||
fromString = message['Source']
|
||||
output = "Email for: " + fromString + " forwarded to: " + ', '.join(message['Destinations']) + "! Message ID: " + response['MessageId']
|
||||
return output
|
||||
|
||||
def lambda_handler(event, context):
|
||||
# Get the unique ID of the message. This corresponds to the name of the file in S3.
|
||||
sns = event['Records'][0]['Sns']
|
||||
message = json.loads(sns['Message'])
|
||||
bucket_name = message['receipt']['action']['bucketName']
|
||||
object_key = message['receipt']['action']['objectKey']
|
||||
print(f"Received message with object key {object_key} in bucket {bucket_name}")
|
||||
# Retrieve the file from the S3 bucket.
|
||||
file = get_message_from_s3(bucket_name, object_key)
|
||||
# Create the message.
|
||||
message = create_message(file)
|
||||
# Send the email and print the result.
|
||||
result = send_email(message)
|
||||
print(result)
|
||||
@@ -1,22 +1,27 @@
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource": "arn:aws:logs:*:*:*"
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ses:SendEmail",
|
||||
"ses:SendRawEmail"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "VisualEditor0",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"logs:CreateLogStream",
|
||||
"logs:CreateLogGroup",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource": "*"
|
||||
},
|
||||
{
|
||||
"Sid": "VisualEditor1",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"ses:SendRawEmail"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::emails-for-sapsailing-com/*",
|
||||
"arn:aws:ses:eu-west-1:017363970217:identity/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM donaldduck70/sapjvm8:8.1.059
|
||||
FROM donaldduck70/sapjvm8:8.1.062
|
||||
LABEL maintainer=axel.uhl@sap.com
|
||||
# Download and extract the release
|
||||
WORKDIR /home/sailing/servers/server
|
||||
|
||||
@@ -6,7 +6,7 @@ ENV JAVA_HOME=/opt/sapjvm_8
|
||||
WORKDIR /opt
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y wget unzip \
|
||||
&& curl --cookie eula_3_1_agreed=tools.hana.ondemand.com/developer-license-3_1.txt "https://tools.hana.ondemand.com/additional/sapjvm-8.1.059-linux-x64.zip" --output sapjvm8-linux-x64.zip \
|
||||
&& curl --cookie eula_3_1_agreed=tools.hana.ondemand.com/developer-license-3_1.txt "https://tools.hana.ondemand.com/additional/sapjvm-8.1.062-linux-x64.zip" --output sapjvm8-linux-x64.zip \
|
||||
&& unzip sapjvm8-linux-x64.zip \
|
||||
&& rm sapjvm8-linux-x64.zip \
|
||||
&& echo "export JAVA_HOME=/opt/sapjvm_8; export PATH=\${PATH}:/opt/sapjvm_8/bin" > /etc/profile.d/javahome.sh
|
||||
@@ -12,6 +12,7 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.google.gwt.user;bundle-version="2.8.2";resolution:=optional,
|
||||
com.google.gwt.servlet;bundle-version="2.8.2",
|
||||
com.sap.sse.common,
|
||||
com.sap.sse.debranding,
|
||||
com.sap.sailing.domain.common,
|
||||
com.sap.sailing.domain.shared.android,
|
||||
com.sap.sailing.gwt.ui,
|
||||
|
||||
@@ -7,44 +7,38 @@
|
||||
|
||||
<html manifest="com.sap.sailing.dashboards.gwt.RibDashboard/appcache.manifest">
|
||||
<head>
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/dashboardicon.png" />
|
||||
<link href='images/dashboardicon.png' rel='apple-touch-icon'>
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
|
||||
<title>Dashboard</title>
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script type="text/javascript"
|
||||
src="com.sap.sailing.dashboards.gwt.RibDashboard/com.sap.sailing.dashboards.gwt.RibDashboard.nocache.js"></script>
|
||||
|
||||
<!-- Disables scrolling whole website vertically over edge on apple browsers -->
|
||||
<script type="text/javascript">
|
||||
document.ontouchmove = function(event){
|
||||
event.preventDefault();
|
||||
}
|
||||
</script>
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/dashboardicon${whitelabeled}.png" />
|
||||
<link href='images/dashboardicon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<title>Dashboard</title>
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript"
|
||||
src="com.sap.sailing.dashboards.gwt.RibDashboard/com.sap.sailing.dashboards.gwt.RibDashboard.nocache.js"></script>
|
||||
<!-- Disables scrolling whole website vertically over edge on apple browsers -->
|
||||
<script type="text/javascript">
|
||||
document.ontouchmove = function(event){
|
||||
event.preventDefault();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body style="background-color: #d3d3d3; overflow-y: hidden;">
|
||||
|
||||
<!-- OPTIONAL: include this if you want history support -->
|
||||
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
|
||||
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
|
||||
|
||||
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
|
||||
|
||||
<noscript>
|
||||
<div
|
||||
style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
|
||||
Your web browser must have JavaScript enabled in order for this
|
||||
application to display correctly.</div>
|
||||
</noscript>
|
||||
|
||||
<!-- OPTIONAL: include this if you want history support -->
|
||||
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1'
|
||||
style="position: absolute; width: 0; height: 0; border: 0"></iframe>
|
||||
<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
|
||||
<noscript>
|
||||
<div
|
||||
style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
|
||||
Your web browser must have JavaScript enabled in order for this
|
||||
application to display correctly.</div>
|
||||
</noscript>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,74 +1,83 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet
|
||||
</servlet-class>
|
||||
<init-param>
|
||||
<param-name>dirAllowed</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>useFileMappedBuffer</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>default</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet
|
||||
</servlet-class>
|
||||
<init-param>
|
||||
<param-name>dirAllowed</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>useFileMappedBuffer</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<display-name>Sailing Service</display-name>
|
||||
<servlet-name>SailingService</servlet-name>
|
||||
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceImpl</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>SailingService</servlet-name>
|
||||
<url-pattern>/service/sailing</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet>
|
||||
<display-name>Sailing Service</display-name>
|
||||
<servlet-name>SailingService</servlet-name>
|
||||
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceImpl</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>SailingService</servlet-name>
|
||||
<url-pattern>/service/sailing</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter>
|
||||
<filter-name>LocaleInjectionFilter</filter-name>
|
||||
<filter-class>com.sap.sse.security.ui.server.LocaleInjectionFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>LocaleInjectionFilter</filter-name>
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</filter-mapping>
|
||||
<servlet>
|
||||
<display-name>ClientConfigurationServlet</display-name>
|
||||
<servlet-name>ClientConfigurationServlet</servlet-name>
|
||||
<servlet-class>com.sap.sse.debranding.ClientConfigurationServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>ClientConfigurationServlet</servlet-name>
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter>
|
||||
<filter-name>GWTCacheControlServletFilter</filter-name>
|
||||
<filter-class>com.sap.sse.gwt.server.GWTCacheControlServletFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>GWTCacheControlServletFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet>
|
||||
<display-name>Dashboard Dispatch Service</display-name>
|
||||
<servlet-name>dashboardDispatch</servlet-name>
|
||||
<servlet-class>com.sap.sailing.dashboards.gwt.server.DashboardDispatchServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>dashboardDispatch</servlet-name>
|
||||
<url-pattern>/service/dispatch</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- enabling remote logging -->
|
||||
<servlet>
|
||||
<servlet-name>remoteLoggingServlet</servlet-name>
|
||||
<servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>remoteLoggingServlet</servlet-name>
|
||||
<url-pattern>/com.sap.sailing.dashboards.gwt.RibDashboard/remote_logging</url-pattern>
|
||||
</servlet-mapping>
|
||||
<filter>
|
||||
<filter-name>LocaleInjectionFilter</filter-name>
|
||||
<filter-class>com.sap.sse.security.ui.server.LocaleInjectionFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>LocaleInjectionFilter</filter-name>
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<mime-mapping>
|
||||
<extension>manifest</extension>
|
||||
<mime-type>text/cache-manifest</mime-type>
|
||||
</mime-mapping>
|
||||
<filter>
|
||||
<filter-name>GWTCacheControlServletFilter</filter-name>
|
||||
<filter-class>com.sap.sse.gwt.server.GWTCacheControlServletFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>GWTCacheControlServletFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet>
|
||||
<display-name>Dashboard Dispatch Service</display-name>
|
||||
<servlet-name>dashboardDispatch</servlet-name>
|
||||
<servlet-class>com.sap.sailing.dashboards.gwt.server.DashboardDispatchServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>dashboardDispatch</servlet-name>
|
||||
<url-pattern>/service/dispatch</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- enabling remote logging -->
|
||||
<servlet>
|
||||
<servlet-name>remoteLoggingServlet</servlet-name>
|
||||
<servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>remoteLoggingServlet</servlet-name>
|
||||
<url-pattern>/com.sap.sailing.dashboards.gwt.RibDashboard/remote_logging</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<mime-mapping>
|
||||
<extension>manifest</extension>
|
||||
<mime-type>text/cache-manifest</mime-type>
|
||||
</mime-mapping>
|
||||
</web-app>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
+4
-1
@@ -12,6 +12,7 @@ import com.google.gwt.user.client.ui.HasWidgets;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class DashboardHeader extends Composite implements HasWidgets {
|
||||
|
||||
@@ -37,7 +38,9 @@ public class DashboardHeader extends Composite implements HasWidgets {
|
||||
public DashboardHeader() {
|
||||
dashboardHeaderResources.gss().ensureInjected();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
sapLogo.setResource(DashboardHeaderResources.INSTANCE.sapLogo());
|
||||
if (ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
sapLogo.setResource(DashboardHeaderResources.INSTANCE.sapLogo());
|
||||
}
|
||||
event.setInnerHTML(StringMessages.INSTANCE.dashboardHeader());
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ public class DashboardManifestLinker extends ManifestLinker {
|
||||
return new String[] { "/dashboards/RibDashboard.html",
|
||||
"/dashboards/RibDashboard.css",
|
||||
"/dashboards/images/dashboardicon.png",
|
||||
"/dashboards/images/dashboardicon-whitelabeled.png",
|
||||
"/dashboards/js/jquery-3.3.1.min.js",
|
||||
"/sailing-fontface-1.0.cache.css"};
|
||||
}
|
||||
|
||||
+4
-3
@@ -1292,6 +1292,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
.get(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name());
|
||||
final Boolean controlTrackingFromStartAndFinishTimes = (Boolean) dbRegatta
|
||||
.get(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name());
|
||||
final Boolean autoRestartTrackingUponCompetitorSetChange = (Boolean) dbRegatta
|
||||
.get(FieldNames.REGATTA_AUTO_RESTART_TRACKING_UPON_COMPETITOR_SET_CHANGE.name());
|
||||
Boolean canBoatsOfCompetitorsChangePerRace = (Boolean) dbRegatta
|
||||
.get(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name());
|
||||
// for backward compatibility
|
||||
@@ -1300,7 +1302,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
canBoatsOfCompetitorsChangePerRace = false;
|
||||
createMigratableRegatta = true;
|
||||
}
|
||||
|
||||
CompetitorRegistrationType competitorRegistrationType = CompetitorRegistrationType
|
||||
.valueOfOrDefault((String) dbRegatta.get(FieldNames.REGATTA_COMPETITOR_REGISTRATION_TYPE.name()));
|
||||
final RankingMetricConstructor rankingMetricConstructor = loadRankingMetricConstructor(dbRegatta);
|
||||
@@ -1313,7 +1314,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
: buoyZoneRadiusInHullLengths,
|
||||
useStartTimeInference == null ? true : useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor, new MongoObjectFactoryImpl(database), registrationLinkSecret);
|
||||
autoRestartTrackingUponCompetitorSetChange, rankingMetricConstructor, new MongoObjectFactoryImpl(database), registrationLinkSecret);
|
||||
} else {
|
||||
result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, boatClass,
|
||||
canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, startDate, endDate, series, /* persistent */true,
|
||||
@@ -1322,7 +1323,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
|
||||
: buoyZoneRadiusInHullLengths,
|
||||
useStartTimeInference == null ? true : useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes == null ? false : controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor, registrationLinkSecret);
|
||||
autoRestartTrackingUponCompetitorSetChange == null ? false : autoRestartTrackingUponCompetitorSetChange, rankingMetricConstructor, registrationLinkSecret);
|
||||
}
|
||||
result.setRegattaConfiguration(configuration);
|
||||
}
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ public enum FieldNames {
|
||||
REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS,
|
||||
REGATTA_USE_START_TIME_INFERENCE,
|
||||
REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES,
|
||||
REGATTA_AUTO_RESTART_TRACKING_UPON_COMPETITOR_SET_CHANGE,
|
||||
REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE,
|
||||
REGATTA_COMPETITOR_REGISTRATION_TYPE,
|
||||
REGATTA_REGISTRATION_LINK_SECRET,
|
||||
|
||||
+4
-4
@@ -32,12 +32,12 @@ public class MigratableRegattaImpl extends RegattaImpl implements MigratableRega
|
||||
TimePoint startDate, TimePoint endDate,
|
||||
Iterable<S> series, boolean persistent, ScoringScheme scoringScheme, Serializable id, CourseArea courseArea,
|
||||
Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference,
|
||||
boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor,
|
||||
MongoObjectFactory mongoObjectFactory, String registrationLinkSecret) {
|
||||
boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange,
|
||||
RankingMetricConstructor rankingMetricConstructor, MongoObjectFactory mongoObjectFactory, String registrationLinkSecret) {
|
||||
super(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, startDate, endDate, series,
|
||||
persistent, scoringScheme, id, courseArea, buoyZoneRadiusInHullLengths, useStartTimeInference,
|
||||
controlTrackingFromStartAndFinishTimes, rankingMetricConstructor,
|
||||
registrationLinkSecret);
|
||||
controlTrackingFromStartAndFinishTimes, autoRestartTrackingUponCompetitorSetChange,
|
||||
rankingMetricConstructor, registrationLinkSecret);
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
mongoObjectFactory.storeRegatta(this); // make sure the canBoatsOfCompetitorsChangePerRace flag makes it into the DB
|
||||
}
|
||||
|
||||
+1
@@ -729,6 +729,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
|
||||
dbRegatta.put(FieldNames.REGATTA_BUOY_ZONE_RADIUS_IN_HULL_LENGTHS.name(), regatta.getBuoyZoneRadiusInHullLengths());
|
||||
dbRegatta.put(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name(), regatta.useStartTimeInference());
|
||||
dbRegatta.put(FieldNames.REGATTA_CONTROL_TRACKING_FROM_START_AND_FINISH_TIMES.name(), regatta.isControlTrackingFromStartAndFinishTimes());
|
||||
dbRegatta.put(FieldNames.REGATTA_AUTO_RESTART_TRACKING_UPON_COMPETITOR_SET_CHANGE.name(), regatta.isAutoRestartTrackingUponCompetitorSetChange());
|
||||
dbRegatta.put(FieldNames.REGATTA_CAN_BOATS_OF_COMPETITORS_CHANGE_PER_RACE.name(), regatta.canBoatsOfCompetitorsChangePerRace());
|
||||
dbRegatta.put(FieldNames.REGATTA_COMPETITOR_REGISTRATION_TYPE.name(), regatta.getCompetitorRegistrationType().name());
|
||||
dbRegatta.put(FieldNames.REGATTA_REGISTRATION_LINK_SECRET.name(), regatta.getRegistrationLinkSecret());
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ public class CreateAndTrackWithRaceLogTest extends RaceLogTrackingTestHelper {
|
||||
/* registrationLinkSecret */ null, /* startDate */null, /* endDate */null, UUID.randomUUID(),
|
||||
Collections.<Series> singletonList(series), /* persistent */ true, new HighPoint(), UUID.randomUUID(),
|
||||
/* buoyZoneRadiusInHullLengths */2.0, /* useStartTimeInference */true,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new);
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false, OneDesignRankingMetric::new);
|
||||
series.addRaceColumn(columnName, /* trackedRegattaRegistry */null);
|
||||
leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {});
|
||||
adapter = RaceLogTrackingAdapterFactory.INSTANCE.getAdapter(DomainFactory.INSTANCE);
|
||||
|
||||
+62
-8
@@ -20,6 +20,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder;
|
||||
@@ -28,12 +29,18 @@ import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceInformationFinder;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RegisteredCompetitorsAndBoatsAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor;
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
@@ -146,6 +153,26 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
|
||||
trackedRace.updateStartAndEndOfTracking(/* waitForGPSFixesToLoad */ false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogRevokeEvent event) {
|
||||
if (event.getRevokedEventType().equals(RaceLogRegisterCompetitorEventImpl.class.getName())) {
|
||||
try {
|
||||
checkForChangeOfCompetitorSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RaceLogRegisterCompetitorEvent event) {
|
||||
try {
|
||||
checkForChangeOfCompetitorSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
visitors.put(log, visitor);
|
||||
((RaceLog) log).addListener(visitor);
|
||||
@@ -155,6 +182,26 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
|
||||
public void visit(RegattaLogDefineMarkEvent event) {
|
||||
RaceLogRaceTracker.this.onDefineMarkEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogRevokeEvent event) {
|
||||
if (event.getRevokedEventType().equals(RegattaLogRegisterCompetitorEventImpl.class.getName())) {
|
||||
try {
|
||||
checkForChangeOfCompetitorSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(RegattaLogRegisterCompetitorEvent event) {
|
||||
try {
|
||||
checkForChangeOfCompetitorSet();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
visitors.put(log, visitor);
|
||||
((RegattaLog) log).addListener(visitor);
|
||||
@@ -168,6 +215,13 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForChangeOfCompetitorSet() throws Exception {
|
||||
final Map<Competitor, Boat> competitorsAndTheirBoats = new RegisteredCompetitorsAndBoatsAnalyzer(params.getRaceLog(), params.getRegattaLog()).analyze();
|
||||
if (!Util.setEquals(competitorsAndTheirBoats.keySet(), getRace().getCompetitors())) {
|
||||
trackedRegattaRegistry.updateRaceCompetitors(getRegatta(), getRace());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop(boolean preemptive, boolean willBeRemoved) {
|
||||
RaceLog raceLog = params.getRaceLog();
|
||||
@@ -273,18 +327,18 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
|
||||
}
|
||||
|
||||
private void startTracking(RaceLogStartTrackingEvent event) {
|
||||
RaceLog raceLog = params.getRaceLog();
|
||||
RaceColumn raceColumn = params.getRaceColumn();
|
||||
Fleet fleet = params.getFleet();
|
||||
RaceLogDenoteForTrackingEvent denoteEvent = new RaceInformationFinder(raceLog).analyze();
|
||||
final RaceLog raceLog = params.getRaceLog();
|
||||
final RaceColumn raceColumn = params.getRaceColumn();
|
||||
final Fleet fleet = params.getFleet();
|
||||
final RaceLogDenoteForTrackingEvent denoteEvent = new RaceInformationFinder(raceLog).analyze();
|
||||
final Pair<TimePointSpecificationFoundInLog, TimePointSpecificationFoundInLog> trackingTimes = new TrackingTimesFinder(raceLog).analyze();
|
||||
if (!trackedRegatta.getRegatta().isControlTrackingFromStartAndFinishTimes() &&
|
||||
(trackingTimes == null || trackingTimes.getA() == null || trackingTimes.getA().getTimePoint() == null)) {
|
||||
// the start of tracking interval is unset or set to null; enter "now" as start of tracking into the race log
|
||||
raceLog.add(new RaceLogStartOfTrackingEventImpl(MillisecondsTimePoint.now(), raceLogEventAuthor, raceLog.getCurrentPassId()));
|
||||
}
|
||||
BoatClass boatClass = denoteEvent.getBoatClass();
|
||||
String raceName = denoteEvent.getRaceName();
|
||||
final BoatClass boatClass = denoteEvent.getBoatClass();
|
||||
final String raceName = denoteEvent.getRaceName();
|
||||
CourseBase courseBase = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ true).analyze();
|
||||
if (courseBase == null) {
|
||||
courseBase = new CourseDataImpl("Default course for " + raceName);
|
||||
@@ -303,8 +357,8 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl {
|
||||
}
|
||||
throw new RaceNotCreatedException(String.format("Race for racelog (%s) has already been created", raceLog));
|
||||
}
|
||||
Map<Competitor, Boat> competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(params.getFleet());
|
||||
Serializable raceId = denoteEvent.getRaceId();
|
||||
final Map<Competitor, Boat> competitorsAndTheirBoats = raceColumn.getAllCompetitorsAndTheirBoats(params.getFleet());
|
||||
final Serializable raceId = denoteEvent.getRaceId();
|
||||
try {
|
||||
final RaceDefinition raceDef = raceTrackingHandler.createRaceDefinition(trackedRegatta.getRegatta(), raceName, course,
|
||||
boatClass, competitorsAndTheirBoats, raceId);
|
||||
|
||||
+45
-4
@@ -2,8 +2,10 @@ package com.sap.sailing.domain.racelog.analyzing.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -12,6 +14,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -43,10 +46,8 @@ public class FinishedTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finishe
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 2);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
|
||||
raceLog.add(event1);
|
||||
raceLog.add(event2);
|
||||
|
||||
assertEquals(event2.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@@ -56,10 +57,50 @@ public class FinishedTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finishe
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 2);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
|
||||
raceLog.add(event1);
|
||||
raceLog.add(event2);
|
||||
|
||||
assertEquals(event1.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevokeFinished() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
assertNull(analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevokeFinishedSecond() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 3);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
raceLog.add(event2);
|
||||
assertSame(event2.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindFinishEventAfterRevoke() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 3);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
raceLog.add(event2);
|
||||
assertSame(event2, analyzer.findFinishedEvent());
|
||||
}
|
||||
}
|
||||
+46
-4
@@ -4,6 +4,7 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -12,6 +13,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
@@ -43,10 +45,8 @@ public class FinishingTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finish
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 2);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
|
||||
raceLog.add(event1);
|
||||
raceLog.add(event2);
|
||||
|
||||
assertSame(event2.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@@ -56,10 +56,52 @@ public class FinishingTimeFinderTest extends PassAwareRaceLogAnalyzerTest<Finish
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 2);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHED);
|
||||
|
||||
raceLog.add(event1);
|
||||
raceLog.add(event2);
|
||||
|
||||
assertSame(event1.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevokeFinishing() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
assertNull(analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevokeFinishingSecond() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 3);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
raceLog.add(event2);
|
||||
assertSame(event2.getLogicalTimePoint(), analyzer.analyze());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindFinishEventAfterRevoke() {
|
||||
RaceLogRaceStatusEvent event1 = createEvent(RaceLogRaceStatusEvent.class, 1);
|
||||
when(event1.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
RaceLogRevokeEvent revokeEvent = createEvent(RaceLogRevokeEvent.class,2);
|
||||
final Serializable id = event1.getId();
|
||||
when(revokeEvent.getRevokedEventId()).thenReturn(id);
|
||||
RaceLogRaceStatusEvent event2 = createEvent(RaceLogRaceStatusEvent.class, 3);
|
||||
when(event2.getNextStatus()).thenReturn(RaceLogRaceStatus.FINISHING);
|
||||
raceLog.add(event1);
|
||||
raceLog.add(revokeEvent);
|
||||
raceLog.add(event2);
|
||||
assertSame(event2, analyzer.findFinishingEvent());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+16
-4
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.abstractlog;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.UUID;
|
||||
@@ -57,8 +58,16 @@ extends Track<EventT>, WithID {
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link #lockForRead()} and
|
||||
* {@link #unlockAfterRead()} to avoid {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
Iterable<EventT> getRawFixesDescending();
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link #lockForRead()} and
|
||||
* {@link #unlockAfterRead()} to avoid {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
Iterable<EventT> getFixesDescending();
|
||||
|
||||
void addAllListeners(Iterable<VisitorT> listeners);
|
||||
@@ -103,14 +112,17 @@ extends Track<EventT>, WithID {
|
||||
EventT getEventById(Serializable id);
|
||||
|
||||
/**
|
||||
* Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}. Events are sorted by
|
||||
* their {@link TimePoint} and the oldest is returned first.
|
||||
* @return
|
||||
* Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}. Events are sorted by their
|
||||
* {@link TimePoint} and the oldest is returned first. Callers that want to iterate over the collection returned
|
||||
* need to use {@link #lockForRead()} and {@link #unlockAfterRead()} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
NavigableSet<EventT> getUnrevokedEvents();
|
||||
|
||||
/**
|
||||
* Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}.
|
||||
* Get a {@link NavigableSet} of unrevoked events regardless of the {@code pass}. Callers that want to iterate over
|
||||
* the collection returned need to use {@link #lockForRead()} and {@link #unlockAfterRead()} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
NavigableSet<EventT> getUnrevokedEventsDescending();
|
||||
|
||||
|
||||
+3
@@ -30,6 +30,9 @@ public abstract class BaseLogAnalyzer<LogT extends AbstractLog<EventT, VisitorT>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always called under the {@link #getLog() log's} read lock
|
||||
*/
|
||||
protected abstract ResultT performAnalysis();
|
||||
|
||||
protected Iterable<EventT> getAllEvents() {
|
||||
|
||||
+56
-27
@@ -33,13 +33,13 @@ import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
|
||||
/**
|
||||
* {@link Track} implementation for {@link AbstractLogEvent}s.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* {@link TrackImpl#getDummyFix(com.sap.sailing.domain.common.TimePoint)} is not overridden, see
|
||||
* {@link RaceLogEventComparator} for sorting when interface methods like
|
||||
* {@link Track#getFirstFixAfter(com.sap.sailing.domain.common.TimePoint)} are used.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractLogImpl<EventT extends AbstractLogEvent<VisitorT>, VisitorT>
|
||||
extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
@@ -52,7 +52,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
* Clients can use the {@link #add(RaceLogEvent, UUID)} method
|
||||
*/
|
||||
private transient Map<UUID, Set<EventT>> eventsDeliveredToClient = new HashMap<UUID, Set<EventT>>();
|
||||
|
||||
|
||||
private Map<Serializable, EventT> eventsById = new HashMap<Serializable, EventT>();
|
||||
|
||||
private final Serializable id;
|
||||
@@ -67,7 +67,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
|
||||
/**
|
||||
* Initializes a new {@link RaceLogImpl}.
|
||||
*
|
||||
*
|
||||
* @param nameForReadWriteLock
|
||||
* name of lock.
|
||||
*/
|
||||
@@ -82,7 +82,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
public Serializable getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
|
||||
protected void onSuccessfulAdd(EventT event, boolean notifyListeners) {
|
||||
revokeIfNecessary(event);
|
||||
eventsById.put(event.getId(), event);
|
||||
@@ -90,7 +90,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
notifyListenersAboutReceive(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean add(EventT event, boolean notifyListeners) {
|
||||
boolean isAdded = false;
|
||||
lockForWrite();
|
||||
@@ -107,7 +107,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
}
|
||||
return isAdded;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean add(EventT event) {
|
||||
return add(event, true);
|
||||
@@ -117,7 +117,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
public boolean load(EventT event) {
|
||||
return add(event, false);
|
||||
}
|
||||
|
||||
|
||||
private void revokeIfNecessary(EventT newEvent) {
|
||||
if (newEvent instanceof RevokeEvent) {
|
||||
RevokeEvent<?> revokeEvent = (RevokeEvent<?>) newEvent;
|
||||
@@ -134,7 +134,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkIfSuccessfullyRevokes(RevokeEvent<?> revokeEvent) throws NotRevokableException {
|
||||
lockForRead();
|
||||
EventT revokedEvent;
|
||||
@@ -166,7 +166,7 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
add(event);
|
||||
return getEventsToDeliver(clientId, event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<EventT> getEventsToDeliver(UUID clientId) {
|
||||
return getEventsToDeliver(clientId, null);
|
||||
@@ -311,25 +311,15 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
assertReadLock();
|
||||
return eventsById.get(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NavigableSet<EventT> getUnrevokedEvents() {
|
||||
return new PartialNavigableSetView<EventT>(super.getInternalFixes()) {
|
||||
@Override
|
||||
protected boolean isValid(EventT e) {
|
||||
return ! (e instanceof RevokeEvent) && ! revokedEventIds.contains(e.getId());
|
||||
}
|
||||
};
|
||||
return new FilteredPartialNavigableSetView<>(super.getInternalFixes(), new RevokedValidator<>(revokedEventIds));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NavigableSet<EventT> getUnrevokedEventsDescending() {
|
||||
return new PartialNavigableSetView<EventT>(super.getInternalFixes().descendingSet()) {
|
||||
@Override
|
||||
protected boolean isValid(EventT e) {
|
||||
return ! (e instanceof RevokeEvent) && ! revokedEventIds.contains(e.getId());
|
||||
}
|
||||
};
|
||||
return new FilteredPartialNavigableSetView<EventT>(super.getInternalFixes().descendingSet(), new RevokedValidator<>(revokedEventIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -375,14 +365,14 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
unlockAfterWrite();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void revokeEvent(AbstractLogEventAuthor author, EventT toRevoke) throws NotRevokableException {
|
||||
revokeEvent(author, toRevoke, null);
|
||||
}
|
||||
|
||||
|
||||
protected abstract EventT createRevokeEvent(AbstractLogEventAuthor author, EventT toRevoke, String reason);
|
||||
|
||||
|
||||
@Override
|
||||
public void revokeEvent(AbstractLogEventAuthor author, EventT toRevoke, String reason) throws NotRevokableException {
|
||||
if (toRevoke == null) {
|
||||
@@ -392,4 +382,43 @@ extends TrackImpl<EventT> implements AbstractLog<EventT, VisitorT> {
|
||||
checkIfSuccessfullyRevokes((RevokeEvent<?>) revokeEvent);
|
||||
add(revokeEvent);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface NavigableSetViewValidator<T> {
|
||||
boolean isValid(T item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Considers an event valid if it is not a {@link RevokeEvent} and is not contained in the set of events passed to
|
||||
* the constructor that have been revoked.
|
||||
*/
|
||||
public static class RevokedValidator<EventT extends AbstractLogEvent<VisitorT>, VisitorT> implements NavigableSetViewValidator<EventT> {
|
||||
final Set<Serializable> revokedEventIds;
|
||||
|
||||
public RevokedValidator(Set<Serializable> revokedEventIds) {
|
||||
this.revokedEventIds = revokedEventIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(EventT item) {
|
||||
return !(item instanceof RevokeEvent) && !revokedEventIds.contains(item.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public static class FilteredPartialNavigableSetView<T> extends PartialNavigableSetView<T> {
|
||||
private final NavigableSetViewValidator<T> validator;
|
||||
|
||||
public FilteredPartialNavigableSetView(NavigableSet<T> set, final NavigableSetViewValidator<T> validator) {
|
||||
super(set);
|
||||
if (validator == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid(T t) {
|
||||
return validator.isValid(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-4
@@ -1,18 +1,33 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.AbstractLog;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogImpl;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
/**
|
||||
* "Fix" validity is decided based on the {@link #getCurrentPassId() current pass}. The validity is not cached.
|
||||
*/
|
||||
* "Fix" validity is decided based on the {@link #getCurrentPassId() current pass}. The validity is not cached.
|
||||
*/
|
||||
public interface RaceLog extends AbstractLog<RaceLogEvent, RaceLogEventVisitor>, WithID {
|
||||
public static final int DefaultPassId = 0;
|
||||
|
||||
|
||||
class PassValidator implements AbstractLogImpl.NavigableSetViewValidator<RaceLogEvent> {
|
||||
final int pass;
|
||||
|
||||
public PassValidator(int pass) {
|
||||
this.pass = pass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(RaceLogEvent item) {
|
||||
return item.getPassId() == pass;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current pass id.
|
||||
*
|
||||
*
|
||||
* @return the pass id.
|
||||
*/
|
||||
int getCurrentPassId();
|
||||
|
||||
}
|
||||
+2
-1
@@ -1,12 +1,13 @@
|
||||
package com.sap.sailing.domain.abstractlog.race;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.Revokable;
|
||||
import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
|
||||
/**
|
||||
* Events to indicate the new race status which is valid for all events
|
||||
* arriving after this event (on the same pass).
|
||||
*/
|
||||
public interface RaceLogRaceStatusEvent extends RaceLogEvent {
|
||||
public interface RaceLogRaceStatusEvent extends RaceLogEvent, Revokable {
|
||||
|
||||
RaceLogRaceStatus getNextStatus();
|
||||
|
||||
|
||||
+19
-3
@@ -7,16 +7,32 @@ import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
|
||||
public class FinishedTimeFinder extends RaceLogAnalyzer<TimePoint> {
|
||||
|
||||
public FinishedTimeFinder(RaceLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
public RaceLogRaceStatusEvent findFinishedEvent() {
|
||||
log.lockForRead();
|
||||
try {
|
||||
for (RaceLogEvent event : getPassUnrevokedEventsDescending()) {
|
||||
if (event instanceof RaceLogRaceStatusEvent) {
|
||||
final RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHED)) {
|
||||
return statusEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimePoint performAnalysis() {
|
||||
for (RaceLogEvent event : getPassEventsDescending()) {
|
||||
for (RaceLogEvent event : getPassUnrevokedEventsDescending()) {
|
||||
if (event instanceof RaceLogRaceStatusEvent) {
|
||||
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
final RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHED)) {
|
||||
return statusEvent.getLogicalTimePoint();
|
||||
}
|
||||
|
||||
+19
-4
@@ -12,18 +12,33 @@ public class FinishingTimeFinder extends RaceLogAnalyzer<TimePoint> {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
public RaceLogRaceStatusEvent findFinishingEvent() {
|
||||
log.lockForRead();
|
||||
try {
|
||||
for (RaceLogEvent event : getPassUnrevokedEventsDescending()) {
|
||||
if (event instanceof RaceLogRaceStatusEvent) {
|
||||
final RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHING)) {
|
||||
return statusEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
log.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimePoint performAnalysis() {
|
||||
for (RaceLogEvent event : getPassEventsDescending()) {
|
||||
for (RaceLogEvent event : getPassUnrevokedEventsDescending()) {
|
||||
if (event instanceof RaceLogRaceStatusEvent) {
|
||||
RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
final RaceLogRaceStatusEvent statusEvent = (RaceLogRaceStatusEvent) event;
|
||||
if (statusEvent.getNextStatus().equals(RaceLogRaceStatus.FINISHING)) {
|
||||
return statusEvent.getLogicalTimePoint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+34
-2
@@ -1,22 +1,54 @@
|
||||
package com.sap.sailing.domain.abstractlog.race.analyzing.impl;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.BaseLogAnalyzer;
|
||||
import com.sap.sailing.domain.abstractlog.impl.AbstractLogImpl;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
|
||||
public abstract class RaceLogAnalyzer<ResultType> extends BaseLogAnalyzer
|
||||
<RaceLog, RaceLogEvent, RaceLogEventVisitor, ResultType> {
|
||||
<RaceLog, RaceLogEvent, RaceLogEventVisitor, ResultType> {
|
||||
|
||||
public RaceLogAnalyzer(RaceLog raceLog) {
|
||||
super(raceLog);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link Track#lockForRead()} and
|
||||
* {@link Track#unlockAfterRead()} on the underlying {@link #getLog() log} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
protected Iterable<RaceLogEvent> getPassEvents() {
|
||||
return log.getFixes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link Track#lockForRead()} and
|
||||
* {@link Track#unlockAfterRead()} on the underlying {@link #getLog() log} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
protected Iterable<RaceLogEvent> getPassEventsDescending() {
|
||||
return log.getFixesDescending();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link Track#lockForRead()} and
|
||||
* {@link Track#unlockAfterRead()} on the underlying {@link #getLog() log} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
protected Iterable<RaceLogEvent> getPassUnrevokedEvents() {
|
||||
return new AbstractLogImpl.FilteredPartialNavigableSetView<>(log.getUnrevokedEvents(), new RaceLog.PassValidator(log.getCurrentPassId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Callers that want to iterate over the collection returned need to use {@link Track#lockForRead()} and
|
||||
* {@link Track#unlockAfterRead()} on the underlying {@link #getLog() log} to avoid
|
||||
* {@link ConcurrentModificationException}s.
|
||||
*/
|
||||
protected Iterable<RaceLogEvent> getPassUnrevokedEventsDescending() {
|
||||
return new AbstractLogImpl.FilteredPartialNavigableSetView<>(log.getUnrevokedEventsDescending(), new RaceLog.PassValidator(log.getCurrentPassId()));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -59,7 +59,7 @@ public class RaceStatusAnalyzer extends RaceLogAnalyzer<Pair<RaceLogRaceStatus,
|
||||
protected Pair<RaceLogRaceStatus, TimePoint> performAnalysis() {
|
||||
ArrayListNavigableSet<RaceLogRaceStatusEvent> statusEvents = new ArrayListNavigableSet<>(
|
||||
RaceLogRaceStatusEventComparator.INSTANCE);
|
||||
for (RaceLogEvent event : getPassEvents()) {
|
||||
for (RaceLogEvent event : getPassUnrevokedEvents()) {
|
||||
if (event instanceof RaceLogRaceStatusEvent) {
|
||||
statusEvents.add((RaceLogRaceStatusEvent) event);
|
||||
}
|
||||
|
||||
+15
-21
@@ -9,22 +9,21 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEvent;
|
||||
import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.impl.PartialNavigableSetView;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackImpl;
|
||||
|
||||
/**
|
||||
* {@link Track} implementation for {@link RaceLogEvent}s.
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* "Fix" validity is decided based on the {@link #getCurrentPassId() current pass}. The validity is not cached.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* {@link TrackImpl#getDummyFix(com.sap.sailing.domain.common.TimePoint)} is not overridden, see
|
||||
* {@link RaceLogEventComparator} for sorting when interface methods like
|
||||
* {@link Track#getFirstFixAfter(com.sap.sailing.domain.common.TimePoint)} are used.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class RaceLogImpl extends AbstractLogImpl<RaceLogEvent, RaceLogEventVisitor> implements RaceLog {
|
||||
private static final long serialVersionUID = 98032278604708475L;
|
||||
@@ -39,19 +38,19 @@ public class RaceLogImpl extends AbstractLogImpl<RaceLogEvent, RaceLogEventVisit
|
||||
|
||||
@Override
|
||||
public int getCurrentPassId() {
|
||||
//return pass id of last event, as pass is the top-level sorting criterion in RaceLogEventComparator
|
||||
if (! getUnrevokedEvents().isEmpty()) {
|
||||
return getUnrevokedEvents().last().getPassId();
|
||||
} else {
|
||||
return DefaultPassId;
|
||||
lockForRead();
|
||||
try {
|
||||
// return pass id of last event, as pass is the top-level sorting criterion in RaceLogEventComparator
|
||||
if (!getUnrevokedEvents().isEmpty()) {
|
||||
return getUnrevokedEvents().last().getPassId();
|
||||
} else {
|
||||
return DefaultPassId;
|
||||
}
|
||||
} finally {
|
||||
unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccessfulAdd(RaceLogEvent event, boolean notifyListeners) {
|
||||
super.onSuccessfulAdd(event, notifyListeners);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected RaceLogEvent createRevokeEvent(AbstractLogEventAuthor author, RaceLogEvent toRevoke, String reason) {
|
||||
return new RaceLogRevokeEventImpl(author, getCurrentPassId(), toRevoke, reason);
|
||||
@@ -59,11 +58,6 @@ public class RaceLogImpl extends AbstractLogImpl<RaceLogEvent, RaceLogEventVisit
|
||||
|
||||
@Override
|
||||
protected NavigableSet<RaceLogEvent> getInternalFixes() {
|
||||
return new PartialNavigableSetView<RaceLogEvent>(super.getInternalFixes()) {
|
||||
@Override
|
||||
protected boolean isValid(RaceLogEvent e) {
|
||||
return e.getPassId() == getCurrentPassId();
|
||||
}
|
||||
};
|
||||
return new FilteredPartialNavigableSetView<>(super.getInternalFixes(), new PassValidator(getCurrentPassId()));
|
||||
}
|
||||
}
|
||||
+15
-9
@@ -77,16 +77,22 @@ public class RegattaLogDeviceMappingFinder<ItemT extends WithID>
|
||||
|
||||
protected void findUnrevokedMappingAndClosingEvents(Map<ItemT, List<RegattaLogDeviceMappingEvent<ItemT>>> events,
|
||||
Map<Serializable, RegattaLogCloseOpenEndedDeviceMappingEvent> closingEvents) {
|
||||
for (RegattaLogEvent e : getLog().getUnrevokedEvents()) {
|
||||
if (e instanceof RegattaLogDeviceMappingEvent && isValidMapping(((RegattaLogDeviceMappingEvent<?>) e))) {
|
||||
@SuppressWarnings("unchecked")
|
||||
RegattaLogDeviceMappingEvent<ItemT> mappingEvent = (RegattaLogDeviceMappingEvent<ItemT>) e;
|
||||
getMappingEventsForItem(events, mappingEvent.getMappedTo()).add(mappingEvent);
|
||||
} else if (e instanceof RegattaLogCloseOpenEndedDeviceMappingEvent) {
|
||||
//a higher priority closing events for the same mapping event overwrites the lower priority one
|
||||
RegattaLogCloseOpenEndedDeviceMappingEvent closingEvent = (RegattaLogCloseOpenEndedDeviceMappingEvent) e;
|
||||
closingEvents.put(closingEvent.getDeviceMappingEventId(), closingEvent);
|
||||
final RegattaLog regattaLog = getLog();
|
||||
regattaLog.lockForRead();
|
||||
try {
|
||||
for (RegattaLogEvent e : regattaLog.getUnrevokedEvents()) {
|
||||
if (e instanceof RegattaLogDeviceMappingEvent && isValidMapping(((RegattaLogDeviceMappingEvent<?>) e))) {
|
||||
@SuppressWarnings("unchecked")
|
||||
RegattaLogDeviceMappingEvent<ItemT> mappingEvent = (RegattaLogDeviceMappingEvent<ItemT>) e;
|
||||
getMappingEventsForItem(events, mappingEvent.getMappedTo()).add(mappingEvent);
|
||||
} else if (e instanceof RegattaLogCloseOpenEndedDeviceMappingEvent) {
|
||||
//a higher priority closing events for the same mapping event overwrites the lower priority one
|
||||
RegattaLogCloseOpenEndedDeviceMappingEvent closingEvent = (RegattaLogCloseOpenEndedDeviceMappingEvent) e;
|
||||
closingEvents.put(closingEvent.getDeviceMappingEventId(), closingEvent);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
regattaLog.unlockAfterRead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -92,4 +92,6 @@ public interface DomainFactory {
|
||||
*/
|
||||
void addUpdateHandlers(String updateURL, String username, String password, Serializable eventId,
|
||||
RaceDefinition raceDefinition, DynamicTrackedRace trackedRace) throws URISyntaxException;
|
||||
|
||||
Map<Competitor, Boat> createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass, RaceTrackingHandler raceTrackHandler);
|
||||
}
|
||||
+2
-1
@@ -291,7 +291,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Competitor, Boat> createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass,
|
||||
@Override
|
||||
public Map<Competitor, Boat> createCompetitorsAndBoats(StartList startList, String raceId, BoatClass boatClass,
|
||||
RaceTrackingHandler raceTrackHandler) {
|
||||
Map<Competitor, Boat> result = new LinkedHashMap<>();
|
||||
for (com.sap.sailing.domain.swisstimingadapter.Competitor swissTimingCompetitor : startList.getCompetitors()) {
|
||||
|
||||
+12
-1
@@ -18,6 +18,7 @@ import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.sap.sailing.domain.base.Boat;
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.CompetitorAndBoatStore;
|
||||
@@ -65,6 +66,7 @@ import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.domain.tracking.TrackingDataLoader;
|
||||
import com.sap.sailing.domain.tracking.WindStore;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.RaceTrackingHandler.DefaultRaceTrackingHandler;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackingConnectorInfoImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.UpdateHandler;
|
||||
@@ -443,6 +445,15 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
this.startList = startList;
|
||||
if (oldStartList == null && course != null) {
|
||||
createRaceDefinition(course);
|
||||
} else if (trackedRace != null) {
|
||||
final Map<Competitor, Boat> competitorsAndTheirBoats = domainFactory.createCompetitorsAndBoats(startList, raceID, boatClass, new DefaultRaceTrackingHandler());
|
||||
if (!Util.setEquals(competitorsAndTheirBoats.keySet(), getRace().getCompetitors())) {
|
||||
try {
|
||||
trackedRegattaRegistry.updateRaceCompetitors(getRegatta(), getRace());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,7 +481,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
assert startList != null;
|
||||
assert course != null;
|
||||
// now we can create the RaceDefinition and most other things
|
||||
Race swissTimingRace = new RaceImpl(raceID, raceName, raceDescription, boatClass);
|
||||
final Race swissTimingRace = new RaceImpl(raceID, raceName, raceDescription, boatClass);
|
||||
try {
|
||||
synchronized (this) {
|
||||
race = domainFactory.createRaceDefinition(regatta, swissTimingRace, startList, course,
|
||||
|
||||
+2
-2
@@ -102,8 +102,8 @@ public class TestFarthestAheadWithSkippedMarkPassing {
|
||||
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED,
|
||||
/*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null,
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* courseArea */ null,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new,
|
||||
/* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false,
|
||||
OneDesignRankingMetric::new, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta);
|
||||
List<Waypoint> waypoints = new ArrayList<Waypoint>();
|
||||
// create a two-lap upwind/downwind course:
|
||||
|
||||
+2
-2
@@ -83,8 +83,8 @@ public class TestSimpleTimeOnTimeRankingWithOneUpwindLeg {
|
||||
RegattaImpl.getDefaultName("Test Regatta", boatClass.getName()), boatClass,
|
||||
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED, /*startDate*/ null, /*endDate*/ null, /* trackedRegattaRegistry */ null,
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), "123", /* courseArea */ null,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, TimeOnTimeAndDistanceRankingMetric::new,
|
||||
/* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false,
|
||||
TimeOnTimeAndDistanceRankingMetric::new, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta);
|
||||
List<Waypoint> waypoints = new ArrayList<Waypoint>();
|
||||
// create a two-lap upwind/downwind course:
|
||||
|
||||
+6
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
@@ -72,4 +73,9 @@ public class DummyTrackedRegattaRegistry implements TrackedRegattaRegistry {
|
||||
public Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceHandle updateRaceCompetitors(Regatta regatta, RaceDefinition race) throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+5
@@ -40,6 +40,7 @@ import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRul
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank;
|
||||
import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.RaceHandle;
|
||||
import com.sap.sailing.domain.tracking.RaceTracker;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
@@ -159,6 +160,10 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
public Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id) {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public RaceHandle updateRaceCompetitors(Regatta regatta, RaceDefinition race) throws Exception {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
LeaderboardDTO leaderboardDTO = leaderboard.getLeaderboardDTO(now, emptySet, /* addOverallDetails */ true, trackedRegattaRegistry, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false);
|
||||
assertNotNull(leaderboardDTO);
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class TestDeadlockInRegattaListener {
|
||||
/* startDate */ null, /* endDate */ null,
|
||||
/* trackedRegattaRegistry */ null, new LowPoint(), UUID.randomUUID(),
|
||||
/* courseArea */ null, /* controlTrackingFromStartAndFinishTimes */ true,
|
||||
OneDesignRankingMetric::new, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
/* autoRestartTrackingUponCompetitorSetChange */ false, OneDesignRankingMetric::new, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
DynamicTrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(regatta) {
|
||||
private static final long serialVersionUID = -3599667964201700780L;
|
||||
|
||||
|
||||
+10
@@ -618,6 +618,16 @@ public class MockedTrackedRace implements DynamicTrackedRace {
|
||||
@Override
|
||||
public void setCompetitorRegistrationType(CompetitorRegistrationType competitorRegistrationType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoRestartTrackingUponCompetitorSetChange() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoRestartTrackingUponCompetitorSetChange(
|
||||
boolean autoRestartTrackingUponCompetitorSetChange) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+5
-13
@@ -1,16 +1,13 @@
|
||||
package com.sap.sailing.domain.tractracadapter.persistence.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.sap.sailing.domain.racelog.RaceLogStore;
|
||||
@@ -28,7 +25,8 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.SessionUtils;
|
||||
import com.sap.sse.util.HttpUrlConnectionHelper;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.util.lib.api.exceptions.TimeOutException;
|
||||
|
||||
/**
|
||||
* Handles mapping TracTrac connectivity parameters from and to a map with {@link String} keys. The
|
||||
@@ -144,14 +142,8 @@ public class TracTracConnectivityParamsHandler extends AbstractRaceTrackingConne
|
||||
}
|
||||
|
||||
private void updatePersistentTracTracConfiguration(RaceTrackingConnectivityParametersImpl params)
|
||||
throws MalformedURLException, IOException, ParseException {
|
||||
final String EVENT_MANAGER_HOSTNAME_PREFIX = "em.";
|
||||
final URL paramsJsonUrl = new URL(params.getParamURL().getProtocol(),
|
||||
params.getParamURL().getHost().startsWith(EVENT_MANAGER_HOSTNAME_PREFIX) ? params.getParamURL().getHost() : EVENT_MANAGER_HOSTNAME_PREFIX+params.getParamURL().getHost(),
|
||||
"/events/"+params.getTractracRace().getEvent().getId().toString()+"/races/"+params.getTractracRace().getId().toString()+".json");
|
||||
final URLConnection conn = HttpUrlConnectionHelper.redirectConnection(paramsJsonUrl);
|
||||
final JSONObject paramsJson = (JSONObject) new JSONParser().parse(new InputStreamReader(conn.getInputStream()));
|
||||
final String jsonURL = (String) paramsJson.get("eventJSON");
|
||||
throws MalformedURLException, IOException, ParseException, CreateModelException, URISyntaxException, TimeOutException {
|
||||
final String jsonURL = params.getTractracRace().getParameterSet().getParameter("eventJSON");
|
||||
final String creatorName = SessionUtils.getPrincipal().toString();
|
||||
final TracTracConfigurationImpl tracTracConfiguration = new TracTracConfigurationImpl(creatorName, params.getTractracRace().getEvent().getName(), jsonURL,
|
||||
/* live URI */ null, /* stored URI */ null, // we mainly want to enable the user to list the event's races again in case they are removed; live/stored stuff comes from the tracking params
|
||||
|
||||
+4
-3
@@ -65,6 +65,7 @@ import com.tractrac.model.lib.api.route.IControlPoint;
|
||||
import com.tractrac.subscription.lib.api.IEventSubscriber;
|
||||
import com.tractrac.subscription.lib.api.IRaceSubscriber;
|
||||
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
|
||||
import com.tractrac.util.lib.api.exceptions.TimeOutException;
|
||||
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
@@ -152,8 +153,8 @@ public interface DomainFactory {
|
||||
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry, RaceLogAndTrackedRaceResolver raceLogResolver,
|
||||
LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler)
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException;
|
||||
RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException,
|
||||
IOException, InterruptedException, CreateModelException, TimeOutException;
|
||||
|
||||
/**
|
||||
* Same as {@link #createRaceTracker(URL, URI, URI, URI, TimePoint, TimePoint, WindStore, TrackedRegattaRegistry)},
|
||||
@@ -165,7 +166,7 @@ public interface DomainFactory {
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler)
|
||||
throws MalformedURLException, FileNotFoundException, URISyntaxException, CreateModelException,
|
||||
SubscriberInitializationException, IOException, InterruptedException;
|
||||
SubscriberInitializationException, IOException, InterruptedException, TimeOutException;
|
||||
|
||||
BoatClass getOrCreateBoatClass(String competitorClassName);
|
||||
|
||||
|
||||
+7
-5
@@ -116,6 +116,7 @@ import com.tractrac.model.lib.api.route.IControlPoint;
|
||||
import com.tractrac.subscription.lib.api.IEventSubscriber;
|
||||
import com.tractrac.subscription.lib.api.IRaceSubscriber;
|
||||
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
|
||||
import com.tractrac.util.lib.api.exceptions.TimeOutException;
|
||||
|
||||
import difflib.PatchFailedException;
|
||||
|
||||
@@ -497,8 +498,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
trackedRegattaRegistry,
|
||||
// use the low-point system as the default scoring scheme
|
||||
getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), race.getId(), null,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, rankingMetricConstructor,
|
||||
/* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false,
|
||||
rankingMetricConstructor, /* registrationLinkSecret */ UUID.randomUUID().toString());
|
||||
regattaCache.put(key, result);
|
||||
weakDefaultRegattaCache.put(race, result);
|
||||
logger.info("Created regatta "+result.getName()+" ("+result.hashCode()+") because none found for key "+key);
|
||||
@@ -645,7 +646,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
try {
|
||||
raceDefinition = raceTrackingHandler.createRaceDefinition(trackedRegatta.getRegatta(), raceName, course, boatClass, competitorsAndBoats, raceId);
|
||||
} catch (RuntimeException exception) {
|
||||
final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition + " for regatta " + trackedRegatta.getRegatta();
|
||||
final String reasonForNotAddingRaceToRegatta = "Error while creating race " + raceDefinition
|
||||
+ " for regatta " + trackedRegatta.getRegatta() + ": " + exception.getMessage();
|
||||
errorWhileTryingToTrackRace(trackedRegatta, raceDefinitionSetToUpdate, raceDefinition, reasonForNotAddingRaceToRegatta);
|
||||
}
|
||||
} else {
|
||||
@@ -1029,7 +1031,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler)
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException {
|
||||
return new TracTracRaceTrackerImpl(this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
|
||||
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler);
|
||||
}
|
||||
@@ -1040,7 +1042,7 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, CreateModelException,
|
||||
SubscriberInitializationException, IOException, InterruptedException {
|
||||
SubscriberInitializationException, IOException, InterruptedException, TimeOutException {
|
||||
return new TracTracRaceTrackerImpl(regatta, this, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
|
||||
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds, raceTrackingHandler);
|
||||
}
|
||||
|
||||
+11
-9
@@ -25,6 +25,7 @@ import com.tractrac.model.lib.api.ModelLocator;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.model.lib.api.event.IRace;
|
||||
import com.tractrac.subscription.lib.api.SubscriberInitializationException;
|
||||
import com.tractrac.util.lib.api.exceptions.TimeOutException;
|
||||
|
||||
public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTrackingConnectivityParameters {
|
||||
|
||||
@@ -49,7 +50,6 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
|
||||
private final String raceVisibility;
|
||||
private final boolean useInternalMarkPassingAlgorithm;
|
||||
private final boolean preferReplayIfAvailable;
|
||||
private final transient IRace tractracRace;
|
||||
private final int timeoutInMillis;
|
||||
private final boolean useOfficialEventsToUpdateRaceLog;
|
||||
|
||||
@@ -78,11 +78,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
|
||||
this.useOfficialEventsToUpdateRaceLog = useOfficialEventsToUpdateRaceLog;
|
||||
this.paramURL = paramURL;
|
||||
this.timeoutInMillis = timeoutInMillis;
|
||||
if (timeoutInMillis == -1) {
|
||||
this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()));
|
||||
} else {
|
||||
this.tractracRace = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), timeoutInMillis);
|
||||
}
|
||||
final IRace tractracRace = getTractracRace();
|
||||
if (preferReplayIfAvailable && isReplayRace(tractracRace) &&
|
||||
(!Util.equalsWithNull(liveURI, tractracRace.getLiveURI()) || !Util.equalsWithNull(storedURI, tractracRace.getStoredURI()))) {
|
||||
logger.info("Replay format available and preferred for race " + tractracRace.getName()
|
||||
@@ -114,8 +110,14 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
|
||||
return tractracRace.getStoredURI() != null && tractracRace.getStoredURI().toString().toLowerCase().endsWith(".mtb");
|
||||
}
|
||||
|
||||
public IRace getTractracRace() {
|
||||
return tractracRace;
|
||||
public IRace getTractracRace() throws CreateModelException, URISyntaxException, TimeOutException {
|
||||
final IRace result;
|
||||
if (getTimeoutInMillis() == -1) {
|
||||
result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()));
|
||||
} else {
|
||||
result = ModelLocator.getEventFactory().createRace(new URI(paramURL.toString()), getTimeoutInMillis());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -127,7 +129,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
|
||||
public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore,
|
||||
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
long timeoutInMilliseconds, RaceTrackingHandler raceTrackingHandler) throws URISyntaxException,
|
||||
CreateModelException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
CreateModelException, SubscriberInitializationException, IOException, InterruptedException, TimeOutException {
|
||||
RaceTracker tracker = domainFactory.createRaceTracker(raceLogStore, regattaLogStore, windStore,
|
||||
trackedRegattaRegistry, raceLogResolver, leaderboardGroupResolver, this, timeoutInMilliseconds,
|
||||
raceTrackingHandler);
|
||||
|
||||
+19
-6
@@ -56,6 +56,7 @@ import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.util.impl.ThreadFactoryWithPriority;
|
||||
import com.tractrac.model.lib.api.event.CreateModelException;
|
||||
import com.tractrac.model.lib.api.event.DataSource;
|
||||
import com.tractrac.model.lib.api.event.ICompetitor;
|
||||
import com.tractrac.model.lib.api.event.IEvent;
|
||||
@@ -71,6 +72,7 @@ import com.tractrac.subscription.lib.api.event.IConnectionStatusListener;
|
||||
import com.tractrac.subscription.lib.api.event.ILiveDataEvent;
|
||||
import com.tractrac.subscription.lib.api.event.IStoredDataEvent;
|
||||
import com.tractrac.subscription.lib.api.race.IRacesListener;
|
||||
import com.tractrac.util.lib.api.exceptions.TimeOutException;
|
||||
|
||||
public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
implements IConnectionStatusListener, TracTracRaceTracker, DynamicRaceDefinitionSet, TrackingDataLoader {
|
||||
@@ -270,11 +272,12 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
* you expect things to have loaded; see also
|
||||
* {@link RaceTracker#TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS}.
|
||||
*/
|
||||
TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore,
|
||||
RegattaLogStore regattaLogStore, WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver, RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler)
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
TracTracRaceTrackerImpl(DomainFactory domainFactory, RaceLogStore raceLogStore, RegattaLogStore regattaLogStore,
|
||||
WindStore windStore, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler) throws URISyntaxException, SubscriberInitializationException,
|
||||
IOException, InterruptedException, CreateModelException, TimeOutException {
|
||||
this(/* regatta */ null, domainFactory, raceLogStore, regattaLogStore, windStore, trackedRegattaRegistry,
|
||||
raceLogResolver, leaderboardGroupResolver, connectivityParams, timeoutInMilliseconds,
|
||||
raceTrackingHandler);
|
||||
@@ -299,7 +302,7 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
RaceLogAndTrackedRaceResolver raceLogResolver, LeaderboardGroupResolver leaderboardGroupResolver,
|
||||
RaceTrackingConnectivityParametersImpl connectivityParams, long timeoutInMilliseconds,
|
||||
RaceTrackingHandler raceTrackingHandler)
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException {
|
||||
throws URISyntaxException, SubscriberInitializationException, IOException, InterruptedException, CreateModelException, TimeOutException {
|
||||
super(connectivityParams);
|
||||
final URL paramURL = connectivityParams.getParamURL();
|
||||
final URI liveURI = connectivityParams.getLiveURI();
|
||||
@@ -358,10 +361,20 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl
|
||||
|
||||
@Override
|
||||
public void deleteCompetitor(UUID competitorId) {
|
||||
try {
|
||||
trackedRegattaRegistry.updateRaceCompetitors(getRegatta(), getRace());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCompetitor(ICompetitor competitor) {
|
||||
try {
|
||||
trackedRegattaRegistry.updateRaceCompetitors(getRegatta(), getRace());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
eventSubscriber.subscribeCompetitors(competitorsListener);
|
||||
|
||||
@@ -238,11 +238,26 @@ public interface Regatta
|
||||
* show_bug.cgi?id=3588</a>.
|
||||
*/
|
||||
boolean isControlTrackingFromStartAndFinishTimes();
|
||||
|
||||
|
||||
/**
|
||||
* @see #isControlTrackingFromStartAndFinishTimes()
|
||||
*/
|
||||
void setControlTrackingFromStartAndFinishTimes(boolean controlTrackingFromStartAndFinishTimes);
|
||||
|
||||
/**
|
||||
* Tells whether in the scope of this regatta tracking of a race shall automatically be re-started if the competitor
|
||||
* registrations change. Removing the {@link TrackedRace tracked races} and {@link RaceDefinition}s affected is then
|
||||
* required because the {@link RaceDefinition#getCompetitors() set of competitors of a race} is modeled to be
|
||||
* immutable. As the set of competitors that are part of a tracked race is provided by the tracking connector, the
|
||||
* responsibility for adhering to this flag, which rather expresses a request than describes a fact, lies with the
|
||||
* respective connectors.
|
||||
*/
|
||||
boolean isAutoRestartTrackingUponCompetitorSetChange();
|
||||
|
||||
/**
|
||||
* @see #isAutoRestartTrackingUponCompetitorSetChange()
|
||||
*/
|
||||
void setAutoRestartTrackingUponCompetitorSetChange(boolean autoRestartTrackingUponCompetitorSetChange);
|
||||
|
||||
@Override
|
||||
default QualifiedObjectIdentifier getIdentifier() {
|
||||
|
||||
+19
-10
@@ -389,19 +389,28 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
}
|
||||
Set<Competitor> competitorSet = new HashSet<Competitor>();
|
||||
Util.addAll(competitors, competitorSet);
|
||||
RaceLog raceLog = getRaceLog(fleet);
|
||||
for (RaceLogEvent event : raceLog.getUnrevokedEventsDescending()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
|
||||
if (competitorSet.contains(registerEvent.getCompetitor())) {
|
||||
try {
|
||||
raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, event,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
final RaceLog raceLog = getRaceLog(fleet);
|
||||
final Set<RaceLogEvent> competitorRegistrationEventsToRevoke = new HashSet<>();
|
||||
raceLog.lockForRead();
|
||||
try {
|
||||
for (RaceLogEvent event : raceLog.getUnrevokedEventsDescending()) {
|
||||
if (event instanceof RegisterCompetitorEvent) {
|
||||
RegisterCompetitorEvent<?> registerEvent = (RegisterCompetitorEvent<?>) event;
|
||||
if (competitorSet.contains(registerEvent.getCompetitor())) {
|
||||
competitorRegistrationEventsToRevoke.add(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
raceLog.unlockAfterRead();
|
||||
}
|
||||
for (final RaceLogEvent eventToRevoke : competitorRegistrationEventsToRevoke) {
|
||||
try {
|
||||
raceLog.revokeEvent(raceLogEventAuthorForRaceColumn, eventToRevoke,
|
||||
"unregistering competitor because no longer selected for registration");
|
||||
} catch (NotRevokableException e) {
|
||||
logger.log(Level.WARNING, "could not unregister competitor by adding RevokeEvent", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
* show_bug.cgi?id=3588</a>.
|
||||
*/
|
||||
private boolean controlTrackingFromStartAndFinishTimes;
|
||||
|
||||
private boolean autoRestartTrackingUponCompetitorSetChange;
|
||||
|
||||
private boolean canBoatsOfCompetitorsChangePerRace;
|
||||
|
||||
@@ -169,7 +171,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
|
||||
/**
|
||||
* Constructs a regatta with an empty {@link RaceLogStore} and with
|
||||
* {@link Regatta#isControlTrackingFromStartAndFinishTimes()} set to {@code false}.
|
||||
* {@link Regatta#isControlTrackingFromStartAndFinishTimes()} and
|
||||
* {@link #isAutoRestartTrackingUponCompetitorSetChange()} set to {@code false}.
|
||||
*/
|
||||
public RegattaImpl(String name, BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType,
|
||||
TimePoint startDate, TimePoint endDate,
|
||||
@@ -178,13 +181,14 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
this(EmptyRaceLogStore.INSTANCE, EmptyRegattaLogStore.INSTANCE, name, boatClass, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType,
|
||||
startDate, endDate, series,
|
||||
persistent, scoringScheme, id, courseArea, 0.0, /* useStartTimeInference */true, /* controlTrackingFromStartAndFinishTimes */ false,
|
||||
rankingMetricConstructor, registrationLinkSecret);
|
||||
/* autoRestartTrackingUponCompetitorSetChange */ false, rankingMetricConstructor, registrationLinkSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a regatta with a single default series with empty race column list, and a single default fleet which
|
||||
* is not {@link #isPersistent() marked for persistence}. The regatta is created with
|
||||
* {@link Regatta#isControlTrackingFromStartAndFinishTimes()} set to {@code false}.
|
||||
* {@link Regatta#isControlTrackingFromStartAndFinishTimes()} and
|
||||
* {@link #isAutoRestartTrackingUponCompetitorSetChange()} set to {@code false}.
|
||||
*
|
||||
* @param trackedRegattaRegistry
|
||||
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
|
||||
@@ -199,8 +203,8 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, String registrationLinkSecret) {
|
||||
this(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType,
|
||||
startDate, endDate, trackedRegattaRegistry, scoringScheme,
|
||||
id, courseArea, /* controlTrackingFromStartAndFinishTimes */ false, OneDesignRankingMetric::new,
|
||||
registrationLinkSecret);
|
||||
id, courseArea, /* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false,
|
||||
OneDesignRankingMetric::new, registrationLinkSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,15 +221,15 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType,
|
||||
TimePoint startDate, TimePoint endDate, TrackedRegattaRegistry trackedRegattaRegistry,
|
||||
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea,
|
||||
boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor,
|
||||
String registrationLinkSecret) {
|
||||
boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange,
|
||||
RankingMetricConstructor rankingMetricConstructor, String registrationLinkSecret) {
|
||||
this(raceLogStore, regattaLogStore, name, boatClass, canBoatsOfCompetitorsChangePerRace, competitorRegistrationType,
|
||||
startDate, endDate, Collections.singletonList(new SeriesImpl(LeaderboardNameConstants.DEFAULT_SERIES_NAME,
|
||||
/* isMedal */false, /* isFleetsCanRunInParallel */ true, Collections
|
||||
.singletonList(new FleetImpl(LeaderboardNameConstants.DEFAULT_FLEET_NAME)),
|
||||
/* race column names */new ArrayList<String>(), trackedRegattaRegistry)), /* persistent */false,
|
||||
scoringScheme, id, courseArea, /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */true, controlTrackingFromStartAndFinishTimes,
|
||||
rankingMetricConstructor, registrationLinkSecret);
|
||||
autoRestartTrackingUponCompetitorSetChange, rankingMetricConstructor, registrationLinkSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,13 +241,14 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
BoatClass boatClass, boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType,
|
||||
TimePoint startDate, TimePoint endDate, Iterable<S> series, boolean persistent,
|
||||
ScoringScheme scoringScheme, Serializable id, CourseArea courseArea, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference,
|
||||
boolean controlTrackingFromStartAndFinishTimes, RankingMetricConstructor rankingMetricConstructor,
|
||||
String registrationLinkSecret) {
|
||||
boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange,
|
||||
RankingMetricConstructor rankingMetricConstructor, String registrationLinkSecret) {
|
||||
super(name);
|
||||
this.registrationLinkSecret = registrationLinkSecret;
|
||||
this.rankingMetricConstructor = rankingMetricConstructor;
|
||||
this.useStartTimeInference = useStartTimeInference;
|
||||
this.controlTrackingFromStartAndFinishTimes = controlTrackingFromStartAndFinishTimes;
|
||||
this.autoRestartTrackingUponCompetitorSetChange = autoRestartTrackingUponCompetitorSetChange;
|
||||
this.id = id;
|
||||
this.raceLogStore = raceLogStore;
|
||||
races = new ConcurrentHashMap<>();
|
||||
@@ -671,10 +676,20 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
return controlTrackingFromStartAndFinishTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoRestartTrackingUponCompetitorSetChange() {
|
||||
return autoRestartTrackingUponCompetitorSetChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlTrackingFromStartAndFinishTimes(boolean controlTrackingFromStartAndFinishTimes) {
|
||||
this.controlTrackingFromStartAndFinishTimes = controlTrackingFromStartAndFinishTimes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAutoRestartTrackingUponCompetitorSetChange(boolean autoRestartTrackingUponCompetitorSetChange) {
|
||||
this.autoRestartTrackingUponCompetitorSetChange = autoRestartTrackingUponCompetitorSetChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseStartTimeInference(boolean useStartTimeInference) {
|
||||
|
||||
+22
@@ -91,4 +91,26 @@ public interface TrackedRegattaRegistry {
|
||||
|
||||
Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id);
|
||||
|
||||
/**
|
||||
* Does what is necessary to react to an external change in the {@code race}'s set of competitors. This can, e.g.,
|
||||
* entail removing and re-tracking that race which, however, has to be explicitly
|
||||
* {@link Regatta#isAutoRestartTrackingUponCompetitorSetChange() permitted by the regatta} as it will lead to a
|
||||
* temporary unavailability of the race and any information related to it such as the leaderboard scores.
|
||||
* <p>
|
||||
* By and large, we assume that a race's {@link RaceDefinition#getCompetitors() set of competitors} remains
|
||||
* unchanged once the race has been created. There are, however, scenarios in which this causes some trouble. For
|
||||
* example, if tracking for a regatta shall be started early, so as to enable race officials to see the course
|
||||
* geometry and wind data for the first race of the day, then especially in self-service scenarios there may be late
|
||||
* competitors registrations that happen after tracking has been started. These competitors, depending on how the
|
||||
* connector in use works, may make it into the regatta's leaderboard, but not into the {@link RaceDefinition}. This
|
||||
* would be unfortunate as those competitors then would remain invisible until the race is reloaded.
|
||||
* <p>
|
||||
*
|
||||
* See also <a href="https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5219">bug 5219</a> for a discussion.
|
||||
*
|
||||
* @return {@code null} if it was not possible to re-load the race, either because the regatta doesn't allow for it,
|
||||
* or because the connectivity parameters were not found; a {@link RaceHandle} for the re-started race
|
||||
* otherwise.
|
||||
*/
|
||||
RaceHandle updateRaceCompetitors(Regatta regatta, RaceDefinition race) throws Exception;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.net.URISyntaxException;
|
||||
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.RegattaListener;
|
||||
import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
|
||||
public interface TrackerManager {
|
||||
@@ -14,7 +15,13 @@ public interface TrackerManager {
|
||||
* Creates a {@link RaceTracker} based on the {@code params}. If the {@code params} request
|
||||
* {@link RaceTrackingConnectivityParameters#isTrackWind() wind tracking}, a callback is
|
||||
* {@link RaceTracker#add(com.sap.sailing.domain.tracking.RaceTracker.RaceCreationListener) registered} with the
|
||||
* {@link RaceTracker} that, when the race has been created by the tracker, will start wind tracking.
|
||||
* {@link RaceTracker} that, when the race has been created by the tracker, will start wind tracking.<p>
|
||||
*
|
||||
* The effects of calling this operation will be replicated by means of a listener that is notified when the connector
|
||||
* has successfully loaded and installed the race. {@code RacingEventServiceImpl.raceAdded(...)} which is notified
|
||||
* when the race definition has been added to the regatta (implementing {@link RegattaListener#raceAdded(Regatta, RaceDefinition)}),
|
||||
* and {@code RacingEventServiceImpl.RaceAdditionListener.raceAdded(...)} which is called when the {@link TrackedRace}
|
||||
* is added to the {@link TrackedRegatta}.
|
||||
*
|
||||
* @param regattaToAddTo
|
||||
* if <code>null</code> or no regatta by that identifier is found, the regatta into which the race has
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
target_bundles=$(cat "$1" | grep 'key="target_bundles"' | sed -e 's/^.* value="\([^"]*\)"\/>/\1/' | sed -e 's/,/\n/g' | sed -e 's/^\(.*\)@\(.*\):\(.*\)$/\1 \2 \3/')
|
||||
workspace_bundles=$(cat "$1" | grep 'key="workspace_bundles"' | sed -e 's/^.* value="\([^"]*\)"\/>/\1/' | sed -e 's/,/\n/g' | sed -e 's/^\(.*\)@\(.*\):\(.*\)$/\1 \2 \3/')
|
||||
echo " *** Target Bundles ***"
|
||||
echo "$target_bundles" | sort
|
||||
echo " *** Workspace Bundles ***"
|
||||
echo "$workspace_bundles" | sort
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
#!/bin/bash
|
||||
# Call like this: analyzeProduct.sh <my.product> [<my.launch> ...]
|
||||
# Will output two lines in format
|
||||
# <stringAttribute key="target_bundles" value="com.fasterxml.jackson.core.jackson-annotations@default:default,..."/>
|
||||
# <stringAttribute key="workspace_bundles" value="com.google.gwt.servlet@default:default,..."/>
|
||||
# Updates Eclipse .launch files with the bundles needed for starting an SAP Sailing server based on the current feature.xml.
|
||||
# The .launch files must be in the workspace format that was introduced with Eclipse 2019-12. The script prints an error when no matching
|
||||
# replacement section could be found.
|
||||
# Will output two sections in format
|
||||
# <setAttribute key="selected_target_bundles">
|
||||
# <setEntry value="com.fasterxml.jackson.core.jackson-annotations@default:default"/>
|
||||
# <setEntry value=".....
|
||||
# </setAttribute>
|
||||
# <setAttribute key="selected_workspace_bundles">
|
||||
# <setEntry value="com.google.gwt.servlet@default:default"/>
|
||||
# <setEntry value=".....
|
||||
# </setAttribute>
|
||||
# If one or more launch configuration files are provided as the remaining arguments, they will be patched in-place by
|
||||
# replacing the workspace_bundles and target_bundles string attributes by those generated by this script.
|
||||
# replacing the selected_workspace_bundles and selected_target_bundles string attributes by those generated by this script.
|
||||
# If the launch configuration's name contains the sub-string winddbTest, the additional bundle
|
||||
# ,com.sap.sailing.server.gateway.test.support@default:default
|
||||
# com.sap.sailing.server.gateway.test.support@default:default
|
||||
# is added to the workspace-bundles string.
|
||||
|
||||
# The product consists of the features and plugins it lists. Its <configuration> section overrides
|
||||
@@ -21,7 +30,7 @@
|
||||
# will be set to default:default unless the bundle occurs in the <configuration> section of the
|
||||
# .product definition in which case the start level and auto start values are copied from the
|
||||
# .product's <configuration> section.
|
||||
|
||||
NL=$'\n'
|
||||
GIT_ROOT=`dirname $0`/../../..
|
||||
echo "GIT ROOT: $GIT_ROOT"
|
||||
features=$(cat "$1" | grep "feature id=" | sed -e 's/^.*feature id="\([^"]*\)".*$/\1/')
|
||||
@@ -49,32 +58,45 @@ for feature in $features; do
|
||||
if [ "$?" == "0" ]; then
|
||||
# found a configuration for the bundle
|
||||
echo ' *** Found a non-default configuration for bundle '${bundle}' ***'
|
||||
bundle_spec_for_launch=$(echo "$autostart_bundles" | grep '^'${bundle}' [^ ]* [^ ]*$' | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\)$/\1@\2:\3/')
|
||||
bundle_spec_for_launch=$(echo "$autostart_bundles" | grep '^'${bundle}' [^ ]* [^ ]*$' | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\)$/\1\\@\2:\3/')
|
||||
else
|
||||
bundle_spec_for_launch="${bundle}@default:default"
|
||||
bundle_spec_for_launch="${bundle}\@default:default"
|
||||
fi
|
||||
if [[ $feature =~ .runtime$ ]]; then
|
||||
# contribute to target_bundles
|
||||
target_bundles="${target_bundles},${bundle_spec_for_launch}"
|
||||
target_bundles="${target_bundles}${NL}<setEntry value=\"${bundle_spec_for_launch}\"\/>"
|
||||
else
|
||||
# contribute to workspace_bundles
|
||||
workspace_bundles="${workspace_bundles},${bundle_spec_for_launch}"
|
||||
workspace_bundles="${workspace_bundles}${NL}<setEntry value=\"${bundle_spec_for_launch}\"\/>"
|
||||
fi
|
||||
done
|
||||
done
|
||||
echo ' *** Target Bundles ***'
|
||||
echo "<stringAttribute key=\"target_bundles\" value=\"${target_bundles:1}\"/>"
|
||||
echo "${target_bundles}"
|
||||
echo ' *** Workspace Bundles ***'
|
||||
echo "<stringAttribute key=\"workspace_bundles\" value=\"${workspace_bundles:1}\"/>"
|
||||
echo "${workspace_bundles}"
|
||||
# Now patch the .launch file if provided
|
||||
while [ "$2" != "" ]; do
|
||||
echo "Patching $2 ..."
|
||||
if echo "$2" | grep -q winddbTest; then
|
||||
patched_workspace_bundles="${workspace_bundles},com.sap.sailing.server.gateway.test.support@default:default"
|
||||
if grep -q key=\"target_bundles\" "$2"; then
|
||||
echo "Not patching $2 ... please use script for eclipse 2019-09 or older"
|
||||
else
|
||||
patched_workspace_bundles="${workspace_bundles}"
|
||||
echo "Patching $2 ..."
|
||||
if echo "$2" | grep -q winddbTest; then
|
||||
patched_workspace_bundles="${workspace_bundles}${NL}<setEntry value=\"com.sap.sailing.server.gateway.test.support@default:default\"\/>${NL}"
|
||||
else
|
||||
patched_workspace_bundles="${workspace_bundles}"
|
||||
fi
|
||||
selected_target_bundles="<setAttribute key=\"selected_target_bundles\">${target_bundles}${NL}<\/setAttribute>"
|
||||
patched_workspace_bundles="<setAttribute key=\"selected_workspace_bundles\">${patched_workspace_bundles}${NL}<\/setAttribute>"
|
||||
# Used Perl CLI options:
|
||||
#0 -> specifies the record separator, as you alread found out, it defaults to \0 so it does not terminate before the end of the text file. Ensures that the regular expression is applied over the whole file.
|
||||
#p -> apply looping wrapper, see perl man page
|
||||
#e -> denotes the (regular) expression that is goint ot be applied.
|
||||
#i -> inplace editing of files
|
||||
perl -i -p0e "s/<setAttribute key=\"selected_target_bundles\">.*?<\/setAttribute>/${selected_target_bundles}/s" "$2"
|
||||
perl -i -p0e "s/<setAttribute key=\"selected_workspace_bundles\">.*?<\/setAttribute>/${patched_workspace_bundles}/s" "$2"
|
||||
# remove eventuelly created bak files (this happens at least on windows platform)
|
||||
rm -f "$2.bak"
|
||||
fi
|
||||
sed -i 's/<stringAttribute key="target_bundles" value="[^"]*"/<stringAttribute key="target_bundles" value="'${target_bundles:1}'"/' "$2"
|
||||
sed -i 's/<stringAttribute key="workspace_bundles" value="[^"]*"/<stringAttribute key="workspace_bundles" value="'${patched_workspace_bundles:1}'"/' "$2"
|
||||
shift
|
||||
done
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
target_bundles=$(cat "$1" | grep "plugin id=" | sed -e 's/^.* id="\([^"]*\)".*$/\1/')
|
||||
echo " *** Target Bundles ***"
|
||||
echo "$target_bundles"
|
||||
@@ -494,4 +494,11 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="com.sap.sse.debranding"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class PingMarkViaRegattaLogTest {
|
||||
/* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED, /* registrationLinkSecret */ null, /*startDate*/ null, /*endDate*/ null,
|
||||
UUID.randomUUID(), Collections.<Series>singletonList(series),
|
||||
false, new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true,
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.ONE_DESIGN));
|
||||
/* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false, RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.ONE_DESIGN));
|
||||
RegattaLeaderboard leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {});
|
||||
|
||||
MarkDTO mark = new MarkDTO("mark", "mark", "m");
|
||||
|
||||
@@ -99,7 +99,7 @@ public class SlicingTest {
|
||||
seriesCreationParameters);
|
||||
final RegattaDTO regatta = sailingService.createRegatta(regattaName, boatClassName, false,
|
||||
CompetitorRegistrationType.CLOSED, null, null, null, regattaCreationParameters, false,
|
||||
ScoringSchemeType.HIGH_POINT, null, 3.0, false, false, RankingMetrics.ONE_DESIGN);
|
||||
ScoringSchemeType.HIGH_POINT, null, 3.0, false, false, /* autoRestartTrackingUponCompetitorSetChange */ false, RankingMetrics.ONE_DESIGN);
|
||||
final List<Pair<String, Integer>> columnNames = new ArrayList<>();
|
||||
columnNames.add(new Pair<>(columnNameOriginalRace, 0));
|
||||
sailingService.addRaceColumnsToSeries(regatta.getRegattaIdentifier(), seriesName, columnNames);
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<!-- -->
|
||||
<!-- Consider inlining CSS to reduce the number of requested files -->
|
||||
<!-- -->
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
|
||||
<!-- -->
|
||||
<!-- Any title is fine -->
|
||||
<!-- -->
|
||||
<title>SAP Sailing Analytics Administration Console</title>
|
||||
<title>${SAP}Sailing Analytics Administration Console</title>
|
||||
|
||||
<!-- AdminConsole is not prepared to work with nomalize. -->
|
||||
<!-- <link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css"> -->
|
||||
@@ -27,12 +27,16 @@
|
||||
<link rel="stylesheet" type="text/css" href="SettingsDialog.css">
|
||||
<link rel="stylesheet" type="text/css" href="AdminConsole.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
|
||||
<!-- Client-side QR code generation -->
|
||||
<script type="text/javascript" src="qrcode/qrcode.min.js"></script>
|
||||
|
||||
<!-- Client-side QR code generation -->
|
||||
<script type="text/javascript" src="qrcode/qrcode.min.js"></script>
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<!-- -->
|
||||
<!-- This script loads your compiled module. -->
|
||||
<!-- If you add any GWT meta tags, they must -->
|
||||
@@ -40,72 +44,72 @@
|
||||
<!-- -->
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.AdminConsole/com.sap.sailing.gwt.ui.AdminConsole.nocache.js"></script>
|
||||
|
||||
<!-- Loading Indicator -->
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
<!-- Loading Indicator -->
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<!-- -->
|
||||
@@ -126,10 +130,10 @@
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">SAP Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">${SAP}Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,13 +13,13 @@
|
||||
<!-- -->
|
||||
<!-- Consider inlining CSS to reduce the number of requested files -->
|
||||
<!-- -->
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
|
||||
<!-- -->
|
||||
<!-- Any title is fine -->
|
||||
<!-- -->
|
||||
<title>SAP Sailing Analytics AutoPlay</title>
|
||||
<title>${SAP}Sailing Analytics AutoPlay</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
@@ -39,7 +39,11 @@
|
||||
<script>
|
||||
videojs.options.techOrder = ['vimeo', 'youtube', 'html5'];
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="com.sap.sailing.gwt.autoplay.AutoPlay/com.sap.sailing.gwt.autoplay.AutoPlay.nocache.js"></script>
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<title>Your browser is unsupported</title>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -8,18 +8,22 @@
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<!-- This module isn't compatible with normalize. -->
|
||||
<!-- <link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css"> -->
|
||||
<link rel="stylesheet" type="text/css" href="/clean/sailing-clean-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="DataMining.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.DataMining/com.sap.sailing.gwt.ui.DataMining.nocache.js"></script>
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.DataMining/com.sap.sailing.gwt.ui.DataMining.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -2,94 +2,98 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!--[if lt IE 9]>
|
||||
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
|
||||
<![endif]-->
|
||||
<!--[if lt IE 9]>
|
||||
<meta http-equiv="REFRESH" content="0; url=/browser-info.html">
|
||||
<![endif]-->
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics Race Board</title>
|
||||
<title>${SAP}Sailing Analytics Race Board</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="EmbeddedMapAndWindChart.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="EmbeddedMapAndWindChart.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart.nocache.js"></script>
|
||||
|
||||
<!-- Loading Indicator -->
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
<!-- Loading Indicator -->
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
@@ -104,10 +108,10 @@
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">SAP Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">${SAP}Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -34,7 +34,6 @@
|
||||
</listAttribute>
|
||||
<booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.debug.ui.INCLUDE_EXTERNAL_JARS" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="false"/>
|
||||
<listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8" javaProject="com.sap.sailing.gwt.ui" path="1" type="4"/> "/>
|
||||
<listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry internalArchive="/com.sap.sailing.gwt.ui/src/main/resources" path="3" type="2"/> "/>
|
||||
@@ -116,6 +115,7 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="com.gwtplugins.gwt.eclipse.core.moduleClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-style PRETTY -incremental -war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9876 -startupUrl /gwt/Home.html -startupUrl /gwt/AdminConsole.html -startupUrl /gwt/PairingList.html -startupUrl /gwt/LeaderboardEditing.html -startupUrl /gwt/Leaderboard.html -startupUrl /gwt/Spectator.html -startupUrl /gwt/EmbeddedMapAndWindChart -startupUrl /gwt/RaceBoard.html -startupUrl /gwt/RegattaOverview.html -startupUrl /gwt/DataMining.html -startupUrl /gwt/Simulator.html -startupUrl /gwt/VideoPopup.html -startupUrl /gwt/AutoPlay.html -startupUrl /gwt/YoutubePopup.html com.sap.sailing.gwt.home.Home com.sap.sailing.gwt.ui.AdminConsole com.sap.sailing.gwt.ui.PairingList com.sap.sailing.gwt.ui.LeaderboardEditing com.sap.sailing.gwt.ui.Leaderboard com.sap.sailing.gwt.ui.Spectator com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart com.sap.sailing.gwt.ui.RaceBoard com.sap.sailing.gwt.regattaoverview.RegattaOverview com.sap.sailing.gwt.ui.DataMining com.sap.sailing.gwt.ui.Simulator com.sap.sailing.gwt.ui.VideoPopup com.sap.sailing.gwt.ui.YoutubePopup com.sap.sailing.gwt.autoplay.AutoPlay"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+UseG1GC -XX:+UseStringDeduplication -Dgwt.watchFileChanges=false -Xmx2048m -Dgwt-usearchives=false -Dgwt.persistentunitcache=false"/>
|
||||
|
||||
@@ -1,111 +1,115 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" selenium-id="shortcutIcon"/>
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon' selenium-id="appIcon">
|
||||
|
||||
<title>SAP Sailing - Homepage</title>
|
||||
<title>${SAP}Sailing - Homepage</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/sailing-fontface-1.0.cache.css">
|
||||
<script src="js/jquery-3.3.1.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="js/jquery.slick/slick-1.8.1.css"/>
|
||||
<script type="text/javascript" src="js/jquery.slick/slick-1.8.1.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="/sailing-fontface-1.0.cache.css">
|
||||
<script src="js/jquery-3.3.1.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="js/jquery.slick/slick-1.8.1.css"/>
|
||||
<script type="text/javascript" src="js/jquery.slick/slick-1.8.1.min.js"></script>
|
||||
|
||||
<link href="js/video-js/video-js.min.css" rel="stylesheet">
|
||||
<link href="js/video-js/video-js-sapsailing.css" rel="stylesheet">
|
||||
<script src="js/video-js/video.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="js/videojs-panorama.min.css"/>
|
||||
<script src="js/videojs-panorama.v5.min.js"></script>
|
||||
<script src="js/videojs-panorama.v5.min.js"></script>
|
||||
<script src="js/Youtube.min.js"></script>
|
||||
<script src="js/Vimeo.js"></script>
|
||||
<script>
|
||||
videojs.options.techOrder = ['vimeo', 'youtube', 'html5'];
|
||||
</script>
|
||||
|
||||
<script src="com.sap.sailing.gwt.home.Home/com.sap.sailing.gwt.home.Home.nocache.js"></script>
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
<script src="js/Vimeo.js"></script>
|
||||
<script>
|
||||
videojs.options.techOrder = ['vimeo', 'youtube', 'html5'];
|
||||
</script>
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script src="com.sap.sailing.gwt.home.Home/com.sap.sailing.gwt.home.Home.nocache.js"></script>
|
||||
<style type="text/css">
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
.loading > .sapsailing {
|
||||
margin: 40px;
|
||||
color: #008fcc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.loading > .waitmessage {
|
||||
margin: 60px 40px;
|
||||
}
|
||||
|
||||
.signal {
|
||||
border:3px solid #6a6a6a;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
height:300px;
|
||||
width:300px;
|
||||
margin: 0px auto;
|
||||
opacity:0;
|
||||
-webkit-animation: pulsate 2s ease-out;
|
||||
animation: pulsate 2s ease-out;
|
||||
-webkit-animation-iteration-count:infinite;
|
||||
animation-iteration-count:infinite;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@-webkit-keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsate {
|
||||
0% {
|
||||
-webkit-transform:scale(.1);
|
||||
transform:scale(.1);
|
||||
opacity: 0.0;
|
||||
}
|
||||
50% {
|
||||
opacity:1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform:scale(1.2);
|
||||
transform:scale(1.2);
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
|
||||
<noscript>
|
||||
<div
|
||||
style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
|
||||
Your web browser must have JavaScript enabled in order for this
|
||||
application to display correctly.</div>
|
||||
</noscript>
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">SAP Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
|
||||
<noscript>
|
||||
<div
|
||||
style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
|
||||
Your web browser must have JavaScript enabled in order for this
|
||||
application to display correctly.</div>
|
||||
</noscript>
|
||||
<div id="loading" class="loading">
|
||||
<p class="sapsailing">${SAP}Sailing Analytics</p>
|
||||
<p class="waitmessage">Loading, please wait...</p>
|
||||
<div class="signal"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,9 +2,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<title>SAP Sailing - Homepage</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<title>${SAP}Sailing - Homepage</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<title>SAP Sailing - Homepage</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<title>${SAP}Sailing - Homepage</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
@@ -6,20 +6,24 @@
|
||||
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
|
||||
<![endif]-->
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics Leaderboard</title>
|
||||
<title>${SAP}Sailing Analytics Leaderboard</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="Leaderboard.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="com.sap.sailing.gwt.ui.Leaderboard/com.sap.sailing.gwt.ui.Leaderboard.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<!-- -->
|
||||
<!-- Consider inlining CSS to reduce the number of requested files -->
|
||||
@@ -17,13 +17,17 @@
|
||||
<!-- -->
|
||||
<!-- Any title is fine -->
|
||||
<!-- -->
|
||||
<title>SAP Sailing Analytics Leaderboard Editing</title>
|
||||
<title>${SAP}Sailing Analytics Leaderboard Editing</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/clean/sailing-clean-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="SettingsDialog.css">
|
||||
<link rel="stylesheet" type="text/css" href="Leaderboard.css">
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<!-- -->
|
||||
<!-- This script loads your compiled module. -->
|
||||
<!-- If you add any GWT meta tags, they must -->
|
||||
|
||||
@@ -55,6 +55,7 @@ Require-Bundle: com.sap.sailing.domain,
|
||||
com.sap.sse.datamining.annotations,
|
||||
com.sap.sse.shared.android,
|
||||
com.sap.sailing.competitorimport,
|
||||
com.sap.sse.debranding,
|
||||
com.sap.sailing.expeditionconnector,
|
||||
com.sap.sailing.expeditionconnector.common,
|
||||
org.mp4parser.isoparser;bundle-version="1.9.37",
|
||||
|
||||
@@ -6,20 +6,24 @@
|
||||
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
|
||||
<![endif]-->
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics PairingList</title>
|
||||
<title>${SAP}Sailing Analytics PairingList</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="PairingList.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="com.sap.sailing.gwt.ui.PairingList/com.sap.sailing.gwt.ui.PairingList.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!--[if lt IE 9]>
|
||||
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
|
||||
<![endif]-->
|
||||
<!--[if lt IE 9]>
|
||||
<meta http-equiv="REFRESH" content="0; url=http://www.sapsailing.com/browser-info.html">
|
||||
<![endif]-->
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics Race Board</title>
|
||||
<title>${SAP}Sailing Analytics Race Board</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="RaceBoard.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-reset-2.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="RaceBoard.css">
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<link href="js/video-js/video-js.min.css" rel="stylesheet">
|
||||
<link href="js/video-js/video-js-sapsailing.css" rel="stylesheet">
|
||||
@@ -32,7 +32,11 @@
|
||||
<script>
|
||||
videojs.options.techOrder = [ 'vimeo', 'html5' ];
|
||||
</script>
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.RaceBoard/com.sap.sailing.gwt.ui.RaceBoard.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -9,18 +9,22 @@
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<title>SAP Sailing Analytics Regatta Overview</title>
|
||||
<title>${SAP}Sailing Analytics Regatta Overview</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
language="javascript"
|
||||
src="com.sap.sailing.gwt.regattaoverview.RegattaOverview/com.sap.sailing.gwt.regattaoverview.RegattaOverview.nocache.js"
|
||||
></script>
|
||||
type="text/javascript"
|
||||
language="javascript"
|
||||
src="com.sap.sailing.gwt.regattaoverview.RegattaOverview/com.sap.sailing.gwt.regattaoverview.RegattaOverview.nocache.js"
|
||||
></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- OPTIONAL: include this if you want history support -->
|
||||
|
||||
@@ -3,23 +3,26 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Analytics Race Simulator</title>
|
||||
<title>${SAP}Sailing Analytics Race Simulator</title>
|
||||
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="Simulator.css">
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300,300italic' rel='stylesheet' type='text/css'>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="Simulator.css">
|
||||
|
||||
|
||||
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="com.sap.sailing.gwt.ui.Simulator/com.sap.sailing.gwt.ui.Simulator.nocache.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
<meta content='yes' name='apple-mobile-web-app-capable'>
|
||||
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
|
||||
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
|
||||
<link href='images/sap-sailing-app-icon.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!--<link href='http://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,300italic,400italic,500italic,700italic' rel='stylesheet' type='text/css'>-->
|
||||
<!-- -->
|
||||
<!-- Consider inlining CSS to reduce the number of requested files -->
|
||||
<!-- -->
|
||||
@@ -24,13 +24,17 @@
|
||||
<!-- -->
|
||||
<!-- Any title is fine -->
|
||||
<!-- -->
|
||||
<title>SAP Sailing Analytics Spectator Vision</title>
|
||||
<title>${SAP}Sailing Analytics Spectator Vision</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/clean/sailing-clean-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-fontface-1.0.cache.css">
|
||||
<link rel="stylesheet" type="text/css" href="Spectator.css">
|
||||
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<!-- -->
|
||||
<!-- This script loads your compiled module. -->
|
||||
<!-- If you add any GWT meta tags, they must -->
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Video</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<title>${SAP}Sailing Video</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.VideoPopup/com.sap.sailing.gwt.ui.VideoPopup.nocache.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/sailing-normalize-3.0.2.cache.css">
|
||||
|
||||
@@ -61,6 +61,15 @@
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet>
|
||||
<display-name>ClientConfigurationServlet</display-name>
|
||||
<servlet-name>ClientConfigurationServlet</servlet-name>
|
||||
<servlet-class>com.sap.sse.debranding.ClientConfigurationServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>ClientConfigurationServlet</servlet-name>
|
||||
<url-pattern>*.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet>
|
||||
<display-name>Status</display-name>
|
||||
<servlet-name>Status</servlet-name>
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<title>SAP Sailing Video</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap.ico" />
|
||||
<title>${SAP}Sailing Video</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
|
||||
<script>
|
||||
document.clientConfigurationContext = {
|
||||
debrandingActive: ${debrandingActive}
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="com.sap.sailing.gwt.ui.YoutubePopup/com.sap.sailing.gwt.ui.YoutubePopup.nocache.js"></script>
|
||||
<style type="text/css">
|
||||
html {overflow: auto;}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
+3
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.event.legacy;
|
||||
import com.google.gwt.place.shared.PlaceTokenizer;
|
||||
import com.sap.sailing.gwt.common.client.AbstractBasePlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class EventPlace extends AbstractBasePlace {
|
||||
private final String eventUuidAsString;
|
||||
@@ -35,7 +36,8 @@ public class EventPlace extends AbstractBasePlace {
|
||||
}
|
||||
|
||||
public String getTitle(String eventName) {
|
||||
return StringMessages.INSTANCE.sapSailing() + " - " + eventName;
|
||||
return (ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing()) + " - " + eventName;
|
||||
}
|
||||
|
||||
public String getEventUuidAsString() {
|
||||
|
||||
+4
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.event.legacy;
|
||||
import com.google.gwt.place.shared.PlaceTokenizer;
|
||||
import com.sap.sailing.gwt.common.client.AbstractBasePlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class RegattaPlace extends AbstractBasePlace {
|
||||
private final String eventUuidAsString;
|
||||
@@ -44,7 +45,9 @@ public class RegattaPlace extends AbstractBasePlace {
|
||||
}
|
||||
|
||||
public String getTitle(String eventName, String leaderboardName) {
|
||||
return StringMessages.INSTANCE.sapSailing() + " - " + StringMessages.INSTANCE.leaderboard() + ": " + leaderboardName;
|
||||
return (ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing()) + " - " + StringMessages.INSTANCE.leaderboard() + ": "
|
||||
+ leaderboardName;
|
||||
}
|
||||
|
||||
public String getEventUuidAsString() {
|
||||
|
||||
+4
-1
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.event.legacy;
|
||||
import com.google.gwt.place.shared.PlaceTokenizer;
|
||||
import com.sap.sailing.gwt.common.client.AbstractBasePlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class SeriesPlace extends AbstractBasePlace {
|
||||
private final String eventUuidAsString;
|
||||
@@ -44,7 +45,9 @@ public class SeriesPlace extends AbstractBasePlace {
|
||||
}
|
||||
|
||||
public String getTitle(String eventName, String leaderboardName) {
|
||||
return StringMessages.INSTANCE.sapSailing() + " - " + StringMessages.INSTANCE.leaderboard() + ": " + leaderboardName;
|
||||
return (ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing()) + " - " + StringMessages.INSTANCE.leaderboard() + ": "
|
||||
+ leaderboardName;
|
||||
}
|
||||
|
||||
public String getEventUuidAsString() {
|
||||
|
||||
+33
-1
@@ -1,7 +1,12 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.footer;
|
||||
|
||||
import static com.google.gwt.dom.client.Style.Display.NONE;
|
||||
import static com.sap.sse.gwt.shared.DebugConstants.DEBUG_ID_ATTRIBUTE;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.dom.client.Style.Display;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.DOM;
|
||||
@@ -15,14 +20,24 @@ import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace;
|
||||
import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace.WhatsNewNavigationTabs;
|
||||
import com.sap.sailing.gwt.home.shared.SwitchingEntryPoint;
|
||||
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.client.controls.languageselect.LanguageSelector;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
import com.sap.sse.gwt.shared.DebugConstants;
|
||||
|
||||
public class Footer extends Composite {
|
||||
private static FooterPanelUiBinder uiBinder = GWT.create(FooterPanelUiBinder.class);
|
||||
|
||||
interface FooterPanelUiBinder extends UiBinder<Widget, Footer> {
|
||||
}
|
||||
|
||||
|
||||
@UiField AnchorElement whatsNewAnchor;
|
||||
@UiField AnchorElement sapJobsAnchor;
|
||||
@UiField AnchorElement feedbackAnchor;
|
||||
@UiField LanguageSelector languageSelector;
|
||||
@UiField DivElement copyrightDiv;
|
||||
@UiField AnchorElement imprintAnchorLink;
|
||||
@UiField AnchorElement privacyAnchorLink;
|
||||
@UiField AnchorElement mobileUi;
|
||||
@UiField(provided = true)
|
||||
final PlaceNavigation<WhatsNewPlace> releaseNotesNavigation;
|
||||
@@ -44,6 +59,23 @@ public class Footer extends Composite {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
copyrightDiv.getStyle().setDisplay(NONE);
|
||||
languageSelector.setLabelText(StringMessages.INSTANCE.whitelabelFooterLanguage());
|
||||
sapJobsAnchor.getStyle().setDisplay(Display.NONE);
|
||||
feedbackAnchor.getStyle().setDisplay(Display.NONE);
|
||||
whatsNewAnchor.getStyle().setDisplay(Display.NONE);
|
||||
imprintAnchorLink.getStyle().setDisplay(Display.NONE);
|
||||
privacyAnchorLink.getStyle().setDisplay(Display.NONE);
|
||||
}
|
||||
copyrightDiv.setAttribute(DebugConstants.DEBUG_ID_ATTRIBUTE, "copyrightDiv");
|
||||
sapJobsAnchor.setAttribute(DEBUG_ID_ATTRIBUTE, "sapJobsAnchor");
|
||||
feedbackAnchor.setAttribute(DEBUG_ID_ATTRIBUTE, "feedbackAnchor");
|
||||
whatsNewAnchor.setAttribute(DEBUG_ID_ATTRIBUTE, "whatsNewAnchor");
|
||||
imprintAnchorLink.setAttribute(DEBUG_ID_ATTRIBUTE, "imprintAnchorLink");
|
||||
privacyAnchorLink.setAttribute(DEBUG_ID_ATTRIBUTE, "privacyAnchorLink");
|
||||
languageSelector.getElement().setAttribute(DEBUG_ID_ATTRIBUTE, "languageSelector");
|
||||
}
|
||||
|
||||
}
|
||||
+6
-6
@@ -10,32 +10,32 @@
|
||||
<!-- Website footer-->
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<div class="{res.mediaCss.small12} {res.mediaCss.medium9} {res.mediaCss.columns}">
|
||||
<div class="{local_res.css.sitefooter_copyright}">
|
||||
<div ui:field="copyrightDiv" class="{local_res.css.sitefooter_copyright}">
|
||||
<ui:text from='{i18n.footerCopyright}' />
|
||||
</div>
|
||||
<div class="{local_res.css.sitefooter_links}">
|
||||
<a ui:field="imprintAnchorLink" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<ui:text from='{i18n.footerLegal}' />
|
||||
</a>
|
||||
<a href="https://www.sap.com/about/legal/privacy.html" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<a ui:field="privacyAnchorLink" href="https://www.sap.com/about/legal/privacy.html" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<ui:text from='{i18n.footerPrivacy}' />
|
||||
</a>
|
||||
<a href="https://jobs.sap.com" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<a ui:field="sapJobsAnchor" href="https://jobs.sap.com" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<ui:text from='{i18n.footerJobs}'/>
|
||||
</a>
|
||||
<a href="mailto:sailing_analytics%40sap.com?subject=[SAP Sailing] Feedback" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<a ui:field="feedbackAnchor" href="mailto:sailing_analytics%40sap.com?subject=[SAP Sailing] Feedback" target="_blank" class="{local_res.css.sitefooter_links_link}">
|
||||
<ui:text from='{i18n.footerFeedback}' />
|
||||
</a>
|
||||
<a ui:field="mobileUi" href="HomeMobile.html"
|
||||
class="{local_res.css.sitefooter_links_link} {res.mediaCss.showonsmall} {res.mediaCss.hideonmedium} {res.mediaCss.hideonlarge}">
|
||||
Mobile
|
||||
</a>
|
||||
<a href="{releaseNotesNavigation.getSafeTargetUrl}" class="{local_res.css.sitefooter_links_link}">
|
||||
<a ui:field="whatsNewAnchor" href="{releaseNotesNavigation.getSafeTargetUrl}" class="{local_res.css.sitefooter_links_link}">
|
||||
<ui:text from='{i18n.whatsNew}' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<l:LanguageSelector labelText="{i18n.footerLanguage}" addStyleNames="{res.mediaCss.small12}
|
||||
<l:LanguageSelector ui:field="languageSelector" labelText="{i18n.footerLanguage}" addStyleNames="{res.mediaCss.small12}
|
||||
{res.mediaCss.medium3} {res.mediaCss.columns} {local_res.css.sitefooter_language}" />
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
|
||||
+21
@@ -1,9 +1,14 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.header;
|
||||
|
||||
import static com.sap.sse.gwt.shared.DebugConstants.DEBUG_ID_ATTRIBUTE;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.ImageElement;
|
||||
import com.google.gwt.dom.client.Style.Display;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
@@ -32,6 +37,8 @@ import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace.Solutions
|
||||
import com.sap.sailing.gwt.home.shared.places.start.StartPlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.client.mvp.PlaceChangedEvent;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
import com.sap.sse.gwt.shared.DebugConstants;
|
||||
import com.sap.sse.security.ui.authentication.view.AuthenticationMenuView;
|
||||
import com.sap.sse.security.ui.authentication.view.AuthenticationMenuViewImpl;
|
||||
|
||||
@@ -39,12 +46,15 @@ public class Header extends Composite {
|
||||
@UiField Anchor startPageLink;
|
||||
@UiField Anchor eventsPageLink;
|
||||
@UiField Anchor solutionsPageLink;
|
||||
@UiField AnchorElement logoAnchor;
|
||||
// @UiField Anchor sponsoringPageLink;
|
||||
|
||||
@UiField TextBox searchText;
|
||||
@UiField Button searchButton;
|
||||
|
||||
@UiField Anchor usermenu;
|
||||
|
||||
@UiField ImageElement logoImage;
|
||||
|
||||
private static final HyperlinkImpl HYPERLINK_IMPL = GWT.create(HyperlinkImpl.class);
|
||||
|
||||
@@ -96,6 +106,17 @@ public class Header extends Composite {
|
||||
});
|
||||
|
||||
authenticationMenuView = new AuthenticationMenuViewImpl(usermenu, HeaderResources.INSTANCE.css().loggedin(), HeaderResources.INSTANCE.css().open());
|
||||
|
||||
if (!ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
logoImage.getStyle().setDisplay(Display.NONE);
|
||||
solutionsPageLink.getElement().getStyle().setDisplay(Display.NONE);
|
||||
logoAnchor.setHref("");
|
||||
}
|
||||
|
||||
logoImage.setAttribute(DebugConstants.DEBUG_ID_ATTRIBUTE, "logoImage");
|
||||
solutionsPageLink.getElement().setAttribute(DEBUG_ID_ATTRIBUTE, "solutionsPageLink");
|
||||
logoAnchor.setAttribute(DEBUG_ID_ATTRIBUTE, "logoAnchor");
|
||||
eventsPageLink.getElement().setAttribute(DEBUG_ID_ATTRIBUTE, "eventsPage");
|
||||
}
|
||||
|
||||
@UiHandler("startPageLink")
|
||||
|
||||
+3
-3
@@ -9,8 +9,8 @@
|
||||
<!-- Website header-->
|
||||
<div class="{res.mediaCss.grid}">
|
||||
<div class="{local_res.css.siteheader_logo} {res.mediaCss.small2} {res.mediaCss.medium2} {res.mediaCss.large3} {res.mediaCss.columns}">
|
||||
<a href="https://www.sap.com/sponsorships">
|
||||
<img src="images/home/logo-small@2x.png" alt="{i18n.headerLogo}" class="{local_res.css.siteheader_logo_image}"></img>
|
||||
<a ui:field="logoAnchor" href="https://www.sap.com/sponsorships">
|
||||
<img ui:field="logoImage" src="images/home/logo-small@2x.png" alt="{i18n.headerLogo}" class="{local_res.css.siteheader_logo_image}"></img>
|
||||
<p class="{local_res.css.siteheader_logo_title}">
|
||||
<ui:text from='{i18n.headerLogo}' />
|
||||
</p>
|
||||
@@ -21,7 +21,7 @@
|
||||
styleName="{local_res.css.sitenavigation_link}" text="{i18n.home}" />
|
||||
<g:Anchor ui:field="eventsPageLink"
|
||||
styleName="{local_res.css.sitenavigation_link}" text="{i18n.events}" />
|
||||
<g:Anchor ui:field="solutionsPageLink"
|
||||
<g:Anchor ui:field="solutionsPageLink"
|
||||
styleName="{local_res.css.sitenavigation_link}" text="{i18n.solutions}" />
|
||||
<!--
|
||||
<g:Anchor ui:field="sponsoringPageLink"
|
||||
|
||||
+12
@@ -1,5 +1,7 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.sharing;
|
||||
|
||||
import static com.google.gwt.dom.client.Style.Display.NONE;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.http.client.UrlBuilder;
|
||||
@@ -7,7 +9,9 @@ import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class SharingButtons extends Composite {
|
||||
|
||||
@@ -16,6 +20,7 @@ public class SharingButtons extends Composite {
|
||||
interface SharingButtonsUiBinder extends UiBinder<Widget, SharingButtons> {
|
||||
}
|
||||
|
||||
@UiField HTMLPanel htmlPanel;
|
||||
@UiField AnchorElement mail;
|
||||
@UiField AnchorElement twitter;
|
||||
@UiField AnchorElement facebook;
|
||||
@@ -23,9 +28,16 @@ public class SharingButtons extends Composite {
|
||||
public SharingButtons() {
|
||||
SharingButtonsResources.INSTANCE.css().ensureInjected();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
if (!ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
htmlPanel.getElement().getStyle().setDisplay(NONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUp(SharingMetadataProvider provider) {
|
||||
if (!ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String shortText = provider.getShortText();
|
||||
String longText = provider.getLongText(Window.Location.getHref());
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.sharing.SharingButtonsResources" />
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.eventheader_sharing}">
|
||||
<g:HTMLPanel addStyleNames="{local_res.css.eventheader_sharing}" ui:field="htmlPanel">
|
||||
<a ui:field="mail" title="{i18n.sharingMailTooltip}"
|
||||
class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itememail}"></a>
|
||||
<a ui:field="twitter" title="{i18n.sharingTwitterTooltip}" target="_blank"
|
||||
|
||||
+14
-1
@@ -1,20 +1,33 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.socialfooter;
|
||||
|
||||
import static com.google.gwt.dom.client.Style.Display.NONE;
|
||||
import static com.sap.sse.gwt.shared.DebugConstants.DEBUG_ID_ATTRIBUTE;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class SocialFooter extends Composite {
|
||||
|
||||
interface SocialFooterUiBinder extends UiBinder<Widget, SocialFooter> {
|
||||
}
|
||||
|
||||
|
||||
private static SocialFooterUiBinder uiBinder = GWT.create(SocialFooterUiBinder.class);
|
||||
|
||||
@UiField
|
||||
HTMLPanel htmlPanel;
|
||||
|
||||
public SocialFooter() {
|
||||
SocialFooterResources.INSTANCE.css().ensureInjected();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
if (!ClientConfiguration.getInstance().isBrandingActive()) {
|
||||
htmlPanel.getElement().getStyle().setDisplay(NONE);
|
||||
}
|
||||
htmlPanel.getElement().setAttribute(DEBUG_ID_ATTRIBUTE, "socialFooter");
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
|
||||
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.socialfooter.SocialFooterResources" />
|
||||
<g:HTMLPanel>
|
||||
<g:HTMLPanel ui:field="htmlPanel">
|
||||
<!-- The search/social media page footer-->
|
||||
<div class="{local_res.css.socialfooter}">
|
||||
<div class="{res.mediaCss.grid}">
|
||||
|
||||
+9
-6
@@ -10,6 +10,7 @@ import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.Command;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.History;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
@@ -156,27 +157,29 @@ public class Solutions extends Composite {
|
||||
}
|
||||
|
||||
private void scrollToView(SolutionsNavigationTabs navigationTab) {
|
||||
final int actualScrollLeft = Window.getScrollLeft();
|
||||
if (navigationTab == null) {
|
||||
sapInSailingDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, 0);
|
||||
} else {
|
||||
switch (navigationTab) {
|
||||
case BuoyPingerApp:
|
||||
buoyPingerDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, buoyPingerDiv.getAbsoluteTop());
|
||||
break;
|
||||
case InSightApp:
|
||||
inSightDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, inSightDiv.getAbsoluteTop());
|
||||
break;
|
||||
case SapInSailing:
|
||||
sapInSailingDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, 0);
|
||||
break;
|
||||
case SailingAnalytics:
|
||||
sailingAnalyticsDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, sailingAnalyticsDiv.getAbsoluteTop());
|
||||
break;
|
||||
case RaceManagerApp:
|
||||
raceDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, raceDiv.getAbsoluteTop());
|
||||
break;
|
||||
case SailingSimulator:
|
||||
simulatorDiv.scrollIntoView();
|
||||
Window.scrollTo(actualScrollLeft, simulatorDiv.getAbsoluteTop());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -29,6 +29,7 @@ import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.gwt.client.LinkUtil;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class TabletAndDesktopMultiRegattaEventView extends Composite implements EventMultiregattaView {
|
||||
|
||||
@@ -92,7 +93,9 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements
|
||||
@Override
|
||||
public void navigateTabsTo(AbstractMultiregattaEventPlace place) {
|
||||
tabPanelUi.activatePlace(place);
|
||||
StringBuilder titleBuilder = new StringBuilder(StringMessages.INSTANCE.sapSailing()).append(" - ");
|
||||
StringBuilder titleBuilder = new StringBuilder(
|
||||
(ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing())).append(" - ");
|
||||
|
||||
titleBuilder.append(currentPresenter.showRegattaMetadata() ? currentPresenter.getRegattaMetadata()
|
||||
.getDisplayName() : currentPresenter.getEventDTO().getDisplayName());
|
||||
|
||||
+4
-1
@@ -32,6 +32,7 @@ import com.sap.sailing.gwt.ui.client.FlagImageResolver;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.gwt.client.LinkUtil;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class TabletAndDesktopRegattaEventView extends Composite implements EventRegattaView {
|
||||
|
||||
@@ -102,7 +103,9 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event
|
||||
@Override
|
||||
public void navigateTabsTo(AbstractEventRegattaPlace place) {
|
||||
tabPanelUi.activatePlace(place);
|
||||
StringBuilder titleBuilder = new StringBuilder(StringMessages.INSTANCE.sapSailing()).append(" - ");
|
||||
StringBuilder titleBuilder = new StringBuilder(
|
||||
(ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing())).append(" - ");
|
||||
|
||||
titleBuilder.append(currentPresenter.showRegattaMetadata() ? currentPresenter.getRegattaMetadata()
|
||||
.getDisplayName() : currentPresenter.getEventDTO().getDisplayName());
|
||||
|
||||
+4
-1
@@ -14,6 +14,7 @@ import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.seriesheader.SeriesHeader;
|
||||
import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class TabletAndDesktopSeriesView extends Composite implements SeriesView<AbstractSeriesTabPlace, SeriesView.Presenter> {
|
||||
private static final ApplicationHistoryMapper historyMapper = GWT.<ApplicationHistoryMapper> create(ApplicationHistoryMapper.class);
|
||||
@@ -49,7 +50,9 @@ public class TabletAndDesktopSeriesView extends Composite implements SeriesView<
|
||||
@Override
|
||||
public void navigateTabsTo(AbstractSeriesTabPlace place) {
|
||||
tabPanelUi.activatePlace(place);
|
||||
StringBuilder titleBuilder = new StringBuilder(StringMessages.INSTANCE.sapSailing()).append(" - ");
|
||||
StringBuilder titleBuilder = new StringBuilder(
|
||||
(ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing())).append(" - ");
|
||||
|
||||
titleBuilder.append(currentPresenter.getSeriesDTO().getDisplayName());
|
||||
|
||||
|
||||
+4
-2
@@ -6,11 +6,12 @@ import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
|
||||
public class SolutionsActivity extends AbstractActivity {
|
||||
private final SolutionsPlace solutionsPlace;
|
||||
private final SolutionsClientFactory clientFactory;
|
||||
|
||||
|
||||
public SolutionsActivity(SolutionsPlace place, SolutionsClientFactory clientFactory) {
|
||||
this.solutionsPlace = place;
|
||||
this.clientFactory = clientFactory;
|
||||
@@ -20,6 +21,7 @@ public class SolutionsActivity extends AbstractActivity {
|
||||
public void start(AcceptsOneWidget panel, EventBus eventBus) {
|
||||
SolutionsView solutionsView = clientFactory.createSolutionsView(solutionsPlace.getNavigationTab());
|
||||
panel.setWidget(solutionsView.asWidget());
|
||||
Window.setTitle(StringMessages.INSTANCE.sapSailing() + " - " + StringMessages.INSTANCE.solutions());
|
||||
Window.setTitle((ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing()) + " - " + StringMessages.INSTANCE.solutions());
|
||||
}
|
||||
}
|
||||
+1
@@ -33,6 +33,7 @@ public class TabletAndDesktopStartView extends Composite implements StartView {
|
||||
mainMedia = new MainMedia(navigator);
|
||||
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -7,6 +7,6 @@
|
||||
<!-- <s:mainsponsors.MainSponsors ui:field='mainSponsors'/> -->
|
||||
<dp:mainevents.MainEvents ui:field='mainEvents'/>
|
||||
<dp:mainmedia.MainMedia ui:field='mainMedia'/>
|
||||
<dp:socialfooter.SocialFooter/>
|
||||
<dp:socialfooter.SocialFooter ui:field="socialFooter"/>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+18
-12
@@ -18,11 +18,14 @@ import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
|
||||
import com.sap.sailing.gwt.ui.client.FlagImageResolver;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.gwt.shared.ClientConfiguration;
|
||||
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
|
||||
import com.sap.sse.security.ui.userprofile.desktop.userheader.UserHeader;
|
||||
|
||||
public class TabletAndDesktopUserProfileView extends Composite implements UserProfileView<AbstractUserProfilePlace, UserProfileView.Presenter> {
|
||||
private static final ApplicationHistoryMapper historyMapper = GWT.<ApplicationHistoryMapper> create(ApplicationHistoryMapper.class);
|
||||
public class TabletAndDesktopUserProfileView extends Composite
|
||||
implements UserProfileView<AbstractUserProfilePlace, UserProfileView.Presenter> {
|
||||
private static final ApplicationHistoryMapper historyMapper = GWT
|
||||
.<ApplicationHistoryMapper> create(ApplicationHistoryMapper.class);
|
||||
|
||||
private static MyBinder uiBinder = GWT.create(MyBinder.class);
|
||||
|
||||
@@ -31,14 +34,15 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
|
||||
interface MyBinder extends UiBinder<Widget, TabletAndDesktopUserProfileView> {
|
||||
}
|
||||
|
||||
@UiField StringMessages i18n;
|
||||
|
||||
@UiField
|
||||
StringMessages i18n;
|
||||
|
||||
@UiField(provided = true)
|
||||
TabPanel<AbstractUserProfilePlace, UserProfileView.Presenter, UserProfileTabView<AbstractUserProfilePlace>> tabPanelUi;
|
||||
|
||||
|
||||
@UiField(provided = true)
|
||||
UserHeader headerUi;
|
||||
|
||||
|
||||
@UiField(provided = true)
|
||||
UserProfilePreferencesTabView preferencesTabUi;
|
||||
|
||||
@@ -55,11 +59,11 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
|
||||
public void registerPresenter(final UserProfileView.Presenter currentPresenter) {
|
||||
this.currentPresenter = currentPresenter;
|
||||
tabPanelUi = new TabPanel<>(currentPresenter, historyMapper);
|
||||
|
||||
|
||||
headerUi = new UserHeader(SharedResources.INSTANCE);
|
||||
|
||||
|
||||
preferencesTabUi = new UserProfilePreferencesTabView(flagImageResolver);
|
||||
|
||||
|
||||
sailorProfileTabUi = new SailorProfileTabView(flagImageResolver);
|
||||
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
@@ -68,7 +72,9 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
|
||||
@Override
|
||||
public void navigateTabsTo(AbstractUserProfilePlace place) {
|
||||
tabPanelUi.activatePlace(place);
|
||||
StringBuilder titleBuilder = new StringBuilder(StringMessages.INSTANCE.sapSailing()).append(" - ");
|
||||
StringBuilder titleBuilder = new StringBuilder(
|
||||
(ClientConfiguration.getInstance().isBrandingActive() ? StringMessages.INSTANCE.sapSailing()
|
||||
: StringMessages.INSTANCE.whitelabelSailing())).append(" - ");
|
||||
|
||||
titleBuilder.append(place.getLocationTitle());
|
||||
|
||||
@@ -78,7 +84,7 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
|
||||
}
|
||||
Window.setTitle(titleBuilder.toString());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
|
||||
headerUi.setAuthenticationContext(authenticationContext);
|
||||
@@ -90,7 +96,7 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
|
||||
public void onTabSelection(TabPanelPlaceSelectionEvent e) {
|
||||
currentPresenter.handleTabPlaceSelection((TabView<?, UserProfileView.Presenter>) e.getSelectedActivity());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void showErrorInCurrentTab(IsWidget errorView) {
|
||||
tabPanelUi.overrideCurrentContentInTab(errorView);
|
||||
|
||||
Loaded 100 of 320 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user