diff --git a/.project b/.project index 162ae1089ed..0bf7812c78a 100644 --- a/.project +++ b/.project @@ -1,11 +1,31 @@ - - - sailing - - - - - - - - + + + sailing + + + + + + + + + + 1447316281613 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-java + + + + 1447316281626 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-mobile + + + + diff --git a/configuration/convertELBLogToApacheFormat b/configuration/convertELBLogToApacheFormat new file mode 100755 index 00000000000..4563874bf6e --- /dev/null +++ b/configuration/convertELBLogToApacheFormat @@ -0,0 +1,23 @@ +#!/bin/bash +PREFIX=$1 +shift +for i in $*; do + if [ ${i: -3} == ".gz" ]; then + gzip -cd $i + else + cat $i + fi | iconv -f ISO-8859-1 -t UTF8 | + sed -e 's/^\([^T]*\)T\([^.]*\)[^ ]* [^ ]* \([^:]*\):[^ ]* [^ ]* [^ ]* [^ ]* [^ ]* [^ ]* \([^ ]*\) \([^ ]*\) [^ ]* \(\"[^"]*\"\) \(\"[^"]*\"\).*$/'$PREFIX' \3 - - [\1:\2 +0000] \6 \4 \5 "http:\/\/'$PREFIX'" \7/' | + sed -e 's/\[\([0-9]*\)-01-\([0-9]*\):/\[\2\/Jan\/\1:/' | + sed -e 's/\[\([0-9]*\)-02-\([0-9]*\):/\[\2\/Feb\/\1:/' | + sed -e 's/\[\([0-9]*\)-03-\([0-9]*\):/\[\2\/Mar\/\1:/' | + sed -e 's/\[\([0-9]*\)-04-\([0-9]*\):/\[\2\/Apr\/\1:/' | + sed -e 's/\[\([0-9]*\)-05-\([0-9]*\):/\[\2\/May\/\1:/' | + sed -e 's/\[\([0-9]*\)-06-\([0-9]*\):/\[\2\/Jun\/\1:/' | + sed -e 's/\[\([0-9]*\)-07-\([0-9]*\):/\[\2\/Jul\/\1:/' | + sed -e 's/\[\([0-9]*\)-08-\([0-9]*\):/\[\2\/Aug\/\1:/' | + sed -e 's/\[\([0-9]*\)-09-\([0-9]*\):/\[\2\/Sep\/\1:/' | + sed -e 's/\[\([0-9]*\)-10-\([0-9]*\):/\[\2\/Oct\/\1:/' | + sed -e 's/\[\([0-9]*\)-11-\([0-9]*\):/\[\2\/Nov\/\1:/' | + sed -e 's/\[\([0-9]*\)-12-\([0-9]*\):/\[\2\/Dec\/\1:/' +done diff --git a/configuration/sailing b/configuration/sailing index f62b001fa48..53f4f45d248 100755 --- a/configuration/sailing +++ b/configuration/sailing @@ -27,17 +27,20 @@ start_servers() { MEMORY_PER_INSTANCE_IN_MB=`cat /proc/meminfo | grep MemTotal | awk '{printf("%i\n", ($2 / 1024 * 0.75 - 1500) / '$NUMBER_OF_INSTANCES' );}'` echo "Using ${MEMORY_PER_INSTANCE_IN_MB}MB as default heap size per instance." for conf in $JAVA_START_INSTANCES; do - echo "Checking for amazon update..." + echo "Checking for amazon update..." >>/var/log/sailing.out echo "MEMORY=\"${MEMORY_PER_INSTANCE_IN_MB}m\"" >>$SERVERS_DIR/$conf/env.sh su - sailing -c "cd $SERVERS_DIR/$conf && $GIT_REPOSITORY/java/target/refreshInstance.sh auto-install" 2>>/var/log/sailing.err >>/var/log/sailing.out ( # execute env.sh in a subshell which now has the same set of variables that the server will see source $SERVERS_DIR/$conf/env.sh - echo "Starting Java server $conf" + echo "Starting Java server \"$conf\"" >>/var/log/sailing.out su - sailing -c "cd $SERVERS_DIR/$conf && ./start" 2>>/var/log/sailing.err >>/var/log/sailing.out server_name="`echo $SERVER_NAME | tr [A-Z] [a-z]`" - echo "Appending macro invocation to $APACHE_CONFIR_DIR/001-events.conf to map ${server_name}.sapsailing.com to event with ID $EVENT_ID with server running on local port $SERVER_PORT..." >>/var/log/sailing.out - echo "Use Event $server_name.sapsailing.com \"$EVENT_ID\" 127.0.0.1 $SERVER_PORT" >>$APACHE_CONFIG_DIR/001-events.conf + echo "Appending macro invocation to $APACHE_CONFIG_DIR/001-events.conf to map ${server_name}.sapsailing.com to event with ID $EVENT_ID with server running on local port $SERVER_PORT..." >>/var/log/sailing.out + echo "Use Event ${server_name}.sapsailing.com \"$EVENT_ID\" 127.0.0.1 $SERVER_PORT" >>$APACHE_CONFIG_DIR/001-events.conf + HTTP_LOGROTATE=/etc/logrotate.d/httpd + echo "Patching $HTTP_LOGROTATE so that old logs go to /var/log/old/$SERVER_NAME/$INSTANCE_IP4" >>/var/log/sailing.out + sed -i -e "s/\/var\/log\/old\/\([^/]*\)\/\([^/ ]*\)/\/var\/log\/old\/$SERVER_NAME\/$INSTANCE_IP4/" $HTTP_LOGROTATE # terminating the subshell will forget all the variable assignments brought in by env.sh, clearing for the next server instance ) RETVAL=$? diff --git a/configuration/unique_ips_per_referrer b/configuration/unique_ips_per_referrer index 22e455f4517..d06f2201d0a 100755 --- a/configuration/unique_ips_per_referrer +++ b/configuration/unique_ips_per_referrer @@ -1,5 +1,12 @@ #!/bin/bash +CACHE=/var/log/old/cache/unique-ips-per-referrer +VISITED_FILES=$CACHE/visited +STATS=$CACHE/stats +MONTHS=$STATS/months + +mkdir -p "$STATS" + # groups Apache / httpd log entries into "${referrer}.ips" files, where ${referrer} is the # referrer URL identifying the "event"; the lines written to the .ips files hold the IP # address of the requestor, the date (not the time) and the user agent string. @@ -9,12 +16,38 @@ # A sample line: # 505Worlds2012.sapsailing.com 66.249.73.53 - - [12/Jan/2014:03:33:11 +0000] "GET /robots.txt HTTP/1.1" 404 238 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" -#cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]\" \"\([\"]*\)\"\(.*\)$/\1 \2 \5 \7/' -cat $* | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^\"]*\" [^ ]* [^ ]* \"[^\"]*\" \"\([^\"]*\)\"/\1 \2 \5 \7/' | while read referrer hit; do - echo "$hit" >>${referrer}.ips +for i in $*; do + grep -q "^$i\$" $VISITED_FILES + if [ "$?" = "0" ]; then + echo "Already visited $i; ignoring (edit $VISITED_FILES to change this)." + else + echo "Analyzing log file $i" + if [ ${i: -3} == ".gz" ]; then + gzip -cd $i + else + cat $i + fi | iconv -f ISO-8859-1 -t UTF8 | sed -e 's/^\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \[\([^:]*\):\([^]]*\)\] \"[^"]*\" [^ ]* [^ ]* \"[^"]*\" \"\([^"]*\)\"/\1 \2 \5 \7/' | while read referrer hit; do + echo "$hit" >>${STATS}/${referrer}.ips + done + echo "$i" >>$VISITED_FILES + fi done -for i in *.ips; do - echo -n "$i " +for i in ${STATS}/*.ips; do + echo -n "`basename $i .ips` " cat $i | sort -u | wc | awk '{ print $1; }' -done | tee unique-ips-days-useragents-per-event -echo "Done. Wrote results to `pwd`/unique-ips-days-useragents-per-event + # TODO consider producing an AWStats configuration file for each virtual host name and splitting all new logs into virtual host name-specific log files +done | tee $STATS/unique-ips-days-useragents-per-event +echo "Wrote total results to $STATS/unique-ips-days-useragents-per-event" + + +# Now filter and group by month +cat ${STATS}/*.ips | awk '{ print $2; }' | sed -e 's/^[0-9]*\///' | sort -u >$MONTHS +for month in `cat $MONTHS`; do + for i in ${STATS}/*.ips; do + echo -n "`basename $i .ips` " + cat $i | grep "^[^ ]* [0-9]*/$month .*" | sort -u | wc | awk '{ print $1; }' + # TODO consider producing an AWStats configuration file for each virtual host name and splitting all new logs into virtual host name-specific log files + done | tee $STATS/unique-ips-days-useragents-per-event-$month + echo "Wrote per-month results to $STATS/unique-ips-days-useragents-per-event-$month" +done +echo "Done." diff --git a/home.md b/home.md index 50ee84c389b..51cc280a2bd 100644 --- a/home.md +++ b/home.md @@ -32,6 +32,7 @@ SAP is at the center of today’s technology revolution, developing innovations * [[Operating Igtimi WindBots/windbot-operations]] * [[Monitoring Apache and RabbitMQ|wiki/monitoring-apache-and-rabbitmq]] * [[JMX Support|wiki/jmx]] + * [[Log File Analysis|wiki/log-file-analysis]] * Information for Developers * [[OnBoarding Information|wiki/onboarding]] * [[Cook Book|wiki/cook-book]] diff --git a/java/.project b/java/.project new file mode 100644 index 00000000000..2c17f2fa456 --- /dev/null +++ b/java/.project @@ -0,0 +1,67 @@ + + + java + + + + + + + + + + 1447316122256 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-com\.sap\..* + + + + 1447316122263 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-com\.google.* + + + + 1447316122270 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-com\.tractrac\..* + + + + 1447316122279 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-org\.json\..* + + + + 1447316122293 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-org\.moxieapps\..* + + + + 1447316122310 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-org\.openqa\..* + + + + diff --git a/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT sdm.launch b/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT sdm.launch index 3df14c0b671..e6230b9950b 100755 --- a/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT sdm.launch +++ b/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT sdm.launch @@ -1,47 +1,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT.launch b/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT.launch index 4d2ae11f9e2..20731950d47 100755 --- a/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT.launch +++ b/java/com.sap.sailing.dashboards.gwt/SailingDashboardsGWT.launch @@ -1,47 +1,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.dashboards.gwt/fonts/bebas.ttf b/java/com.sap.sailing.dashboards.gwt/fonts/bebas.ttf deleted file mode 100644 index eaff48668af..00000000000 Binary files a/java/com.sap.sailing.dashboards.gwt/fonts/bebas.ttf and /dev/null differ diff --git a/java/com.sap.sailing.dashboards.gwt/pom.xml b/java/com.sap.sailing.dashboards.gwt/pom.xml index 9bc75ff31f7..ec9512cb84d 100644 --- a/java/com.sap.sailing.dashboards.gwt/pom.xml +++ b/java/com.sap.sailing.dashboards.gwt/pom.xml @@ -11,19 +11,6 @@ com.sap.sailing.dashboards.gwt eclipse-plugin - - - sonatype - http://oss.sonatype.org/content/repositories/snapshots - - true - - - false - - - - javax.validation diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/RibDashboardDataRetriever.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/RibDashboardDataRetriever.java index 621710c6a66..7ef3fbd6c27 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/RibDashboardDataRetriever.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/RibDashboardDataRetriever.java @@ -89,8 +89,7 @@ public class RibDashboardDataRetriever implements TimeListener, RaceSelectionPro @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received RibDashboardRaceInfoDTO"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received RibDashboardRaceInfoDTO, "+caught.getMessage()); } }); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/WindBotDataRetriever.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/WindBotDataRetriever.java index 91acf82e65a..6f69bbca8c7 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/WindBotDataRetriever.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/dataretriever/WindBotDataRetriever.java @@ -89,8 +89,7 @@ public class WindBotDataRetriever implements TimeListener, WindBotDataRetrieverP @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received WindInfoForRaceDTO"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received WindInfoForRaceDTO, "+caught.getMessage()); } }); } @@ -157,8 +156,7 @@ public class WindBotDataRetriever implements TimeListener, WindBotDataRetrieverP loadWindBotData(finaloldTime, finalNewTime, result); } else { notifyListenersAboutNumberOfWindBotsReceivedIsZero(); - logger.log(Level.INFO, "RegattaAndRaceIdentifier for race which takes wind is null"); - logger.log(Level.INFO, "Can´t load wind data"); + logger.log(Level.INFO, "Can´t load wind data because RegattaAndRaceIdentifier for race which takes wind is null"); } } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/eventlogo/EventLogo.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/eventlogo/EventLogo.java index 93034b24a86..e9fe51f6920 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/eventlogo/EventLogo.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/eventlogo/EventLogo.java @@ -47,8 +47,7 @@ public class EventLogo extends Image { @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received EventDTO"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received EventDTO, "+caught.getMessage()); eventLogo.getElement().getStyle().setVisibility(Visibility.HIDDEN); } }); diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisCard.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisCard.java index f076671cc7c..60ebd904b53 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisCard.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisCard.java @@ -21,6 +21,8 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.dashboards.gwt.client.startanalysis.rankingtable.StartAnalysisStartRankTable; import com.sap.sailing.dashboards.gwt.shared.dto.startanalysis.StartAnalysisDTO; import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.gwt.ui.client.CompetitorColorProvider; +import com.sap.sailing.gwt.ui.client.CompetitorColorProviderImpl; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; @@ -65,7 +67,8 @@ public class StartlineAnalysisCard extends Composite implements HasWidgets, Star private SailingServiceAsync sailingServiceAsync; private StringMessages stringMessages; private final CompetitorSelectionModel competitorSelectionModel; - + private final CompetitorColorProvider colorProvider; + private final double WIND_LINE_ADVANTAGE_DIV_WIDTH_IN_PT = 185; private final double GEOMETRIC_LINE_ADVANTAGE_DIV_WIDTH_IN_PT = 210; private final int TABLE_MARGIN_IN_PT = 10; @@ -78,7 +81,8 @@ public class StartlineAnalysisCard extends Composite implements HasWidgets, Star stringMessages = StringMessages.INSTANCE; resources.combinedWindPanelStyle().ensureInjected(); this.sailingServiceAsync = sailingServiceAsync; - competitorSelectionModel = new CompetitorSelectionModel(/* hasMultiSelection */true); + colorProvider = new CompetitorColorProviderImpl(); + competitorSelectionModel = new CompetitorSelectionModel(/* hasMultiSelection */true, colorProvider); competitorSelectionModel.setCompetitors(startAnalysisDTO.getCompetitorDTOsFromStartAnaylsisCompetitorDTOs(), raceMap); initWidget(uiBinder.createAndBindUi(this)); @@ -146,7 +150,7 @@ public class StartlineAnalysisCard extends Composite implements HasWidgets, Star AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingServiceAsync, asyncActionsExecutor, null, Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier), 5000l /* requestInterval */); - raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel, + raceMap = new RaceMap(sailingServiceAsync, asyncActionsExecutor, null, timer, competitorSelectionModel, StringMessages.INSTANCE, false, false, false, false, startAnalysisDTO.regattaAndRaceIdentifier, resources.combinedWindPanelStyle(), /* showHeaderPanel */ true); raceMap.onRaceSelectionChange(Collections.singletonList(startAnalysisDTO.regattaAndRaceIdentifier)); diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisComponent.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisComponent.java index ec166f3b3cb..9645a09aab4 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisComponent.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startanalysis/StartlineAnalysisComponent.java @@ -201,8 +201,7 @@ public class StartlineAnalysisComponent extends Composite implements HasWidgets @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received startanalysis list"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received startanalysis list, "+caught.getMessage()); } }); } @@ -266,8 +265,7 @@ public class StartlineAnalysisComponent extends Composite implements HasWidgets @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received competitors for leaderboard name"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received competitors for leaderboard name, "+caught.getMessage()); } }); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startlineadvantage/StartlineAdvantagesByWindComponent.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startlineadvantage/StartlineAdvantagesByWindComponent.java index 0651e26541d..d29bf87d175 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startlineadvantage/StartlineAdvantagesByWindComponent.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/startlineadvantage/StartlineAdvantagesByWindComponent.java @@ -86,8 +86,7 @@ public class StartlineAdvantagesByWindComponent extends Composite implements Has @Override public void onFailure(Throwable caught) { - logger.log(Level.INFO, "Failed to received StartlineAdvantagesWithMaxAndAverageDTO"); - logger.log(Level.INFO, caught.getMessage()); + logger.log(Level.INFO, "Failed to received StartlineAdvantagesWithMaxAndAverageDTO, "+caught.getMessage()); } }); } diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/windchart/WindBotComponent.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/windchart/WindBotComponent.java index c1f797d4183..acba0c39e09 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/windchart/WindBotComponent.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/client/windchart/WindBotComponent.java @@ -174,7 +174,8 @@ public class WindBotComponent extends Composite implements HasWidgets, WindBotDa WindTrackInfoDTO windTrackInfoDTO = getWindTrackInfoDTOFromAndWindBotID(windInfoForRaceDTO, windBotId); if (windTrackInfoDTO != null) { logger.log(Level.INFO, "WindInfoForRaceDTO contains WindTrackInfoDTO for Windbot id "+ windBotId); - if (windTrackInfoDTO.windFixes != null && windTrackInfoDTO.windFixes.size() > 0) { + if (windTrackInfoDTO.windFixes != null) { + if (windTrackInfoDTO.windFixes.size() > 0) { logger.log(Level.INFO, "Upating UI with Wind Fixes for WindBot id "+ windBotId); Point[] speedPoints = convertWindFixListIntoPointsArray(windTrackInfoDTO.windFixes, WindType.SPEED); Point[] directionPoints = convertWindFixListIntoPointsArray(windTrackInfoDTO.windFixes, @@ -192,8 +193,11 @@ public class WindBotComponent extends Composite implements HasWidgets, WindBotDa movingAverageDirection.getAverage()); locationPointerCompass.windBotPositionChanged(windTrackInfoDTO.windFixes .get(windTrackInfoDTO.windFixes.size() - 1).position); + } else { + logger.log(Level.INFO, "WindTrackInfoDTO.windFixes is empty"); + } } else { - logger.log(Level.INFO, "WindTrackInfoDTO.windFixes is null or empty"); + logger.log(Level.INFO, "WindTrackInfoDTO.windFixes is null"); } } else { logger.log(Level.INFO, "WindInfoForRaceDTO does not contains WindTrackInfoDTO for Windbot id "+ windBotId); diff --git a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java index fd3d6c8eb2a..59452db071e 100644 --- a/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java +++ b/java/com.sap.sailing.dashboards.gwt/src/main/java/com/sap/sailing/dashboards/gwt/server/RibDashboardServiceImpl.java @@ -240,7 +240,7 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib } private Pair retrieveStartlineMarkPositionsFromStartLineWayPoint(Waypoint startLineWayPoint) { - Pair startLineMarkPositions = null; + Pair result = null; Iterator markIterator = startLineWayPoint.getMarks().iterator(); if (markIterator.hasNext()) { Mark startboat = (Mark) markIterator.next(); @@ -249,10 +249,12 @@ public class RibDashboardServiceImpl extends RemoteServiceServlet implements Rib TimePoint now = MillisecondsTimePoint.now(); Position startBoatPosition = getPositionFromMarkAtTimePoint(runningRace, startboat, now); Position pinEndPosition = getPositionFromMarkAtTimePoint(runningRace, pinEnd, now); - return new Pair(startBoatPosition, pinEndPosition); + if(startBoatPosition != null && pinEndPosition != null) { + result = new Pair(startBoatPosition, pinEndPosition); + } } } - return startLineMarkPositions; + return result; } private Position getPositionFromMarkAtTimePoint(TrackedRace trackedRace, Mark mark, TimePoint timePoint) { diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java index dd0ce21a1f7..d8215553eb1 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/BoatClassMasterdata.java @@ -1,14 +1,16 @@ package com.sap.sailing.domain.common; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import com.sap.sailing.domain.common.impl.MeterDistance; public enum BoatClassMasterdata { _18Footer ("18Footer", true, 8.90, 2.00, BoatHullType.MONOHULL, true, "18.Footer", "18ft", "18ft Skiff", "18. Footer"), - _2_4M ("2.4 Meter", true, 4.11, 0.81, BoatHullType.MONOHULL, false, "2.4M", "2.4mR", "2.4 Metre", "2.4-metre"), + _2_4M ("2.4 Meter", true, 4.11, 0.81, BoatHullType.MONOHULL, false, "2.4M", "2.4mR", "2.4 Metre", "2.4-metre", "24MR"), _5O5 ("5O5", true, 5.03, 1.88, BoatHullType.MONOHULL, true, "505", "5o5", "505er", "5o5er"), _12M ("12 Meter", true, 5.97, 1.43, BoatHullType.MONOHULL, true, "12M", "12mR", "12SQM", "12-metre", "12 metre"), _29ER ("29er", true, 4.45, 1.70, BoatHullType.MONOHULL, true), @@ -27,7 +29,7 @@ public enum BoatClassMasterdata { D_ONE ("D-One", true, 4.23, 2.31, BoatHullType.MONOHULL, true, "Devoti D-One", "DOne", "D_One"), DRAGON_INT ("Dragon Int.", true, 8.89, 1.96, BoatHullType.MONOHULL, true, "Drachen", "Dragon"), DYAS("Dyas", true, 7.15, 1.95, BoatHullType.MONOHULL, true), - EXTREME_40 ("Extreme 40", false, 12.2, 6.60, BoatHullType.CATAMARAN, true, "Extreme-40", "Extreme40", "ESS40"), + EXTREME_40 ("Extreme 40", false, 12.2, 6.60, BoatHullType.CATAMARAN, true, "Extreme-40", "Extreme40", "ESS40", "ess"), D_35 ("D35", false, 10.81, 6.89, BoatHullType.CATAMARAN, false), ELLIOTT_6M ("Elliott 6m", true, 6.0, 2.35, BoatHullType.MONOHULL, true, "Elliott6m"), EUROPE_INT ("Europe Int.", true, 3.35, 1.35, BoatHullType.MONOHULL, false, "Europe"), @@ -84,7 +86,6 @@ public enum BoatClassMasterdata { ORC_CLUB ("ORC Club", true, 13.83, 3.91, BoatHullType.MONOHULL, true), ORC_INTERNATIONAL ("ORC International", true, 13.83, 3.91, BoatHullType.MONOHULL, true, "ORC Int."); - private final String displayName; private final String[] alternativeNames; private final double hullLengthInMeter; @@ -93,6 +94,8 @@ public enum BoatClassMasterdata { private final boolean typicallyStartsUpwind; private final boolean hasAdditionalDownwindSail; + private static Map fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata; + private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeter, double hullBeamInMeter, BoatHullType hullType, boolean hasAdditionalDownwindSail, String... alternativeNames) { this.displayName = displayName; @@ -102,6 +105,17 @@ public enum BoatClassMasterdata { this.hullType = hullType; this.hasAdditionalDownwindSail = hasAdditionalDownwindSail; this.alternativeNames = alternativeNames; + addToCache(this); + } + + private void addToCache(BoatClassMasterdata boatClassMasterdata) { + if (fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata == null) { + fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata = new HashMap<>(); + } + fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata.put(unifyBoatClassName(getDisplayName()), this); + for (final String alternativeName : getAlternativeNames()) { + fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata.put(unifyBoatClassName(alternativeName), this); + } } private BoatClassMasterdata(String displayName, boolean typicallyStartsUpwind, double hullLengthInMeter, @@ -113,28 +127,45 @@ public enum BoatClassMasterdata { this.hullType = hullType; this.hasAdditionalDownwindSail = hasAdditionalDownwindSail; this.alternativeNames = null; + addToCache(this); } public static BoatClassMasterdata resolveBoatClass(String boatClassName) { - String boatClassNameToResolve = unifyBoatClassName(boatClassName); - for (BoatClassMasterdata boatClass : values()) { - if (unifyBoatClassName(boatClass.displayName).equals(boatClassNameToResolve)) { - return boatClass; - } else if (boatClass.alternativeNames != null) { - for (String name : boatClass.alternativeNames) { - if (unifyBoatClassName(name).equals(boatClassNameToResolve)) { - return boatClass; - } - } - } - } - return null; + return fromUnifiedDisplayAndAlternativeNamesToBoatClassMasterdata.get(unifyBoatClassName(boatClassName)); } + /** + * Maps the boatClassName string by removing all whitespace and converting to all upper case. + * Example: "Laser Int." becomes "LASERINT."

+ * + * Note that the mapping is not related to the set of {@link BoatClassMasterdata} objects known and works the same + * regardless of whether boatClassName matches any of the existing {@link BoatClassMasterdata} literals, + * display names or alternative names. + */ public static String unifyBoatClassName(String boatClassName) { return boatClassName == null ? null : boatClassName.toUpperCase().replaceAll("\\s+",""); } + /** + * If any of the existing {@link BoatClassMasterdata} objects has a matching {@link #unifyBoatClassName(String) + * unified} display or alternative name, the unified display name of that object is returned. Otherwise, the + * {@link #unifyBoatClassName(String) unified} boatClassName value is returned. Example: "LASER" and + * "Laser" and "LSR" and "lsr" and "Laser Int." and "LASER INT ." and "LASERINT." will all be mapped to "LASERINT." + * based on the boat class masterdata object whose display name is "Laser Int.". In turn, "xyz" and "x y z" will be + * mapped to "XYZ" without any matching {@link BoatClassMasterdata} object existing, simply based on the string + * mapping described for {@link #unifyBoatClassName(String)}. + */ + public static String unifyBoatClassNameBasedOnExistingMasterdata(String boatClassName) { + BoatClassMasterdata bcm = resolveBoatClass(boatClassName); + final String result; + if (bcm != null) { + result = unifyBoatClassName(bcm.getDisplayName()); + } else { + result = unifyBoatClassName(boatClassName); + } + return result; + } + public Distance getHullLength() { return new MeterDistance(hullLengthInMeter); } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java index 0309c084ccc..fc5368b9ebb 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/ScoringSchemeType.java @@ -3,5 +3,6 @@ package com.sap.sailing.domain.common; public enum ScoringSchemeType { LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE, HIGH_POINT_FIRST_GETS_TEN, HIGH_POINT_FIRST_GETS_ONE, LOW_POINT_WINNER_GETS_ZERO, HIGH_POINT_WINNER_GETS_SIX, HIGH_POINT_WINNER_GETS_FIVE, HIGH_POINT_WINNER_GETS_EIGHT, - HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION, HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT, LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07 + HIGH_POINT_WINNER_GETS_EIGHT_AND_INTERPOLATION, HIGH_POINT_FIRST_GETS_TEN_OR_EIGHT, LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07, + LOW_POINT_LEAGUE_OVERALL } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java index 7658519367d..8a9fa9017a9 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java @@ -26,6 +26,10 @@ public abstract class AbstractLeaderboardDTO implements Serializable { public Map rows; public boolean hasCarriedPoints; public int[] discardThresholds; + + /** + * Set to the non-null regatta name if this DTO represents a RegattaLeaderboard. + */ public String regattaName; public String displayName; public UUID defaultCourseAreaId; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java new file mode 100644 index 00000000000..09a4e29ebf2 --- /dev/null +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java @@ -0,0 +1,64 @@ +package com.sap.sailing.domain.common.dto; + +import java.io.Serializable; + +import com.sap.sse.common.Color; + +public class BoatDTO extends NamedDTO implements Serializable { + private static final long serialVersionUID = -4076992788294272162L; + + private String sailId; + private Color color; + + // for GWT + BoatDTO() {} + + public BoatDTO(String name, String sailId) { + this(name, sailId, null); + } + + public BoatDTO(String name, String sailId, Color color) { + super(name); + this.sailId = sailId; + this.color = color; + } + + public Color getColor() { + return color; + } + + public String getSailId() { + return sailId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((color == null) ? 0 : color.hashCode()); + result = prime * result + ((sailId == null) ? 0 : sailId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + BoatDTO other = (BoatDTO) obj; + if (color == null) { + if (other.color != null) + return false; + } else if (!color.equals(other.color)) + return false; + if (sailId == null) { + if (other.sailId != null) + return false; + } else if (!sailId.equals(other.sailId)) + return false; + return true; + } +} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java index a4ba1b6d676..7a60ac393cc 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTO.java @@ -14,10 +14,12 @@ public interface CompetitorDTO extends Serializable, MappableToDevice { String getCountryName(); - String getSailID(); - String getIdAsString(); + String getSailID(); + + BoatDTO getBoat(); + BoatClassDTO getBoatClass(); String getName(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java index 4b02ed850ce..ca059c63cc6 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/CompetitorDTOImpl.java @@ -21,9 +21,9 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial private String threeLetterIocCountryCode; private Color color; private String email; - private String sailID; private String idAsString; private BoatClassDTO boatClass; + private BoatDTO boat; private String imageURL; private String flagImageURL; private Double timeOnTimeFactor; @@ -32,17 +32,18 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial public CompetitorDTOImpl() {} public CompetitorDTOImpl(String name, Color color, String email, String twoLetterIsoCountryCode, String threeLetterIocCountryCode, - String countryName, String sailID, String idAsString, String imageURL, String flagImageURL, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) { + String countryName, String idAsString, String imageURL, String flagImageURL, + BoatDTO boat, BoatClassDTO boatClass, Double timeOnTimeFactor, Duration timeOnDistanceAllowancePerNauticalMile) { super(name); this.color = color; this.email = email; this.twoLetterIsoCountryCode = twoLetterIsoCountryCode; this.threeLetterIocCountryCode = threeLetterIocCountryCode; this.countryName = countryName; - this.sailID = sailID; this.idAsString = idAsString; this.imageURL = imageURL; this.flagImageURL = flagImageURL; + this.boat = boat; this.boatClass = boatClass; this.timeOnTimeFactor = timeOnTimeFactor; this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; @@ -53,8 +54,8 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial final int prime = 31; int result = super.hashCode(); result = prime * result + ((boatClass == null) ? 0 : boatClass.hashCode()); + result = prime * result + ((boat == null) ? 0 : boat.hashCode()); result = prime * result + ((idAsString == null) ? 0 : idAsString.hashCode()); - result = prime * result + ((sailID == null) ? 0 : sailID.hashCode()); result = prime * result + ((color == null) ? 0 : color.hashCode()); result = prime * result + ((email == null) ? 0 : email.hashCode()); result = prime * result + ((threeLetterIocCountryCode == null) ? 0 : threeLetterIocCountryCode.hashCode()); @@ -79,16 +80,16 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial return false; } else if (!boatClass.equals(other.boatClass)) return false; + if (boat == null) { + if (other.boat != null) + return false; + } else if (!boat.equals(other.boat)) + return false; if (idAsString == null) { if (other.idAsString != null) return false; } else if (!idAsString.equals(other.idAsString)) return false; - if (sailID == null) { - if (other.sailID != null) - return false; - } else if (!sailID.equals(other.sailID)) - return false; if (threeLetterIocCountryCode == null) { if (other.threeLetterIocCountryCode != null) return false; @@ -144,7 +145,7 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial @Override public String getSailID() { - return sailID; + return boat==null?null:boat.getSailId(); } @Override @@ -198,4 +199,9 @@ public class CompetitorDTOImpl extends NamedDTO implements CompetitorDTO, Serial public Duration getTimeOnDistanceAllowancePerNauticalMile() { return timeOnDistanceAllowancePerNauticalMile; } + + @Override + public BoatDTO getBoat() { + return boat; + } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java index 4a98fa6d73e..935b3f52ef8 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/IncrementalLeaderboardDTO.java @@ -9,10 +9,12 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import com.sap.sse.common.Cloner; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; /** * Reduces the transmission size of a {@link LeaderboardDTO} by comparing this object to a previous version of @@ -174,16 +176,20 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme } /** - * @param previousVersion needed because after serialization/deserialization, the transient {@link #previousLeaderboard} will be null + * @param previousVersion + * needed because after serialization/deserialization, the transient {@link #previousLeaderboard} + * will be null. + * @return a map whose keys are the {@link CompetitorDTO#getIdAsString()} of the competitors for which the value + * tells the set of keys that are unchanged */ - public Set> getAllUnchangedCompetitorsAndKeys(LeaderboardDTO previousVersion) { - Set> result = new HashSet>(); + public Map> getAllUnchangedCompetitorIdsAsStringAndKeys(LeaderboardDTO previousVersion) { + Map> result = new HashMap<>(); for (Map.Entry raceColumnNameAndBitSet : unchanged.entrySet()) { final long[] bitset = raceColumnNameAndBitSet.getValue(); if (bitset == null) { // this means that all entries for the column are unchanged for all competitors for (CompetitorDTO competitor : previousVersion.competitors) { - result.add(new com.sap.sse.common.Util.Pair(competitor, raceColumnNameAndBitSet.getKey())); + Util.add(result, competitor.getIdAsString(), raceColumnNameAndBitSet.getKey()); } } else { int competitorNumber = 0; @@ -191,7 +197,7 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme long bitValue = 1; for (int bit=0; bit(previousVersion.competitors.get(competitorNumber), raceColumnNameAndBitSet.getKey())); + Util.add(result, previousVersion.competitors.get(competitorNumber).getIdAsString(), raceColumnNameAndBitSet.getKey()); } bitValue <<= 1; competitorNumber++; @@ -321,6 +327,14 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme } private void applyThisToPreviousVersionByUpdatingThis(LeaderboardDTO previousVersion) { + // As a performance improvement for the GWT-compiled version of this class, try to avoid key types + // other than strings when there is a map or set to be implemented that has a lot of strain on the + // put / add / contains methods. For this, we use the competitor's getIdAsString() result that + // identifies them reasonably well. + final Map competitorsOfPreviousVersionByIdAsString = new HashMap<>(); + for (final CompetitorDTO c : previousVersion.competitors) { + competitorsOfPreviousVersionByIdAsString.put(c.getIdAsString(), c); + } if (this.updatedFromPreviousVersionWithId != null) { if (!this.updatedFromPreviousVersionWithId.equals(previousVersion.getId())) { throw new IllegalStateException("This incremental leaderboard DTO was already applied to a different previous version. It cannot be applied multiple times."); @@ -410,62 +424,66 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme row.competitor = expandedCompetitor; rows.put(expandedCompetitor, row); } - final Set rowsUnchangedForCompetitors = new HashSet(); + final Set rowsUnchangedForCompetitorsWithIdAsString = new HashSet<>(); if (rowsUnchanged != null) { - for (com.sap.sse.common.Util.Pair rowUnchanged : rowsUnchanged.getAllUnchangedCompetitorsAndKeys(previousVersion)) { - rowsUnchangedForCompetitors.add(rowUnchanged.getA()); - rows.put(rowUnchanged.getA(), previousVersion.rows.get(rowUnchanged.getA())); + for (Entry> rowUnchanged : rowsUnchanged.getAllUnchangedCompetitorIdsAsStringAndKeys(previousVersion).entrySet()) { + rowsUnchangedForCompetitorsWithIdAsString.add(rowUnchanged.getKey()); + final CompetitorDTO previousCompetitor = competitorsOfPreviousVersionByIdAsString.get(rowUnchanged.getKey()); + rows.put(previousCompetitor, previousVersion.rows.get(previousCompetitor)); } } - final Set> allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames = - unchangedLeaderboardEntries == null ? new HashSet>() : - unchangedLeaderboardEntries.getAllUnchangedCompetitorsAndKeys(previousVersion); + final Map> allUnchangedLeaderboardEntriesAsCompetitorIdsAsStringAndColumnNames = + unchangedLeaderboardEntries == null ? new HashMap>() : + unchangedLeaderboardEntries.getAllUnchangedCompetitorIdsAsStringAndKeys(previousVersion); if (unchangedLeaderboardEntries != null) { - for (com.sap.sse.common.Util.Pair competitorAndColumnName : allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames) { - CompetitorDTO previousCompetitor = competitorAndColumnName.getA(); - if (!rowsUnchangedForCompetitors.contains(previousCompetitor)) { // only care if not the entire row was marked unchanged - LeaderboardEntryDTO previousEntry = previousVersion.rows.get(previousCompetitor).fieldsByRaceColumnName.get( - competitorAndColumnName.getB()); - final LeaderboardRowDTO row = rows.get(previousCompetitor); - if (row != null) { // may be null if the competitor disappeared, e.g., because of suppression - row.fieldsByRaceColumnName.put(competitorAndColumnName.getB(), previousEntry); + for (Entry> competitorAndColumnNames : allUnchangedLeaderboardEntriesAsCompetitorIdsAsStringAndColumnNames.entrySet()) { + CompetitorDTO previousCompetitor = competitorsOfPreviousVersionByIdAsString.get(competitorAndColumnNames.getKey()); + for (final String columnName : competitorAndColumnNames.getValue()) { + if (!rowsUnchangedForCompetitorsWithIdAsString.contains(competitorAndColumnNames.getKey())) { // only care if not the entire row was marked unchanged + LeaderboardEntryDTO previousEntry = previousVersion.rows.get(previousCompetitor).fieldsByRaceColumnName.get(columnName); + final LeaderboardRowDTO row = rows.get(previousCompetitor); + if (row != null) { // may be null if the competitor disappeared, e.g., because of suppression + row.fieldsByRaceColumnName.put(columnName, previousEntry); + } } } } } if (legDetailsUnchanged != null) { - for (com.sap.sse.common.Util.Pair> competitorInPreviosAndColumnNameAndLegDetailsIndex : legDetailsUnchanged - .getAllUnchangedCompetitorsAndKeys(previousVersion)) { - CompetitorDTO previousCompetitor = competitorInPreviosAndColumnNameAndLegDetailsIndex.getA(); - final String raceColumnName = competitorInPreviosAndColumnNameAndLegDetailsIndex.getB().getA(); - // if it's already clear that the entire LeaderboardEntryDTO was unchanged, the entry in legDetailsUnchanged was - // merely a hint for column compression within legDetailsUnchanged and doesn't need to be handled here - if (!allUnchangedLeaderboardEntriesAsCompetitorsAndColumnNames - .contains(new com.sap.sse.common.Util.Pair(previousCompetitor, raceColumnName))) { - final LeaderboardRowDTO leaderboardRowDTO = rows.get(previousCompetitor); - LeaderboardEntryDTO leaderboardEntry = leaderboardRowDTO == null ? null - : leaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName); - if (leaderboardEntry != null) { - final LeaderboardRowDTO previousLeaderboardRowDTO = previousVersion.rows - .get(previousCompetitor); - final LeaderboardEntryDTO previousLeaderboardEntryDTO = previousLeaderboardRowDTO == null ? null - : previousLeaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName); - final List previousLegDetails = previousLeaderboardEntryDTO == null ? null - : previousLeaderboardEntryDTO.legDetails; - if (previousLegDetails == null) { - // the leg index can only be null if the previous leg details are null - leaderboardEntry.legDetails = null; - } else { - // here, the leg index cannot be null - if (leaderboardEntry.legDetails == null) { - leaderboardEntry.legDetails = new ArrayList(); + for (Entry>> competitorInPreviosAndColumnNameAndLegDetailsIndex : + legDetailsUnchanged.getAllUnchangedCompetitorIdsAsStringAndKeys(previousVersion).entrySet()) { + CompetitorDTO previousCompetitor = competitorsOfPreviousVersionByIdAsString.get(competitorInPreviosAndColumnNameAndLegDetailsIndex.getKey()); + for (final Pair columnNameAndLegDetailsIndex : competitorInPreviosAndColumnNameAndLegDetailsIndex.getValue()) { + final String raceColumnName = columnNameAndLegDetailsIndex.getA(); + // if it's already clear that the entire LeaderboardEntryDTO was unchanged, the entry in legDetailsUnchanged was + // merely a hint for column compression within legDetailsUnchanged and doesn't need to be handled here + final Set unchangedRaceColumnNamesForCompetitor; + if ((unchangedRaceColumnNamesForCompetitor=allUnchangedLeaderboardEntriesAsCompetitorIdsAsStringAndColumnNames.get(competitorInPreviosAndColumnNameAndLegDetailsIndex.getKey())) == null + || !unchangedRaceColumnNamesForCompetitor.contains(raceColumnName)) { + final LeaderboardRowDTO leaderboardRowDTO = rows.get(previousCompetitor); + LeaderboardEntryDTO leaderboardEntry = leaderboardRowDTO == null ? null + : leaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName); + if (leaderboardEntry != null) { + final LeaderboardRowDTO previousLeaderboardRowDTO = previousVersion.rows.get(previousCompetitor); + final LeaderboardEntryDTO previousLeaderboardEntryDTO = previousLeaderboardRowDTO == null ? null + : previousLeaderboardRowDTO.fieldsByRaceColumnName.get(raceColumnName); + final List previousLegDetails = previousLeaderboardEntryDTO == null ? null + : previousLeaderboardEntryDTO.legDetails; + if (previousLegDetails == null) { + // the leg index can only be null if the previous leg details are null + leaderboardEntry.legDetails = null; + } else { + // here, the leg index cannot be null + if (leaderboardEntry.legDetails == null) { + leaderboardEntry.legDetails = new ArrayList(); + } + final Integer pos = columnNameAndLegDetailsIndex.getB(); + ensureSize(leaderboardEntry.legDetails, pos + 1); + leaderboardEntry.legDetails.set(pos, previousLegDetails.get(pos)); } - final Integer pos = competitorInPreviosAndColumnNameAndLegDetailsIndex.getB().getB(); - ensureSize(leaderboardEntry.legDetails, pos + 1); - leaderboardEntry.legDetails.set(pos, previousLegDetails.get(pos)); } } - } + } } } } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java index e77f2fb7677..4016116068c 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PreviousCompetitorDTOImpl.java @@ -70,6 +70,12 @@ public class PreviousCompetitorDTOImpl implements CompetitorDTO { " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); } + @Override + public BoatDTO getBoat() { + throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ + " need to be replaced by an object of "+CompetitorDTOImpl.class.getName()+" after deserialization"); + } + @Override public Color getColor() { throw new RuntimeException("Internal error. Objects of type "+PreviousCompetitorDTOImpl.class.getName()+ diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java index 8adda83ea37..771e95856e8 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/RaceColumnDTO.java @@ -157,7 +157,7 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { public boolean isLive(FleetDTO fleet, long serverTimePointAsMillis) { boolean result = false; final RaceDTO raceDTO = racesPerFleet.get(fleet); - if(raceDTO != null) { + if (raceDTO != null) { result = raceDTO.isLive(serverTimePointAsMillis); } return result; @@ -169,7 +169,7 @@ public class RaceColumnDTO extends NamedDTO implements Serializable { public boolean hasLiveRaces(long serverTimePointAsMillis) { boolean result = false; - for(FleetDTO fleet: fleets) { + for (FleetDTO fleet: fleets) { result |= isLive(fleet, serverTimePointAsMillis); } return result; diff --git a/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF b/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF index c169680edd6..6b35a388318 100644 --- a/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.domain.persistence/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: com.sap.sse.mongodb, com.sap.sailing.server.gateway.serialization, com.sap.sse.common, com.sap.sse, - com.sap.sailing.server.gateway.serialization.shared.android + com.sap.sailing.server.gateway.serialization.shared.android, + com.sap.sse.shared.android Export-Package: com.sap.sailing.domain.persistence, com.sap.sailing.domain.persistence.impl; x-friends:="com.sap.sailing.domain.persistence.test, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index d132dd645c7..d83d3620927 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -41,7 +41,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; @@ -59,10 +58,30 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; @@ -70,6 +89,13 @@ import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorM import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; 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.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; @@ -198,19 +224,18 @@ import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.RGBColor; import com.sap.sse.common.impl.TimeRangeImpl; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; public class DomainObjectFactoryImpl implements DomainObjectFactory { private static final Logger logger = Logger.getLogger(DomainObjectFactoryImpl.class.getName()); private final CompetitorJsonDeserializer competitorDeserializer; private final DB database; - - private RaceLogEventRestoreFactory raceLogEventFactory; + private final DomainFactory baseDomainFactory; private final TypeBasedServiceFinder deviceIdentifierServiceFinder; private final TypeBasedServiceFinderFactory serviceFinderFactory; @@ -235,7 +260,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { this.baseDomainFactory = baseDomainFactory; this.competitorDeserializer = CompetitorJsonDeserializer.create(baseDomainFactory); this.database = db; - this.raceLogEventFactory = RaceLogEventRestoreFactory.INSTANCE; } @Override @@ -614,11 +638,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { // deprecated style: a DBObject whose keys are the escaped competitor names // new style: a BasicDBList whose entries are DBObjects with COMPETITOR_ID and COMPETITOR_DISPLAY_NAME fields if (competitorDisplayNames != null) { - for (Object o : (BasicDBList) competitorDisplayNames) { - DBObject competitorDisplayName = (DBObject) o; - final Serializable competitorId = (Serializable) competitorDisplayName.get(FieldNames.COMPETITOR_ID.name()); - final String displayName = (String) competitorDisplayName.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); - correctionsToUpdate.setDisplayNameByID(competitorId, displayName); + if (competitorDisplayNames instanceof BasicDBList) { + for (Object o : (BasicDBList) competitorDisplayNames) { + DBObject competitorDisplayName = (DBObject) o; + final Serializable competitorId = (Serializable) competitorDisplayName.get(FieldNames.COMPETITOR_ID.name()); + final String displayName = (String) competitorDisplayName.get(FieldNames.COMPETITOR_DISPLAY_NAME.name()); + correctionsToUpdate.setDisplayNameByID(competitorId, displayName); + } + } else { + logger.severe("Deprecated, now unreadable format of the "+FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name() + +" field for leaderboard "+dbLeaderboard.get(FieldNames.LEADERBOARD_NAME.name())+ + ". You will have to update the competitor display names manually: "+ + competitorDisplayNames); } } } @@ -1363,7 +1394,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Serializable id, Integer passId, List competitors, DBObject dbObject) { Wind wind = loadWind((DBObject) dbObject.get(FieldNames.WIND.name())); Boolean isMagnetic = (Boolean) dbObject.get(FieldNames.IS_MAGNETIC.name()); - return raceLogEventFactory.createWindFixEvent(createdAt, author, logicalTimePoint, id, competitors, passId, wind, isMagnetic == null ? true : isMagnetic); + return new RaceLogWindFixEventImpl(createdAt, logicalTimePoint, author, id, passId, wind, isMagnetic == null ? true : isMagnetic); } private RaceLogEvent loadRaceLogDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1380,7 +1411,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { (Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name())); TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM); TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO); - return raceLogEventFactory.createDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to); + return new RaceLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, passId, mappedTo, device, from, to); } private RaceLogEvent loadRaceLogDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1397,7 +1428,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name())); TimePoint from = loadTimePoint(dbObject, FieldNames.RACE_LOG_FROM); TimePoint to = loadTimePoint(dbObject, FieldNames.RACE_LOG_TO); - return raceLogEventFactory.createDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, device, mappedTo, passId, from, to); + return new RaceLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, passId, mappedTo, device, from, to); } private RaceLogEvent loadRaceLogDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1405,12 +1436,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String raceName = (String) dbObject.get(FieldNames.RACE_NAME.name()); BoatClass boatClass = baseDomainFactory.getOrCreateBoatClass((String) dbObject.get(FieldNames.BOAT_CLASS_NAME.name())); Serializable raceId = (Serializable) dbObject.get(FieldNames.RACE_ID.name()); - return raceLogEventFactory.createDenoteForTrackingEvent(createdAt, author, logicalTimePoint, id, passId, raceName, boatClass, raceId); + return new RaceLogDenoteForTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId, raceName, boatClass, raceId); } private RaceLogEvent loadRaceLogStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - return raceLogEventFactory.createStartTrackingEvent(createdAt, author, logicalTimePoint, id, passId); + return new RaceLogStartTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } private RaceLogEvent loadRaceLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1420,7 +1451,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String revokedEventType = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.RACE_LOG_REVOKED_REASON.name()); - return raceLogEventFactory.createRevokeEvent(createdAt, author, logicalTimePoint, id, passId, + return new RaceLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, passId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); } @@ -1428,20 +1459,20 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Serializable id, Integer passId, List competitors, DBObject dbObject) { Serializable competitorId = (Serializable) dbObject.get(FieldNames.RACE_LOG_COMPETITOR_ID.name()); Competitor comp = baseDomainFactory.getCompetitorStore().getExistingCompetitorById(competitorId); - return raceLogEventFactory.createRegisterCompetitorEvent(createdAt, author, logicalTimePoint, id, passId, comp); + return new RaceLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, passId, comp); } private RaceLogEvent loadRaceLogDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Mark mark = loadMark((DBObject) dbObject.get(FieldNames.RACE_LOG_MARK.name())); - return raceLogEventFactory.createDefineMarkEvent(createdAt, author, logicalTimePoint, id, passId, mark); + return new RaceLogDefineMarkEventImpl(createdAt, logicalTimePoint, author, id, passId, mark); } private RaceLogEvent loadRaceLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) dbObject.get(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name())); TimePoint closingTimePoint = loadTimePoint(dbObject, FieldNames.RACE_LOG_CLOSING_TIMEPOINT); - return raceLogEventFactory.createCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, passId, + return new RaceLogCloseOpenEndedDeviceMappingEventImpl(createdAt, logicalTimePoint, author, id, passId, deviceMappingEventId, closingTimePoint); } @@ -1454,19 +1485,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } else { logger.warning("Could not find additional scoring information attached to db log for " + dbObject.toString()); } - return raceLogEventFactory.createAdditionalScoringInformationEvent(createdAt, author, logicalTimePoint, id, competitors, passId, informationType); + return new RaceLogAdditionalScoringInformationEventImpl(createdAt, logicalTimePoint, author, id, passId, informationType); } private RaceLogEvent loadRaceLogProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { TimePoint protestStartTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_PROTEST_START_TIME); - return raceLogEventFactory.createProtestStartTimeEvent(createdAt, author, logicalTimePoint, id, competitors, passId, protestStartTime); + return new RaceLogProtestStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, protestStartTime); } private RaceLogEvent loadRaceLogStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { RacingProcedureType type = RacingProcedureType.valueOf(dbObject.get(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name()).toString()); - return raceLogEventFactory.createStartProcedureChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, type); + return new RaceLogStartProcedureChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, type); } private RaceLogEvent loadRaceLogGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, @@ -1476,14 +1507,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { if (dbObject.containsField(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name())) { golfDownTime = (Number) dbObject.get(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name()); } - return raceLogEventFactory.createGateLineOpeningTimeEvent(createdAt, author, logicalTimePoint, id, competitors, + return new RaceLogGateLineOpeningTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, gateLaunchStopTime == null ? null : gateLaunchStopTime.longValue(), golfDownTime.longValue()); } private RaceLogEvent loadRaceLogPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { String pathfinderId = dbObject.get(FieldNames.RACE_LOG_PATHFINDER_ID.name()).toString(); - return raceLogEventFactory.createPathfinderEvent(createdAt, author, logicalTimePoint, id, competitors, passId, pathfinderId); + return new RaceLogPathfinderEventImpl(createdAt, logicalTimePoint, author, id, passId, pathfinderId); } private RaceLogEvent loadRaceLogFinishPositioningConfirmedEvent(TimePoint createdAt, AbstractLogEventAuthor author, @@ -1496,7 +1527,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); } - return raceLogEventFactory.createFinishPositioningConfirmedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors); + return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); } private RaceLogEvent loadRaceLogFinishPositioningListChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, @@ -1504,36 +1535,36 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { BasicDBList dbPositionedCompetitorList = (BasicDBList) dbObject.get(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name()); CompetitorResults positionedCompetitors = loadPositionedCompetitors(dbPositionedCompetitorList); - return raceLogEventFactory.createFinishPositioningListChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors); + return new RaceLogFinishPositioningListChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, positionedCompetitors); } private RaceLogEvent loadRaceLogPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors) { - return raceLogEventFactory.createPassChangeEvent(createdAt, author, logicalTimePoint, id, competitors, passId); + return new RaceLogPassChangeEventImpl(createdAt, logicalTimePoint, author, id, passId); } private RaceLogCourseDesignChangedEvent loadRaceLogCourseDesignChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { String courseName = (String) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name()); CourseBase courseData = loadCourseData((BasicDBList) dbObject.get(FieldNames.RACE_LOG_COURSE_DESIGN.name()), courseName); - return raceLogEventFactory.createCourseDesignChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, courseData); + return new RaceLogCourseDesignChangedEventImpl(createdAt, logicalTimePoint, author, id, passId, courseData); } private RaceLogCourseAreaChangedEvent loadRaceLogCourseAreaChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Serializable courseAreaId = (Serializable) dbObject.get(FieldNames.COURSE_AREA_ID.name()); - return raceLogEventFactory.createCourseAreaChangedEvent(createdAt, author, logicalTimePoint, id, competitors, passId, courseAreaId); + return new RaceLogCourseAreaChangeEventImpl(createdAt, logicalTimePoint, author, id, passId, courseAreaId); } private RaceLogEvent loadRaceLogFixedMarkPassingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { TimePoint ofFixedPassing = loadTimePoint(dbObject, FieldNames.TIMEPOINT_OF_FIXED_MARKPASSING); Integer zeroBasedIndexOfWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_PASSED_WAYPOINT.name()); - return raceLogEventFactory.createFixedMarkPassingEvent(logicalTimePoint, author, id, competitors, passId, ofFixedPassing, zeroBasedIndexOfWaypoint); + return new RaceLogFixedMarkPassingEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, ofFixedPassing, zeroBasedIndexOfWaypoint); } private RaceLogEvent loadRaceLogSuppressedMarkPassingsEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { Integer zeroBasedIndexOfFirstSuppressedWaypoint = (Integer) dbObject.get(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name()); - return raceLogEventFactory.createSuppressedMarkPassingsEvent(logicalTimePoint, author, id, competitors, passId, zeroBasedIndexOfFirstSuppressedWaypoint); + return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, logicalTimePoint, author, id, competitors, passId, zeroBasedIndexOfFirstSuppressedWaypoint); } private CompetitorResults loadPositionedCompetitors(BasicDBList dbPositionedCompetitorList) { @@ -1581,22 +1612,21 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { return null; } - return raceLogEventFactory.createFlagEvent(createdAt, author, logicalTimePoint, id, competitors, passId, upperFlag, lowerFlag, displayed); + return new RaceLogFlagEventImpl(createdAt, logicalTimePoint, author, id, passId, upperFlag, lowerFlag, displayed); } private RaceLogStartTimeEvent loadRaceLogStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { TimePoint startTime = loadTimePoint(dbObject, FieldNames.RACE_LOG_EVENT_START_TIME); - final String nextStatusName = (String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name()); - final RaceLogRaceStatus nextStatus = nextStatusName==null?null:RaceLogRaceStatus.valueOf(nextStatusName); - return raceLogEventFactory.createStartTimeEvent(createdAt, author, logicalTimePoint, id, competitors, passId, startTime, nextStatus); + RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); + return new RaceLogStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, startTime, nextStatus); } private RaceLogStartOfTrackingEvent loadRaceLogStartOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - return raceLogEventFactory.createStartOfTrackingEvent(logicalTimePoint, author, id, competitors, passId); + return new RaceLogStartOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } private RaceLogEndOfTrackingEvent loadRaceLogEndOfTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { - return raceLogEventFactory.createEndOfTrackingEvent(logicalTimePoint, author, id, competitors, passId); + return new RaceLogEndOfTrackingEventImpl(createdAt, logicalTimePoint, author, id, passId); } private RaceLogDependentStartTimeEvent loadRaceLogDependentStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { @@ -1611,13 +1641,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final Duration startTimeDifference = startTimeDifferenceObject == null ? null : new MillisecondsDurationImpl(((Number) startTimeDifferenceObject).longValue()); RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); - return raceLogEventFactory.createDependentStartTimeEvent(createdAt, author, logicalTimePoint, id, competitors, + return new RaceLogDependentStartTimeEventImpl(createdAt, logicalTimePoint, author, id, passId, dependentRaceLog, startTimeDifference, nextStatus); } private RaceLogRaceStatusEvent loadRaceLogRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Integer passId, List competitors, DBObject dbObject) { RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf((String) dbObject.get(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name())); - return raceLogEventFactory.createRaceStatusEvent(createdAt, author, logicalTimePoint, id, competitors, passId, nextStatus); + return new RaceLogRaceStatusEventImpl(createdAt, logicalTimePoint, author, id, passId, nextStatus); } @Override @@ -1689,7 +1719,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { final Competitor comp = getCompetitorByID(dbObject); final Double timeOnTimeFactor = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_TIME_FACTOR.name()); - return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, author, logicalTimePoint, id, comp, timeOnTimeFactor); + return new RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnTimeFactor); } private RegattaLogEvent loadRegattaLogSetCompetitorTimeOnTimeFactorEvent(TimePoint createdAt, @@ -1698,7 +1728,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final Double timeOnDistanceSecondsAllowancePerNauticalMile = (Double) dbObject.get(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name()); final Duration timeOnDistanceAllowancePerNauticalMile = timeOnDistanceSecondsAllowancePerNauticalMile == null ? null : new MillisecondsDurationImpl((long) (timeOnDistanceSecondsAllowancePerNauticalMile*1000)); - return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, author, logicalTimePoint, id, comp, timeOnDistanceAllowancePerNauticalMile); + return new RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(createdAt, logicalTimePoint, author, id, comp, timeOnDistanceAllowancePerNauticalMile); } private RegattaLogRevokeEvent loadRegattaLogRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, @@ -1708,14 +1738,14 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { String revokedEventType = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name()); String revokedEventShortInfo = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name()); String reason = (String) dbObject.get(FieldNames.REGATTA_LOG_REVOKED_REASON.name()); - return new RegattaLogRevokeEventImpl(createdAt, author, logicalTimePoint, id, + return new RegattaLogRevokeEventImpl(createdAt, logicalTimePoint, author, id, revokedEventId, revokedEventType, revokedEventShortInfo, reason); } private RegattaLogRegisterCompetitorEvent loadRegattaLogRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) { Competitor comp = getCompetitorByID(dbObject); - return new RegattaLogRegisterCompetitorEventImpl(createdAt, author, logicalTimePoint, id, comp); + return new RegattaLogRegisterCompetitorEventImpl(createdAt, logicalTimePoint, author, id, comp); } private RegattaLogCloseOpenEndedDeviceMappingEvent loadRegattaLogCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, @@ -1742,7 +1772,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { Triple times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, FieldNames.RACE_LOG_FROM, FieldNames.REGATTA_LOG_TO, FieldNames.RACE_LOG_TO); final TimePoint from = times.getA(); final TimePoint to = times.getB(); - final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to); + final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); final boolean needsMigration = times.getC(); if (needsMigration) { // remove old version of mapping event @@ -1804,7 +1834,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { final TimePoint from = times.getA(); final TimePoint to = times.getB(); final boolean needsMigration = times.getC(); - final RegattaLogDeviceCompetitorMappingEventImpl result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to); + final RegattaLogDeviceCompetitorMappingEventImpl result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); if (needsMigration) { // remove old version of mapping event WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject); diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index a0c0ae078f3..0bbc0721096 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -1,1533 +1,1533 @@ -package com.sap.sailing.domain.persistence.impl; - -import java.io.Serializable; -import java.net.URL; -import java.util.List; -import java.util.Map.Entry; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.bson.types.ObjectId; -import org.json.simple.JSONObject; - -import com.mongodb.BasicDBList; -import com.mongodb.BasicDBObject; -import com.mongodb.BasicDBObjectBuilder; -import com.mongodb.DB; -import com.mongodb.DBCollection; -import com.mongodb.DBObject; -import com.mongodb.WriteConcern; -import com.mongodb.util.JSON; -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -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.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; -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.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; -import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.ControlPoint; -import com.sap.sailing.domain.base.ControlPointWithTwoMarks; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.RemoteSailingServerReference; -import com.sap.sailing.domain.base.SailingServerConfiguration; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.Venue; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.configuration.DeviceConfiguration; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; -import com.sap.sailing.domain.base.configuration.RegattaConfiguration; -import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherMulti; -import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.common.Bearing; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.domain.common.Positioned; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.Speed; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.racelog.tracking.TransformationException; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; -import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler; -import com.sap.sailing.domain.persistence.racelog.tracking.impl.PlaceHolderDeviceIdentifierMongoHandler; -import com.sap.sailing.domain.racelog.RaceLogIdentifier; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRegatta; -import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; -import com.sap.sse.common.Duration; -import com.sap.sse.common.NoCorrespondingServiceRegisteredException; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.TimeRange; -import com.sap.sse.common.Timed; -import com.sap.sse.common.TypeBasedServiceFinder; -import com.sap.sse.common.TypeBasedServiceFinderFactory; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; - -public class MongoObjectFactoryImpl implements MongoObjectFactory { - private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); - private final DB database; - private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); - private final TypeBasedServiceFinder deviceIdentifierServiceFinder; - - /** - * Uses null for the device type service finder and hence will be unable to store device identifiers. - * Use this constructor only for testing purposes or in cases where there will happen absolutely no access to - * {@link DeviceIdentifier} objects. - */ - public MongoObjectFactoryImpl(DB database) { - this(database, /* deviceTypeServiceFinder */ null); - } - - public MongoObjectFactoryImpl(DB database, TypeBasedServiceFinderFactory serviceFinderFactory) { - this.database = database; - if (serviceFinderFactory != null) { - this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class); - this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler()); - } else { - this.deviceIdentifierServiceFinder = null; - } - } - - @Override - public DB getDatabase() { - return database; - } - - public DBObject storeWind(Wind wind) { - DBObject result = new BasicDBObject(); - storePositioned(wind, result); - storeTimed(wind, result); - storeSpeedWithBearing(wind, result); - return result; - } - - public static void storeTimePoint(TimePoint timePoint, DBObject result, String fieldName) { - if (timePoint != null) { - result.put(fieldName, timePoint.asMillis()); - } - } - - public static void storeTimePoint(TimePoint timePoint, DBObject result, FieldNames field) { - storeTimePoint(timePoint, result, field.name()); - } - - public static void storeTimeRange(TimeRange timeRange, DBObject result, FieldNames field) { - if (timeRange != null) { - DBObject timeRangeObj = new BasicDBObject(); - storeTimePoint(timeRange.from(), timeRangeObj, FieldNames.FROM_MILLIS); - storeTimePoint(timeRange.to(), timeRangeObj, FieldNames.TO_MILLIS); - result.put(field.name(), timeRangeObj); - } - } - - public void storeTimed(Timed timed, DBObject result) { - if (timed.getTimePoint() != null) { - storeTimePoint(timed.getTimePoint(), result, FieldNames.TIME_AS_MILLIS); - } - } - - public void storeSpeedWithBearing(SpeedWithBearing speedWithBearing, DBObject result) { - storeSpeed(speedWithBearing, result); - storeBearing(speedWithBearing.getBearing(), result); - - } - - public void storeBearing(Bearing bearing, DBObject result) { - result.put(FieldNames.DEGREE_BEARING.name(), bearing.getDegrees()); - } - - public void storeSpeed(Speed speed, DBObject result) { - result.put(FieldNames.KNOT_SPEED.name(), speed.getKnots()); - } - - public void storePositioned(Positioned positioned, DBObject result) { - if (positioned.getPosition() != null) { - result.put(FieldNames.LAT_DEG.name(), positioned.getPosition().getLatDeg()); - result.put(FieldNames.LNG_DEG.name(), positioned.getPosition().getLngDeg()); - } - } - - @Override - public void addWindTrackDumper(TrackedRegatta trackedRegatta, TrackedRace trackedRace, WindSource windSource) { - WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource); - windTrack.addListener(new MongoWindListener(trackedRace, trackedRegatta.getRegatta().getName(), windSource, this, database)); - } - - public DBCollection getWindTrackCollection() { - DBCollection result = database.getCollection(CollectionNames.WIND_TRACKS.name()); - result.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), null)); - return result; - } - - public DBCollection getGPSFixCollection() { - DBCollection gpsFixCollection = database.getCollection(CollectionNames.GPS_FIXES.name()); - DBObject index = new BasicDBObject(); - index.put(FieldNames.DEVICE_ID.name(), null); - index.put(FieldNames.TIME_AS_MILLIS.name(), null); - gpsFixCollection.createIndex(index); - return gpsFixCollection; - } - - public DBCollection getGPSFixMetadataCollection() { - DBCollection collection = database.getCollection(CollectionNames.GPS_FIXES_METADATA.name()); - DBObject index = new BasicDBObject(); - index.put(FieldNames.DEVICE_ID.name(), null); - collection.createIndex(index); - return collection; - } - - /** - * @param regattaName - * the regatta name is stored only for human readability purposes because a time stamp may be a bit unhandy for - * identifying where the wind fix was collected - */ - public DBObject storeWindTrackEntry(RaceDefinition race, String regattaName, WindSource windSource, Wind wind) { - BasicDBObject result = new BasicDBObject(); - result.put(FieldNames.RACE_ID.name(), race.getId()); - result.put(FieldNames.REGATTA_NAME.name(), regattaName); - result.put(FieldNames.WIND_SOURCE_NAME.name(), windSource.name()); - if (windSource.getId() != null) { - result.put(FieldNames.WIND_SOURCE_ID.name(), windSource.getId()); - } - result.put(FieldNames.WIND.name(), storeWind(wind)); - return result; - } - - private void storeRaceIdentifiers(RaceColumn raceColumn, DBObject dbObject) { - BasicDBObject raceIdentifiersPerFleet = new BasicDBObject(); - for (Fleet fleet : raceColumn.getFleets()) { - RaceIdentifier raceIdentifier = raceColumn.getRaceIdentifier(fleet); - if (raceIdentifier != null) { - DBObject raceIdentifierForFleet = new BasicDBObject(); - storeRaceIdentifier(raceIdentifierForFleet, raceIdentifier); - raceIdentifiersPerFleet.put(MongoUtils.escapeDollarAndDot(fleet.getName()), raceIdentifierForFleet); - } - } - dbObject.put(FieldNames.RACE_IDENTIFIERS.name(), raceIdentifiersPerFleet); - } - - private void storeRaceIdentifier(DBObject dbObject, RaceIdentifier raceIdentifier) { - if (raceIdentifier != null) { - dbObject.put(FieldNames.EVENT_NAME.name(), raceIdentifier.getRegattaName()); - dbObject.put(FieldNames.RACE_NAME.name(), raceIdentifier.getRaceName()); - } - } - - @Override - public void storeLeaderboard(Leaderboard leaderboard) { - DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); - try { - leaderboardCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), 1)); - } catch (NullPointerException npe) { - // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE - logger.log(Level.SEVERE, "storeLeaderboard", npe); - } - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); - BasicDBObject dbLeaderboard = new BasicDBObject(); - dbLeaderboard.put(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); - if (leaderboard.getDisplayName() != null) { - dbLeaderboard.put(FieldNames.LEADERBOARD_DISPLAY_NAME.name(), leaderboard.getDisplayName()); - } - BasicDBList dbSuppressedCompetitorIds = new BasicDBList(); - for (Competitor suppressedCompetitor : leaderboard.getSuppressedCompetitors()) { - dbSuppressedCompetitorIds.add(suppressedCompetitor.getId()); - } - dbLeaderboard.put(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name(), dbSuppressedCompetitorIds); - if (leaderboard instanceof FlexibleLeaderboard) { - storeFlexibleLeaderboard((FlexibleLeaderboard) leaderboard, dbLeaderboard); - } else if (leaderboard instanceof RegattaLeaderboard) { - storeRegattaLeaderboard((RegattaLeaderboard) leaderboard, dbLeaderboard); - } else { - // at least store the scoring scheme - dbLeaderboard.put(FieldNames.SCORING_SCHEME_TYPE.name(), leaderboard.getScoringScheme().getType().name()); - } - if (leaderboard.getDefaultCourseArea() != null) { - dbLeaderboard.put(FieldNames.COURSE_AREA_ID.name(), leaderboard.getDefaultCourseArea().getId().toString()); - } else { - dbLeaderboard.put(FieldNames.COURSE_AREA_ID.name(), null); - } - storeColumnFactors(leaderboard, dbLeaderboard); - storeLeaderboardCorrectionsAndDiscards(leaderboard, dbLeaderboard); - leaderboardCollection.update(query, dbLeaderboard, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - private void storeColumnFactors(Leaderboard leaderboard, BasicDBObject dbLeaderboard) { - DBObject raceColumnFactors = new BasicDBObject(); - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - Double explicitFactor = raceColumn.getExplicitFactor(); - if (explicitFactor != null) { - raceColumnFactors.put(MongoUtils.escapeDollarAndDot(raceColumn.getName()), explicitFactor); - } - } - dbLeaderboard.put(FieldNames.LEADERBOARD_COLUMN_FACTORS.name(), raceColumnFactors); - } - - private void storeRegattaLeaderboard(RegattaLeaderboard leaderboard, DBObject dbLeaderboard) { - dbLeaderboard.put(FieldNames.REGATTA_NAME.name(), leaderboard.getRegatta().getName()); - } - - private void storeFlexibleLeaderboard(FlexibleLeaderboard leaderboard, BasicDBObject dbLeaderboard) { - BasicDBList dbRaceColumns = new BasicDBList(); - dbLeaderboard.put(FieldNames.SCORING_SCHEME_TYPE.name(), leaderboard.getScoringScheme().getType().name()); - dbLeaderboard.put(FieldNames.LEADERBOARD_COLUMNS.name(), dbRaceColumns); - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - BasicDBObject dbRaceColumn = storeRaceColumn(raceColumn); - dbRaceColumns.add(dbRaceColumn); - } - } - - private void storeLeaderboardCorrectionsAndDiscards(Leaderboard leaderboard, BasicDBObject dbLeaderboard) { - if (leaderboard.hasCarriedPoints()) { - BasicDBList dbCarriedPoints = new BasicDBList(); - dbLeaderboard.put(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name(), dbCarriedPoints); - for (Entry competitorWithCarriedPoints : leaderboard - .getCompetitorsForWhichThereAreCarriedPoints().entrySet()) { - double carriedPoints = competitorWithCarriedPoints.getValue(); - Competitor competitor = competitorWithCarriedPoints.getKey(); - DBObject dbCarriedPointsForCompetitor = new BasicDBObject(); - dbCarriedPointsForCompetitor.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); - dbCarriedPointsForCompetitor.put(FieldNames.LEADERBOARD_CARRIED_POINTS.name(), carriedPoints); - dbCarriedPoints.add(dbCarriedPointsForCompetitor); - } - } - BasicDBObject dbScoreCorrections = new BasicDBObject(); - storeScoreCorrections(leaderboard, dbScoreCorrections); - dbLeaderboard.put(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name(), dbScoreCorrections); - final ResultDiscardingRule resultDiscardingRule = leaderboard.getResultDiscardingRule(); - storeResultDiscardingRule(dbLeaderboard, resultDiscardingRule, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); - BasicDBList competitorDisplayNames = new BasicDBList(); - for (Competitor competitor : leaderboard.getCompetitors()) { - String displayNameForCompetitor = leaderboard.getDisplayName(competitor); - if (displayNameForCompetitor != null) { - DBObject dbDisplayName = new BasicDBObject(); - dbDisplayName.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); - dbDisplayName.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), displayNameForCompetitor); - competitorDisplayNames.add(dbDisplayName); - } - } - dbLeaderboard.put(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name(), competitorDisplayNames); - } - - /** - * Stores the result discarding rule to dbObject's field identified by field if the result discarding - * rule is not null and is of type {@link ThresholdBasedResultDiscardingRule}. Otherwise, it is assumed that the - * result discarding rule is otherwise implicitly obtained, e.g., from a definition of a regatta with its series, stored elsewhere. - */ - private void storeResultDiscardingRule(DBObject dbObject, - final ResultDiscardingRule resultDiscardingRule, FieldNames field) { - if (resultDiscardingRule != null && resultDiscardingRule instanceof ThresholdBasedResultDiscardingRule) { - BasicDBList dbResultDiscardingThresholds = new BasicDBList(); - for (int threshold : ((ThresholdBasedResultDiscardingRule) resultDiscardingRule).getDiscardIndexResultsStartingWithHowManyRaces()) { - dbResultDiscardingThresholds.add(threshold); - } - dbObject.put(field.name(), dbResultDiscardingThresholds); - } - } - - private BasicDBObject storeRaceColumn(RaceColumn raceColumn) { - BasicDBObject dbRaceColumn = new BasicDBObject(); - dbRaceColumn.put(FieldNames.LEADERBOARD_COLUMN_NAME.name(), raceColumn.getName()); - dbRaceColumn.put(FieldNames.LEADERBOARD_IS_MEDAL_RACE_COLUMN.name(), raceColumn.isMedalRace()); - storeRaceIdentifiers(raceColumn, dbRaceColumn); - return dbRaceColumn; - } - - private void storeScoreCorrections(Leaderboard leaderboard, BasicDBObject dbScoreCorrections) { - TimePoint now = MillisecondsTimePoint.now(); - SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection(); - for (RaceColumn raceColumn : scoreCorrection.getRaceColumnsThatHaveCorrections()) { - BasicDBList dbCorrectionForRace = new BasicDBList(); - for (Competitor competitor : scoreCorrection.getCompetitorsThatHaveCorrectionsIn(raceColumn)) { - // TODO bug 655: make score corrections time dependent - if (scoreCorrection.isScoreCorrected(competitor, raceColumn, now)) { - BasicDBObject dbCorrectionForCompetitor = new BasicDBObject(); - dbCorrectionForCompetitor.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); - MaxPointsReason maxPointsReason = scoreCorrection.getMaxPointsReason(competitor, raceColumn, now); - if (maxPointsReason != MaxPointsReason.NONE) { - dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), - maxPointsReason.name()); - } - Double explicitScoreCorrection = scoreCorrection - .getExplicitScoreCorrection(competitor, raceColumn); - if (explicitScoreCorrection != null) { - dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_CORRECTED_SCORE.name(), - explicitScoreCorrection); - } - dbCorrectionForRace.add(dbCorrectionForCompetitor); - } - } - if (!dbCorrectionForRace.isEmpty()) { - // using the column name as the key for the score corrections requires re-writing the score corrections - // of a meta-leaderboard if the name of one of its leaderboards changes - dbScoreCorrections.put(MongoUtils.escapeDollarAndDot(raceColumn.getName()), dbCorrectionForRace); - } - } - final TimePoint timePointOfLastCorrectionsValidity = scoreCorrection.getTimePointOfLastCorrectionsValidity(); - if (timePointOfLastCorrectionsValidity != null) { - dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name(), timePointOfLastCorrectionsValidity.asMillis()); - } - if (scoreCorrection.getComment() != null) { - dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name(), scoreCorrection.getComment()); - } - } - - @Override - public void removeLeaderboard(String leaderboardName) { - DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboardName); - leaderboardCollection.remove(query); - } - - @Override - public void renameLeaderboard(String oldName, String newName) { - DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), oldName); - BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), newName)); - leaderboardCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void storeLeaderboardGroup(LeaderboardGroup leaderboardGroup) { - DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); - DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); - - try { - leaderboardGroupCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), 1)); - } catch (NullPointerException npe) { - // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE - logger.log(Level.SEVERE, "storeLeaderboardGroup", npe); - } - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), leaderboardGroup.getName()); - BasicDBObject dbLeaderboardGroup = new BasicDBObject(); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_UUID.name(), leaderboardGroup.getId()); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_NAME.name(), leaderboardGroup.getName()); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name(), leaderboardGroup.getDescription()); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name(), leaderboardGroup.getDisplayName()); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name(), leaderboardGroup.isDisplayGroupsInReverseOrder()); - final Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); - if (overallLeaderboard != null) { - BasicDBObject overallLeaderboardQuery = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), overallLeaderboard.getName()); - DBObject dbOverallLeaderboard = leaderboardCollection.findOne(overallLeaderboardQuery); - if (dbOverallLeaderboard == null) { - storeLeaderboard(overallLeaderboard); - dbOverallLeaderboard = leaderboardCollection.findOne(overallLeaderboardQuery); - } - ObjectId dbOverallLeaderboardId = (ObjectId) dbOverallLeaderboard.get("_id"); - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), dbOverallLeaderboardId); - } - BasicDBList dbLeaderboardIds = new BasicDBList(); - for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - BasicDBObject leaderboardQuery = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); - DBObject dbLeaderboard = leaderboardCollection.findOne(leaderboardQuery); - if (dbLeaderboard == null) { - storeLeaderboard(leaderboard); - dbLeaderboard = leaderboardCollection.findOne(leaderboardQuery); - } - ObjectId dbLeaderboardId = (ObjectId) dbLeaderboard.get("_id"); - dbLeaderboardIds.add(dbLeaderboardId); - } - dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), dbLeaderboardIds); - leaderboardGroupCollection.update(query, dbLeaderboardGroup, true, false, WriteConcern.SAFE); - } - - @Override - public void removeLeaderboardGroup(String groupName) { - DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), groupName); - leaderboardGroupCollection.remove(query); - } - - @Override - public void renameLeaderboardGroup(String oldName, String newName) { - DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), oldName); - BasicDBObject update = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), newName)); - leaderboardGroupCollection.update(query, update, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void storeServerConfiguration(SailingServerConfiguration serverConfiguration) { - DBCollection serverCollection = database.getCollection(CollectionNames.SERVER_CONFIGURATION.name()); - DBObject newServerConfig = new BasicDBObject(); - newServerConfig.put(FieldNames.SERVER_IS_STANDALONE.name(), serverConfiguration.isStandaloneServer()); - DBObject currentServerConfig = serverCollection.findOne(); - if(currentServerConfig != null) { - serverCollection.update(currentServerConfig, newServerConfig, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } else { - serverCollection.save(newServerConfig); - } - } - - @Override - public void storeSailingServer(RemoteSailingServerReference server) { - DBCollection serverCollection = database.getCollection(CollectionNames.SAILING_SERVERS.name()); - serverCollection.createIndex(new BasicDBObject(FieldNames.SERVER_NAME.name(), 1)); - DBObject query = new BasicDBObject(); - query.put(FieldNames.SERVER_NAME.name(), server.getName()); - DBObject serverDBObject = new BasicDBObject(); - serverDBObject.put(FieldNames.SERVER_NAME.name(), server.getName()); - serverDBObject.put(FieldNames.SERVER_URL.name(), server.getURL().toExternalForm()); - serverCollection.update(query, serverDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void removeSailingServer(String name) { - DBCollection serverCollection = database.getCollection(CollectionNames.SAILING_SERVERS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.SERVER_NAME.name(), name); - serverCollection.remove(query); - } - - /** - * StoreEvent() uses some deprecated methods of event to keep backward compatibility. - */ - @SuppressWarnings("deprecation") - @Override - public void storeEvent(Event event) { - DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name()); - eventCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); - DBObject query = new BasicDBObject(); - query.put(FieldNames.EVENT_ID.name(), event.getId()); - DBObject eventDBObject = new BasicDBObject(); - eventDBObject.put(FieldNames.EVENT_NAME.name(), event.getName()); - eventDBObject.put(FieldNames.EVENT_DESCRIPTION.name(), event.getDescription()); - eventDBObject.put(FieldNames.EVENT_ID.name(), event.getId()); - eventDBObject.put(FieldNames.EVENT_LOGO_IMAGE_URL.name(), event.getLogoImageURL() != null ? event.getLogoImageURL().toString() : null); - eventDBObject.put(FieldNames.EVENT_OFFICIAL_WEBSITE_URL.name(), event.getOfficialWebsiteURL() != null ? event.getOfficialWebsiteURL().toString() : null); - eventDBObject.put(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name(), event.getSailorsInfoWebsiteURL() != null ? event.getSailorsInfoWebsiteURL().toString() : null); - storeTimePoint(event.getStartDate(), eventDBObject, FieldNames.EVENT_START_DATE); - storeTimePoint(event.getEndDate(), eventDBObject, FieldNames.EVENT_END_DATE); - eventDBObject.put(FieldNames.EVENT_IS_PUBLIC.name(), event.isPublic()); - DBObject venueDBObject = getVenueAsDBObject(event.getVenue()); - eventDBObject.put(FieldNames.VENUE.name(), venueDBObject); - BasicDBList imageURLs = new BasicDBList(); - for (URL imageURL : event.getImageURLs()) { - imageURLs.add(imageURL.toString()); - } - eventDBObject.put(FieldNames.EVENT_IMAGE_URLS.name(), imageURLs); - BasicDBList videoURLs = new BasicDBList(); - for (URL videoURL : event.getVideoURLs()) { - videoURLs.add(videoURL.toString()); - } - eventDBObject.put(FieldNames.EVENT_VIDEO_URLS.name(), videoURLs); - BasicDBList sponsorImageURLs = new BasicDBList(); - for (URL sponsorImageURL : event.getSponsorImageURLs()) { - sponsorImageURLs.add(sponsorImageURL.toString()); - } - eventDBObject.put(FieldNames.EVENT_SPONSOR_IMAGE_URLS.name(), sponsorImageURLs); - BasicDBList images = new BasicDBList(); - for (ImageDescriptor image : event.getImages()) { - DBObject imageObject = createImageObject(image); - images.add(imageObject); - } - eventDBObject.put(FieldNames.EVENT_IMAGES.name(), images); - BasicDBList videos = new BasicDBList(); - for (VideoDescriptor video: event.getVideos()) { - DBObject videoObject = createVideoObject(video); - videos.add(videoObject); - } - eventDBObject.put(FieldNames.EVENT_VIDEOS.name(), videos); - eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - // now store the links to the leaderboard groups - DBCollection linksCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUP_LINKS_FOR_EVENTS.name()); - linksCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); - BasicDBList lgUUIDs = new BasicDBList(); - for (LeaderboardGroup lg : event.getLeaderboardGroups()) { - lgUUIDs.add(lg.getId()); - } - DBObject dbLinks = new BasicDBObject(); - dbLinks.put(FieldNames.EVENT_ID.name(), event.getId()); - dbLinks.put(FieldNames.LEADERBOARD_GROUP_UUID.name(), lgUUIDs); - linksCollection.update(query, dbLinks, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void renameEvent(Serializable id, String newName) { - DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.EVENT_ID.name(), id); - BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.EVENT_NAME.name(), newName)); - eventCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void removeEvent(Serializable id) { - DBCollection eventsCollection = database.getCollection(CollectionNames.EVENTS.name()); - BasicDBObject query = new BasicDBObject(FieldNames.EVENT_ID.name(), id); - eventsCollection.remove(query); - } - - private DBObject getVenueAsDBObject(Venue venue) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.VENUE_NAME.name(), venue.getName()); - BasicDBList courseAreaList = new BasicDBList(); - result.put(FieldNames.COURSE_AREAS.name(), courseAreaList); - for (CourseArea courseArea : venue.getCourseAreas()) { - DBObject dbCourseArea = new BasicDBObject(); - courseAreaList.add(dbCourseArea); - dbCourseArea.put(FieldNames.COURSE_AREA_NAME.name(), courseArea.getName()); - dbCourseArea.put(FieldNames.COURSE_AREA_ID.name(), courseArea.getId()); - } - return result; - } - - @Override - public void storeRegatta(Regatta regatta) { - DBCollection regattasCollection = database.getCollection(CollectionNames.REGATTAS.name()); - regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), 1)); - regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_ID.name(), 1)); - DBObject dbRegatta = new BasicDBObject(); - DBObject query = new BasicDBObject(FieldNames.REGATTA_NAME.name(), regatta.getName()); - dbRegatta.put(FieldNames.REGATTA_NAME.name(), regatta.getName()); - dbRegatta.put(FieldNames.REGATTA_ID.name(), regatta.getId()); - storeTimePoint(regatta.getStartDate(), dbRegatta, FieldNames.REGATTA_START_DATE); - storeTimePoint(regatta.getEndDate(), dbRegatta, FieldNames.REGATTA_END_DATE); - dbRegatta.put(FieldNames.SCORING_SCHEME_TYPE.name(), regatta.getScoringScheme().getType().name()); - if (regatta.getBoatClass() != null) { - dbRegatta.put(FieldNames.BOAT_CLASS_NAME.name(), regatta.getBoatClass().getName()); - dbRegatta.put(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name(), regatta.getBoatClass().typicallyStartsUpwind()); - } - dbRegatta.put(FieldNames.REGATTA_SERIES.name(), storeSeries(regatta.getSeries())); - - if (regatta.getDefaultCourseArea() != null) { - dbRegatta.put(FieldNames.COURSE_AREA_ID.name(), regatta.getDefaultCourseArea().getId().toString()); - } else { - dbRegatta.put(FieldNames.COURSE_AREA_ID.name(), null); - } - if (regatta.getRegattaConfiguration() != null) { - JsonSerializer serializer = RegattaConfigurationJsonSerializer.create(); - JSONObject json = serializer.serialize(regatta.getRegattaConfiguration()); - DBObject configurationObject = (DBObject) JSON.parse(json.toString()); - dbRegatta.put(FieldNames.REGATTA_REGATTA_CONFIGURATION.name(), configurationObject); - } - dbRegatta.put(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name(), regatta.useStartTimeInference()); - dbRegatta.put(FieldNames.REGATTA_RANKING_METRIC.name(), storeRankingMetric(regatta)); - regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - private DBObject storeRankingMetric(Regatta regatta) { - DBObject rankingMetricJson = new BasicDBObject(); - final String rankingMetricTypeName = regatta.getRankingMetricType().name(); - rankingMetricJson.put(FieldNames.REGATTA_RANKING_METRIC_TYPE.name(), rankingMetricTypeName); - return rankingMetricJson; - } - - @Override - public void removeRegatta(Regatta regatta) { - DBCollection regattasCollection = database.getCollection(CollectionNames.REGATTAS.name()); - DBObject query = new BasicDBObject(FieldNames.REGATTA_NAME.name(), regatta.getName()); - regattasCollection.remove(query); - } - - private BasicDBList storeSeries(Iterable series) { - BasicDBList dbSeries = new BasicDBList(); - for (Series s : series) { - dbSeries.add(storeSeries(s)); - } - return dbSeries; - } - - private DBObject storeSeries(Series s) { - DBObject dbSeries = new BasicDBObject(); - dbSeries.put(FieldNames.SERIES_NAME.name(), s.getName()); - dbSeries.put(FieldNames.SERIES_IS_MEDAL.name(), s.isMedal()); - dbSeries.put(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name(), s.hasSplitFleetContiguousScoring()); - dbSeries.put(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name(), s.isStartsWithZeroScore()); - dbSeries.put(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name(), s.isFirstColumnIsNonDiscardableCarryForward()); - BasicDBList dbFleets = new BasicDBList(); - for (Fleet fleet : s.getFleets()) { - dbFleets.add(storeFleet(fleet)); - } - dbSeries.put(FieldNames.SERIES_FLEETS.name(), dbFleets); - BasicDBList dbRaceColumns = new BasicDBList(); - for (RaceColumn raceColumn : s.getRaceColumns()) { - dbRaceColumns.add(storeRaceColumn(raceColumn)); - } - dbSeries.put(FieldNames.SERIES_RACE_COLUMNS.name(), dbRaceColumns); - if (s.getResultDiscardingRule() != null) { - storeResultDiscardingRule(dbSeries, s.getResultDiscardingRule(), FieldNames.SERIES_DISCARDING_THRESHOLDS); - } - return dbSeries; - } - - private DBObject storeFleet(Fleet fleet) { - DBObject dbFleet = new BasicDBObject(FieldNames.FLEET_NAME.name(), fleet.getName()); - if (fleet instanceof FleetImpl) { - dbFleet.put(FieldNames.FLEET_ORDERING.name(), ((FleetImpl) fleet).getOrdering()); - if(fleet.getColor() != null) { - com.sap.sse.common.Util.Triple colorAsRGB = fleet.getColor().getAsRGB(); - // we save the color as a integer value representing the RGB values - int colorAsInt = (256 * 256 * colorAsRGB.getC()) + colorAsRGB.getB() * 256 + colorAsRGB.getA(); - dbFleet.put(FieldNames.FLEET_COLOR.name(), colorAsInt); - } else { - dbFleet.put(FieldNames.FLEET_COLOR.name(), null); - } - } - return dbFleet; - } - - @Override - public void storeRegattaForRaceID(String raceIDAsString, Regatta regatta) { - DBCollection regattaForRaceIDCollection = database.getCollection(CollectionNames.REGATTA_FOR_RACE_ID.name()); - DBObject query = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); - DBObject entry = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); - entry.put(FieldNames.REGATTA_NAME.name(), regatta.getName()); - regattaForRaceIDCollection.update(query, entry, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - @Override - public void removeRegattaForRaceID(String raceIDAsString, Regatta regatta) { - DBCollection regattaForRaceIDCollection = database.getCollection(CollectionNames.REGATTA_FOR_RACE_ID.name()); - DBObject query = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); - regattaForRaceIDCollection.remove(query); - } - - public DBCollection getRaceLogCollection() { - DBCollection result = database.getCollection(CollectionNames.RACE_LOGS.name()); - result.createIndex(new BasicDBObject(FieldNames.RACE_LOG_IDENTIFIER.name(), null)); - return result; - } - - private void storeRaceLogEventAuthor(DBObject dbObject, AbstractLogEventAuthor author) { - if (author != null) { - dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_NAME.name(), author.getName()); - dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_PRIORITY.name(), author.getPriority()); - } - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFlagEvent flagEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFlagEvent(flagEvent)); - return result; - } - - private void storeRaceLogIdentifier(RaceLogIdentifier raceLogIdentifier, DBObject result) { - result.put(FieldNames.RACE_LOG_IDENTIFIER.name(), TripleSerializer.serialize(raceLogIdentifier.getIdentifier())); - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartTimeEvent startTimeEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartTimeEvent(startTimeEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogPassChangeEvent passChangeEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogPassChangeEvent(passChangeEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRaceStatusEvent raceStatusEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRaceStatusEvent(raceStatusEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCourseAreaChangedEvent courseAreaChangedEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCourseAreaChangedEvent(courseAreaChangedEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCourseDesignChangedEvent courseDesignChangedEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCourseDesignChangedEvent(courseDesignChangedEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFinishPositioningListChangedEvent finishPositioningListChangedEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFinishPositioningListChangedEvent(finishPositioningListChangedEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFinishPositioningConfirmedEvent(finishPositioningConfirmedEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogPathfinderEvent pathfinderEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogPathfinderEvent(pathfinderEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogGateLineOpeningTimeEvent gateLineOpeningTimeEvent) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogGateLineOpeningTimeEvent(gateLineOpeningTimeEvent)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartProcedureChangedEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartProcedureChangedEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogProtestStartTimeEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogProtestStartTimeEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogWindFixEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogWindFix(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDeviceCompetitorMappingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDeviceCompetitorMappingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDeviceMarkMappingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDeviceMarkMappingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDenoteForTrackingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDenoteForTrackingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartTrackingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartTrackingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRevokeEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRevokeEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDefineMarkEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDefineMarkEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCloseOpenEndedDeviceMappingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCloseOpenEndedDeviceMappingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogEndOfTrackingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogEndOfTrackingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartOfTrackingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartOfTrackingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogAdditionalScoringInformationEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeAdditionalScoringInformation(event)); - return result; - } - - private Object storeAdditionalScoringInformation(RaceLogAdditionalScoringInformationEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogAdditionalScoringInformationEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name(), event.getType().name()); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFixedMarkPassingEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFixedMarkPassingEvent(event)); - return result; - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogSuppressedMarkPassingsEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogSuppressedMarkPassingsEvent(event)); - return result; - } - - private Object storeRaceLogWindFix(RaceLogWindFixEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogWindFixEvent.class.getSimpleName()); - result.put(FieldNames.WIND.name(), storeWind(event.getWindFix())); - result.put(FieldNames.IS_MAGNETIC.name(), event.isMagnetic()); - return result; - } - - private Object storeRaceLogProtestStartTimeEvent(RaceLogProtestStartTimeEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogProtestStartTimeEvent.class.getSimpleName()); - storeTimePoint(event.getProtestStartTime(), result, FieldNames.RACE_LOG_PROTEST_START_TIME); - return result; - } - - private Object storeRaceLogEndOfTrackingEvent(RaceLogEndOfTrackingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogEndOfTrackingEvent.class.getSimpleName()); - return result; - } - - private Object storeRaceLogStartOfTrackingEvent(RaceLogStartOfTrackingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartOfTrackingEvent.class.getSimpleName()); - return result; - } - - private Object storeRaceLogStartProcedureChangedEvent(RaceLogStartProcedureChangedEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartProcedureChangedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name(), event.getStartProcedureType().name()); - return result; - } - - private Object storeRaceLogPathfinderEvent(RaceLogPathfinderEvent pathfinderEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(pathfinderEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogPathfinderEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_PATHFINDER_ID.name(), pathfinderEvent.getPathfinderId()); - return result; - } - - private void storeDeviceMappingEvent(DeviceMappingEvent event, DBObject result, FieldNames fromField, FieldNames toField) { - try { - result.put(FieldNames.DEVICE_ID.name(), storeDeviceId(deviceIdentifierServiceFinder, event.getDevice())); - } catch (TransformationException | NoCorrespondingServiceRegisteredException e) { - logger.log(Level.WARNING, "Could not store device identifier for mappng event", e); - } - if (event.getFrom() != null) { - storeTimePoint(event.getFrom(), result, fromField); - } - if (event.getTo() != null) { - storeTimePoint(event.getTo(), result, toField); - } - } - - private Object storeRaceLogDeviceCompetitorMappingEvent(RaceLogDeviceCompetitorMappingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceCompetitorMappingEvent.class.getSimpleName()); - storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO); - result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId()); - return result; - } - - private Object storeRaceLogDeviceMarkMappingEvent(RaceLogDeviceMarkMappingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceMarkMappingEvent.class.getSimpleName()); - storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO); - result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo())); - return result; - } - - private Object storeRaceLogDenoteForTrackingEvent(RaceLogDenoteForTrackingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDenoteForTrackingEvent.class.getSimpleName()); - result.put(FieldNames.RACE_NAME.name(), event.getRaceName()); - result.put(FieldNames.BOAT_CLASS_NAME.name(), event.getBoatClass().getName()); - result.put(FieldNames.RACE_ID.name(), event.getRaceId()); - return result; - } - - private Object storeRaceLogStartTrackingEvent(RaceLogStartTrackingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartTrackingEvent.class.getSimpleName()); - return result; - } - - private Object storeRaceLogRevokeEvent(RaceLogRevokeEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRevokeEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name(), event.getRevokedEventId()); - result.put(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name(), event.getRevokedEventType()); - result.put(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name(), event.getRevokedEventShortInfo()); - result.put(FieldNames.RACE_LOG_REVOKED_REASON.name(), event.getReason()); - return result; - } - - private Object storeRaceLogRegisterCompetitorEvent(RaceLogRegisterCompetitorEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterCompetitorEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - return result; - } - - private Object storeRaceLogDefineMarkEvent(RaceLogDefineMarkEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDefineMarkEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_MARK.name(), storeMark(event.getMark())); - return result; - } - - private Object storeRaceLogCloseOpenEndedDeviceMappingEvent(RaceLogCloseOpenEndedDeviceMappingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name(), event.getDeviceMappingEventId()); - storeTimePoint(event.getClosingTimePoint(), result, FieldNames.RACE_LOG_CLOSING_TIMEPOINT); - return result; - } - - private Object storeRaceLogFixedMarkPassingEvent(RaceLogFixedMarkPassingEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFixedMarkPassingEvent.class.getSimpleName()); - result.put(FieldNames.INDEX_OF_PASSED_WAYPOINT.name(), event.getZeroBasedIndexOfPassedWaypoint()); - result.put(FieldNames.TIMEPOINT_OF_FIXED_MARKPASSING.name(), event.getTimePointOfFixedPassing().asMillis()); - return result; - } - - private Object storeRaceLogSuppressedMarkPassingsEvent(RaceLogSuppressedMarkPassingsEvent event) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(event, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogSuppressedMarkPassingsEvent.class.getSimpleName()); - result.put(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name(), event.getZeroBasedIndexOfFirstSuppressedWaypoint()); - return result; - } - - public DBObject storeRaceLogFlagEvent(RaceLogFlagEvent flagEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(flagEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFlagEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_EVENT_FLAG_UPPER.name(), flagEvent.getUpperFlag().name()); - result.put(FieldNames.RACE_LOG_EVENT_FLAG_LOWER.name(), flagEvent.getLowerFlag().name()); - result.put(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name(), String.valueOf(flagEvent.isDisplayed())); - return result; - } - - private DBObject storeRaceLogStartTimeEvent(RaceLogStartTimeEvent startTimeEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(startTimeEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartTimeEvent.class.getSimpleName()); - storeTimePoint(startTimeEvent.getStartTime(), result, FieldNames.RACE_LOG_EVENT_START_TIME); - result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), startTimeEvent.getNextStatus().name()); - return result; - } - - private void storeRaceLogEventProperties(RaceLogEvent event, DBObject result) { - // for compatibility reasons we reuse the field name of Timed - storeTimePoint(event.getLogicalTimePoint(), result, FieldNames.TIME_AS_MILLIS); - storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT); - result.put(FieldNames.RACE_LOG_EVENT_ID.name(), event.getId()); - result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), event.getPassId()); - result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedBoats())); - storeRaceLogEventAuthor(result, event.getAuthor()); - } - - - private BasicDBList storeInvolvedBoatsForRaceLogEvent(List competitors) { - BasicDBList dbInvolvedCompetitorIds = new BasicDBList(); - for (Competitor competitor : competitors) { - dbInvolvedCompetitorIds.add(competitor.getId()); - } - return dbInvolvedCompetitorIds; - } - - private DBObject storeRaceLogPassChangeEvent(RaceLogPassChangeEvent passChangeEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(passChangeEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogPassChangeEvent.class.getSimpleName()); - return result; - } - - private DBObject storeRaceLogDependentStartTimeEvent(RaceLogDependentStartTimeEvent dependentStartTimeEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(dependentStartTimeEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDependentStartTimeEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_REGATTALIKE.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getRegattaLikeParentName()); - result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_RACECOLUMN.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getRaceColumnName()); - result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_FLEET.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getFleetName()); - storeDuration(dependentStartTimeEvent.getStartTimeDifference(), result, FieldNames.RACE_LOG_START_TIME_DIFFERENCE_IN_MS); - result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), dependentStartTimeEvent.getNextStatus().name()); - return result; - } - - private void storeDuration(Duration duration, DBObject result, FieldNames fieldName) { - if (duration != null) { - result.put(fieldName.name(), duration.asMillis()); - } - } - - private DBObject storeRaceLogRaceStatusEvent(RaceLogRaceStatusEvent raceStatusEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(raceStatusEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRaceStatusEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), raceStatusEvent.getNextStatus().name()); - return result; - } - - private DBObject storeRaceLogCourseAreaChangedEvent(RaceLogCourseAreaChangedEvent courseAreaChangedEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(courseAreaChangedEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCourseAreaChangedEvent.class.getSimpleName()); - result.put(FieldNames.COURSE_AREA_ID.name(), courseAreaChangedEvent.getCourseAreaId()); - return result; - } - - private DBObject storeRaceLogCourseDesignChangedEvent(RaceLogCourseDesignChangedEvent courseDesignChangedEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(courseDesignChangedEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCourseDesignChangedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name(), courseDesignChangedEvent.getCourseDesign().getName()); - result.put(FieldNames.RACE_LOG_COURSE_DESIGN.name(), storeCourseBase(courseDesignChangedEvent.getCourseDesign())); - return result; - } - - private Object storeRaceLogFinishPositioningListChangedEvent(RaceLogFinishPositioningListChangedEvent finishPositioningListChangedEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(finishPositioningListChangedEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningListChangedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningListChangedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); - - return result; - } - - private Object storeRaceLogFinishPositioningConfirmedEvent(RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent) { - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(finishPositioningConfirmedEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); - - return result; - } - - private Object storeRaceLogGateLineOpeningTimeEvent(RaceLogGateLineOpeningTimeEvent gateLineOpeningTimeEvent){ - DBObject result = new BasicDBObject(); - storeRaceLogEventProperties(gateLineOpeningTimeEvent, result); - result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogGateLineOpeningTimeEvent.class.getSimpleName()); - result.put(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGateLaunchStopTime()); - result.put(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGolfDownTime()); - return result; - } - - private BasicDBList storePositionedCompetitors(List> positionedCompetitors) { - BasicDBList dbList = new BasicDBList(); - if (positionedCompetitors != null) { - for (com.sap.sse.common.Util.Triple competitorPair : positionedCompetitors) { - dbList.add(storePositionedCompetitor(competitorPair)); - } - } - return dbList; - } - - private DBObject storePositionedCompetitor(com.sap.sse.common.Util.Triple competitorTriple) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.COMPETITOR_ID.name(), competitorTriple.getA()); - result.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), competitorTriple.getB()); - result.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), competitorTriple.getC().name()); - - return result; - } - - private BasicDBList storeCourseBase(CourseBase courseData) { - BasicDBList dbList = new BasicDBList(); - - for (Waypoint waypoint : courseData.getWaypoints()) { - dbList.add(storeWaypoint(waypoint)); - } - return dbList; - } - - private DBObject storeWaypoint(Waypoint waypoint) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.WAYPOINT_PASSINGINSTRUCTIONS.name(), getPassingInstructions(waypoint.getPassingInstructions())); - result.put(FieldNames.CONTROLPOINT.name(), storeControlPoint(waypoint.getControlPoint())); - return result; - } - - private DBObject storeControlPoint(ControlPoint controlPoint) { - DBObject result = new BasicDBObject(); - if (controlPoint instanceof Mark) { - result.put(FieldNames.CONTROLPOINT_CLASS.name(), Mark.class.getSimpleName()); - result.put(FieldNames.CONTROLPOINT_VALUE.name(), storeMark((Mark) controlPoint)); - } else if (controlPoint instanceof ControlPointWithTwoMarks) { - result.put(FieldNames.CONTROLPOINT_CLASS.name(), ControlPointWithTwoMarks.class.getSimpleName()); - result.put(FieldNames.CONTROLPOINT_VALUE.name(), storeControlPointWithTwoMarks((ControlPointWithTwoMarks) controlPoint)); - } - return result; - } - - private DBObject storeControlPointWithTwoMarks(ControlPointWithTwoMarks cpwtm) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_ID.name(), cpwtm.getId()); - result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_NAME.name(), cpwtm.getName()); - result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name(), storeMark(cpwtm.getLeft())); - result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name(), storeMark(cpwtm.getRight())); - return result; - } - - private DBObject storeMark(Mark mark) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.MARK_ID.name(), mark.getId()); - result.put(FieldNames.MARK_COLOR.name(), mark.getColor()); - result.put(FieldNames.MARK_NAME.name(), mark.getName()); - result.put(FieldNames.MARK_PATTERN.name(), mark.getPattern()); - result.put(FieldNames.MARK_SHAPE.name(), mark.getShape()); - result.put(FieldNames.MARK_TYPE.name(), mark.getType() == null ? null : mark.getType().name()); - return result; - } - - private String getPassingInstructions(PassingInstruction passingInstructions) { - final String passing; - if (passingInstructions != null) { - passing = passingInstructions.name(); - } else { - passing = null; - } - return passing; - } - @Override - public void storeCompetitor(Competitor competitor) { - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); - JSONObject json = competitorSerializer.serialize(competitor); - DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); - DBObject entry = (DBObject) JSON.parse(json.toString()); - collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); - } - - @Override - public void removeAllCompetitors() { - logger.info("Removing all persistent competitor info"); - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); - collection.drop(); - } - - @Override - public void removeCompetitor(Competitor competitor) { - logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId()); - DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); - DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); - collection.remove(query, WriteConcern.SAFE); - } - - @Override - public void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) { - DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name()); - - DBObject query = new BasicDBObject(); - query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); - - DBObject entryObject = new BasicDBObject(); - entryObject.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); - entryObject.put(FieldNames.CONFIGURATION_MATCHER.name(), createDeviceConfigurationMatcherObject(matcher)); - entryObject.put(FieldNames.CONFIGURATION_CONFIG.name(), createDeviceConfigurationObject(configuration)); - - configurationsCollections.update(query, entryObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); - } - - private DBObject createDeviceConfigurationMatcherObject(DeviceConfigurationMatcher matcher) { - DBObject matcherObject = new BasicDBObject(); - matcherObject.put(FieldNames.CONFIGURATION_MATCHER_TYPE.name(), matcher.getMatcherType().name()); - if (matcher instanceof DeviceConfigurationMatcherSingle) { - BasicDBList client = new BasicDBList(); - client.add(((DeviceConfigurationMatcherSingle)matcher).getClientIdentifier()); - matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), client); - } else if (matcher instanceof DeviceConfigurationMatcherMulti) { - BasicDBList clients = new BasicDBList(); - Util.addAll(((DeviceConfigurationMatcherMulti)matcher).getClientIdentifiers(), clients); - matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), clients); - } - return matcherObject; - } - - private DBObject createDeviceConfigurationObject(DeviceConfiguration configuration) { - JsonSerializer serializer = DeviceConfigurationJsonSerializer.create(); - JSONObject json = serializer.serialize(configuration); - DBObject entry = (DBObject) JSON.parse(json.toString()); - return entry; - } - - @Override - public void removeDeviceConfiguration(DeviceConfigurationMatcher matcher) { - DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name()); - DBObject query = new BasicDBObject(); - query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); - configurationsCollections.remove(query); - } - - public static DBObject storeDeviceId( - TypeBasedServiceFinder deviceIdentifierServiceFinder, DeviceIdentifier device) - throws TransformationException, NoCorrespondingServiceRegisteredException { - String type = device.getIdentifierType(); - DeviceIdentifierMongoHandler handler = deviceIdentifierServiceFinder.findService(type); - com.sap.sse.common.Util.Pair pair = handler.serialize(device); - type = pair.getA(); - Object deviceTypeSpecificId = pair.getB(); - return new BasicDBObjectBuilder() - .add(FieldNames.DEVICE_TYPE.name(), type) - .add(FieldNames.DEVICE_TYPE_SPECIFIC_ID.name(), deviceTypeSpecificId) - .add(FieldNames.DEVICE_STRING_REPRESENTATION.name(), device.getStringRepresentation()).get(); - } - - void storeRaceLogEventEvent(DBObject eventEntry) { - getRaceLogCollection().insert(eventEntry); - } - - @Override - public void removeRaceLog(RaceLogIdentifier identifier) { - DBObject query = new BasicDBObject(); - storeRaceLogIdentifier(identifier, query); - getRaceLogCollection().remove(query); - } - - @Override - public void removeRegattaLog(RegattaLikeIdentifier identifier) { - DBObject query = new BasicDBObject(); - addRegattaLikeIdentifier(identifier, query); - getRegattaLogCollection().remove(query); - } - - @Override - public void storeResultUrl(String resultProviderName, URL url) { - DBCollection resultUrlsCollection = database.getCollection(CollectionNames.RESULT_URLS.name()); - DBObject query = new BasicDBObject(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName); - DBObject entry = new BasicDBObject(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName); - entry.put(FieldNames.RESULT_URL.name(), url.toString()); - resultUrlsCollection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); - } - - @Override - public void removeResultUrl(String resultProviderName, URL url) { - DBCollection resultUrlsCollection = database.getCollection(CollectionNames.RESULT_URLS.name()); - DBObject query = new BasicDBObjectBuilder().add(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName) - .add(FieldNames.RESULT_URL.name(), url.toString()).get(); - resultUrlsCollection.remove(query); - } - - public DBCollection getRegattaLogCollection() { - DBCollection result = database.getCollection(CollectionNames.REGATTA_LOGS.name()); - DBObject index = new BasicDBObject(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), null); - index.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), null); - result.createIndex(index); - return result; - } - - private DBObject createBasicRegattaLogEventDBObject(RegattaLogEvent event) { - DBObject result = new BasicDBObject(); - storeTimed(event, result); - storeTimePoint(event.getCreatedAt(), result, FieldNames.REGATTA_LOG_EVENT_CREATED_AT); - result.put(FieldNames.REGATTA_LOG_EVENT_ID.name(), event.getId()); - result.put(FieldNames.REGATTA_LOG_EVENT_AUTHOR_NAME.name(), event.getAuthor().getName()); - result.put(FieldNames.REGATTA_LOG_EVENT_AUTHOR_PRIORITY.name(), event.getAuthor().getPriority()); - return result; - } - - private void addRegattaLikeIdentifier(RegattaLikeIdentifier regattaLikeId, DBObject toObject) { - toObject.put(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), regattaLikeId.getIdentifierType()); - toObject.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), regattaLikeId.getName()); - } - - private void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, DBObject innerObject) { - DBObject result = new BasicDBObject(FieldNames.REGATTA_LOG_EVENT.name(), innerObject); - addRegattaLikeIdentifier(regattaLikeId, result); - getRegattaLogCollection().insert(result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceCompetitorMappingEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName()); - storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO); - result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId()); - storeRegattaLogEvent(regattaLikeId, result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceMarkMappingEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceMarkMappingEvent.class.getSimpleName()); - storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO); - result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo())); - storeRegattaLogEvent(regattaLikeId, result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRevokeEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRevokeEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name(), event.getRevokedEventId()); - result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name(), event.getRevokedEventType()); - result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name(), event.getRevokedEventShortInfo()); - result.put(FieldNames.REGATTA_LOG_REVOKED_REASON.name(), event.getReason()); - storeRegattaLogEvent(regattaLikeId, result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - storeRegattaLogEvent(regattaLikeId, result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogCloseOpenEndedDeviceMappingEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name(), event.getDeviceMappingEventId()); - storeTimePoint(event.getClosingTimePoint(), result, FieldNames.REGATTA_LOG_CLOSING_TIMEPOINT); - storeRegattaLogEvent(regattaLikeId, result); - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - result.put(FieldNames.REGATTA_LOG_TIME_ON_TIME_FACTOR.name(), event.getTimeOnTimeFactor()); - } - - public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDependentStartTimeEvent event) { - BasicDBObject result = new BasicDBObject(); - storeRaceLogIdentifier(raceLogIdentifier, result); - result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDependentStartTimeEvent(event)); - return result; - } - - public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) { - DBObject result = createBasicRegattaLogEventDBObject(event); - result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); - result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); - result.put(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name(), event.getTimeOnDistanceAllowancePerNauticalMile().asSeconds()); - storeRegattaLogEvent(regattaLikeId, result); - } - - private DBObject createImageObject(ImageDescriptor image) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.IMAGE_URL.name(), image.getURL().toString()); - result.put(FieldNames.IMAGE_LOCALE.name(), image.getLocale() != null ? image.getLocale().toLanguageTag() : null); - result.put(FieldNames.IMAGE_TITLE.name(), image.getTitle()); - result.put(FieldNames.IMAGE_SUBTITLE.name(), image.getSubtitle()); - result.put(FieldNames.IMAGE_COPYRIGHT.name(), image.getCopyright()); - result.put(FieldNames.IMAGE_WIDTH_IN_PX.name(), image.getWidthInPx()); - result.put(FieldNames.IMAGE_HEIGHT_IN_PX.name(), image.getHeightInPx()); - storeTimePoint(image.getCreatedAtDate(), result, FieldNames.IMAGE_CREATEDATDATE); - BasicDBList tags = new BasicDBList(); - for (String tag : image.getTags()) { - tags.add(tag); - } - result.put(FieldNames.IMAGE_TAGS.name(), tags); - return result; - } - - private DBObject createVideoObject(VideoDescriptor video) { - DBObject result = new BasicDBObject(); - result.put(FieldNames.VIDEO_URL.name(), video.getURL().toString()); - result.put(FieldNames.VIDEO_LOCALE.name(), video.getLocale() != null ? video.getLocale().toLanguageTag() : null); - result.put(FieldNames.VIDEO_THUMBNAIL_URL.name(), video.getThumbnailURL() != null ? video.getThumbnailURL().toString() : null); - result.put(FieldNames.VIDEO_TITLE.name(), video.getTitle()); - result.put(FieldNames.VIDEO_SUBTITLE.name(), video.getSubtitle()); - result.put(FieldNames.VIDEO_MIMETYPE.name(), video.getMimeType() != null ? video.getMimeType().name() : null); - result.put(FieldNames.VIDEO_COPYRIGHT.name(), video.getCopyright()); - result.put(FieldNames.VIDEO_LENGTH_IN_SECONDS.name(), video.getLengthInSeconds()); - storeTimePoint(video.getCreatedAtDate(), result, FieldNames.VIDEO_CREATEDATDATE); - BasicDBList tags = new BasicDBList(); - for (String tag : video.getTags()) { - tags.add(tag); - } - result.put(FieldNames.VIDEO_TAGS.name(), tags); - return result; - } -} +package com.sap.sailing.domain.persistence.impl; + +import java.io.Serializable; +import java.net.URL; +import java.util.List; +import java.util.Map.Entry; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.bson.types.ObjectId; +import org.json.simple.JSONObject; + +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.BasicDBObjectBuilder; +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.WriteConcern; +import com.mongodb.util.JSON; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; +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.RaceLogStartProcedureChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +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.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; +import com.sap.sailing.domain.abstractlog.shared.events.DeviceMappingEvent; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.ControlPoint; +import com.sap.sailing.domain.base.ControlPointWithTwoMarks; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.RemoteSailingServerReference; +import com.sap.sailing.domain.base.SailingServerConfiguration; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.Venue; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; +import com.sap.sailing.domain.base.configuration.RegattaConfiguration; +import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherMulti; +import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMatcherSingle; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.common.Bearing; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.PassingInstruction; +import com.sap.sailing.domain.common.Positioned; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.Speed; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.racelog.tracking.TransformationException; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.racelog.tracking.DeviceIdentifierMongoHandler; +import com.sap.sailing.domain.persistence.racelog.tracking.impl.PlaceHolderDeviceIdentifierMongoHandler; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegatta; +import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.server.gateway.serialization.JsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.DeviceConfigurationJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; +import com.sap.sse.common.Duration; +import com.sap.sse.common.NoCorrespondingServiceRegisteredException; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.TimeRange; +import com.sap.sse.common.Timed; +import com.sap.sse.common.TypeBasedServiceFinder; +import com.sap.sse.common.TypeBasedServiceFinderFactory; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +public class MongoObjectFactoryImpl implements MongoObjectFactory { + private static Logger logger = Logger.getLogger(MongoObjectFactoryImpl.class.getName()); + private final DB database; + private final CompetitorJsonSerializer competitorSerializer = CompetitorJsonSerializer.create(); + private final TypeBasedServiceFinder deviceIdentifierServiceFinder; + + /** + * Uses null for the device type service finder and hence will be unable to store device identifiers. + * Use this constructor only for testing purposes or in cases where there will happen absolutely no access to + * {@link DeviceIdentifier} objects. + */ + public MongoObjectFactoryImpl(DB database) { + this(database, /* deviceTypeServiceFinder */ null); + } + + public MongoObjectFactoryImpl(DB database, TypeBasedServiceFinderFactory serviceFinderFactory) { + this.database = database; + if (serviceFinderFactory != null) { + this.deviceIdentifierServiceFinder = serviceFinderFactory.createServiceFinder(DeviceIdentifierMongoHandler.class); + this.deviceIdentifierServiceFinder.setFallbackService(new PlaceHolderDeviceIdentifierMongoHandler()); + } else { + this.deviceIdentifierServiceFinder = null; + } + } + + @Override + public DB getDatabase() { + return database; + } + + public DBObject storeWind(Wind wind) { + DBObject result = new BasicDBObject(); + storePositioned(wind, result); + storeTimed(wind, result); + storeSpeedWithBearing(wind, result); + return result; + } + + public static void storeTimePoint(TimePoint timePoint, DBObject result, String fieldName) { + if (timePoint != null) { + result.put(fieldName, timePoint.asMillis()); + } + } + + public static void storeTimePoint(TimePoint timePoint, DBObject result, FieldNames field) { + storeTimePoint(timePoint, result, field.name()); + } + + public static void storeTimeRange(TimeRange timeRange, DBObject result, FieldNames field) { + if (timeRange != null) { + DBObject timeRangeObj = new BasicDBObject(); + storeTimePoint(timeRange.from(), timeRangeObj, FieldNames.FROM_MILLIS); + storeTimePoint(timeRange.to(), timeRangeObj, FieldNames.TO_MILLIS); + result.put(field.name(), timeRangeObj); + } + } + + public void storeTimed(Timed timed, DBObject result) { + if (timed.getTimePoint() != null) { + storeTimePoint(timed.getTimePoint(), result, FieldNames.TIME_AS_MILLIS); + } + } + + public void storeSpeedWithBearing(SpeedWithBearing speedWithBearing, DBObject result) { + storeSpeed(speedWithBearing, result); + storeBearing(speedWithBearing.getBearing(), result); + + } + + public void storeBearing(Bearing bearing, DBObject result) { + result.put(FieldNames.DEGREE_BEARING.name(), bearing.getDegrees()); + } + + public void storeSpeed(Speed speed, DBObject result) { + result.put(FieldNames.KNOT_SPEED.name(), speed.getKnots()); + } + + public void storePositioned(Positioned positioned, DBObject result) { + if (positioned.getPosition() != null) { + result.put(FieldNames.LAT_DEG.name(), positioned.getPosition().getLatDeg()); + result.put(FieldNames.LNG_DEG.name(), positioned.getPosition().getLngDeg()); + } + } + + @Override + public void addWindTrackDumper(TrackedRegatta trackedRegatta, TrackedRace trackedRace, WindSource windSource) { + WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource); + windTrack.addListener(new MongoWindListener(trackedRace, trackedRegatta.getRegatta().getName(), windSource, this, database)); + } + + public DBCollection getWindTrackCollection() { + DBCollection result = database.getCollection(CollectionNames.WIND_TRACKS.name()); + result.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), null)); + return result; + } + + public DBCollection getGPSFixCollection() { + DBCollection gpsFixCollection = database.getCollection(CollectionNames.GPS_FIXES.name()); + DBObject index = new BasicDBObject(); + index.put(FieldNames.DEVICE_ID.name(), null); + index.put(FieldNames.TIME_AS_MILLIS.name(), null); + gpsFixCollection.createIndex(index); + return gpsFixCollection; + } + + public DBCollection getGPSFixMetadataCollection() { + DBCollection collection = database.getCollection(CollectionNames.GPS_FIXES_METADATA.name()); + DBObject index = new BasicDBObject(); + index.put(FieldNames.DEVICE_ID.name(), null); + collection.createIndex(index); + return collection; + } + + /** + * @param regattaName + * the regatta name is stored only for human readability purposes because a time stamp may be a bit unhandy for + * identifying where the wind fix was collected + */ + public DBObject storeWindTrackEntry(RaceDefinition race, String regattaName, WindSource windSource, Wind wind) { + BasicDBObject result = new BasicDBObject(); + result.put(FieldNames.RACE_ID.name(), race.getId()); + result.put(FieldNames.REGATTA_NAME.name(), regattaName); + result.put(FieldNames.WIND_SOURCE_NAME.name(), windSource.name()); + if (windSource.getId() != null) { + result.put(FieldNames.WIND_SOURCE_ID.name(), windSource.getId()); + } + result.put(FieldNames.WIND.name(), storeWind(wind)); + return result; + } + + private void storeRaceIdentifiers(RaceColumn raceColumn, DBObject dbObject) { + BasicDBObject raceIdentifiersPerFleet = new BasicDBObject(); + for (Fleet fleet : raceColumn.getFleets()) { + RaceIdentifier raceIdentifier = raceColumn.getRaceIdentifier(fleet); + if (raceIdentifier != null) { + DBObject raceIdentifierForFleet = new BasicDBObject(); + storeRaceIdentifier(raceIdentifierForFleet, raceIdentifier); + raceIdentifiersPerFleet.put(MongoUtils.escapeDollarAndDot(fleet.getName()), raceIdentifierForFleet); + } + } + dbObject.put(FieldNames.RACE_IDENTIFIERS.name(), raceIdentifiersPerFleet); + } + + private void storeRaceIdentifier(DBObject dbObject, RaceIdentifier raceIdentifier) { + if (raceIdentifier != null) { + dbObject.put(FieldNames.EVENT_NAME.name(), raceIdentifier.getRegattaName()); + dbObject.put(FieldNames.RACE_NAME.name(), raceIdentifier.getRaceName()); + } + } + + @Override + public void storeLeaderboard(Leaderboard leaderboard) { + DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); + try { + leaderboardCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), 1)); + } catch (NullPointerException npe) { + // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE + logger.log(Level.SEVERE, "storeLeaderboard", npe); + } + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); + BasicDBObject dbLeaderboard = new BasicDBObject(); + dbLeaderboard.put(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); + if (leaderboard.getDisplayName() != null) { + dbLeaderboard.put(FieldNames.LEADERBOARD_DISPLAY_NAME.name(), leaderboard.getDisplayName()); + } + BasicDBList dbSuppressedCompetitorIds = new BasicDBList(); + for (Competitor suppressedCompetitor : leaderboard.getSuppressedCompetitors()) { + dbSuppressedCompetitorIds.add(suppressedCompetitor.getId()); + } + dbLeaderboard.put(FieldNames.LEADERBOARD_SUPPRESSED_COMPETITOR_IDS.name(), dbSuppressedCompetitorIds); + if (leaderboard instanceof FlexibleLeaderboard) { + storeFlexibleLeaderboard((FlexibleLeaderboard) leaderboard, dbLeaderboard); + } else if (leaderboard instanceof RegattaLeaderboard) { + storeRegattaLeaderboard((RegattaLeaderboard) leaderboard, dbLeaderboard); + } else { + // at least store the scoring scheme + dbLeaderboard.put(FieldNames.SCORING_SCHEME_TYPE.name(), leaderboard.getScoringScheme().getType().name()); + } + if (leaderboard.getDefaultCourseArea() != null) { + dbLeaderboard.put(FieldNames.COURSE_AREA_ID.name(), leaderboard.getDefaultCourseArea().getId().toString()); + } else { + dbLeaderboard.put(FieldNames.COURSE_AREA_ID.name(), null); + } + storeColumnFactors(leaderboard, dbLeaderboard); + storeLeaderboardCorrectionsAndDiscards(leaderboard, dbLeaderboard); + leaderboardCollection.update(query, dbLeaderboard, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + private void storeColumnFactors(Leaderboard leaderboard, BasicDBObject dbLeaderboard) { + DBObject raceColumnFactors = new BasicDBObject(); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + Double explicitFactor = raceColumn.getExplicitFactor(); + if (explicitFactor != null) { + raceColumnFactors.put(MongoUtils.escapeDollarAndDot(raceColumn.getName()), explicitFactor); + } + } + dbLeaderboard.put(FieldNames.LEADERBOARD_COLUMN_FACTORS.name(), raceColumnFactors); + } + + private void storeRegattaLeaderboard(RegattaLeaderboard leaderboard, DBObject dbLeaderboard) { + dbLeaderboard.put(FieldNames.REGATTA_NAME.name(), leaderboard.getRegatta().getName()); + } + + private void storeFlexibleLeaderboard(FlexibleLeaderboard leaderboard, BasicDBObject dbLeaderboard) { + BasicDBList dbRaceColumns = new BasicDBList(); + dbLeaderboard.put(FieldNames.SCORING_SCHEME_TYPE.name(), leaderboard.getScoringScheme().getType().name()); + dbLeaderboard.put(FieldNames.LEADERBOARD_COLUMNS.name(), dbRaceColumns); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + BasicDBObject dbRaceColumn = storeRaceColumn(raceColumn); + dbRaceColumns.add(dbRaceColumn); + } + } + + private void storeLeaderboardCorrectionsAndDiscards(Leaderboard leaderboard, BasicDBObject dbLeaderboard) { + if (leaderboard.hasCarriedPoints()) { + BasicDBList dbCarriedPoints = new BasicDBList(); + dbLeaderboard.put(FieldNames.LEADERBOARD_CARRIED_POINTS_BY_ID.name(), dbCarriedPoints); + for (Entry competitorWithCarriedPoints : leaderboard + .getCompetitorsForWhichThereAreCarriedPoints().entrySet()) { + double carriedPoints = competitorWithCarriedPoints.getValue(); + Competitor competitor = competitorWithCarriedPoints.getKey(); + DBObject dbCarriedPointsForCompetitor = new BasicDBObject(); + dbCarriedPointsForCompetitor.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); + dbCarriedPointsForCompetitor.put(FieldNames.LEADERBOARD_CARRIED_POINTS.name(), carriedPoints); + dbCarriedPoints.add(dbCarriedPointsForCompetitor); + } + } + BasicDBObject dbScoreCorrections = new BasicDBObject(); + storeScoreCorrections(leaderboard, dbScoreCorrections); + dbLeaderboard.put(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name(), dbScoreCorrections); + final ResultDiscardingRule resultDiscardingRule = leaderboard.getResultDiscardingRule(); + storeResultDiscardingRule(dbLeaderboard, resultDiscardingRule, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); + BasicDBList competitorDisplayNames = new BasicDBList(); + for (Competitor competitor : leaderboard.getCompetitors()) { + String displayNameForCompetitor = leaderboard.getDisplayName(competitor); + if (displayNameForCompetitor != null) { + DBObject dbDisplayName = new BasicDBObject(); + dbDisplayName.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); + dbDisplayName.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), displayNameForCompetitor); + competitorDisplayNames.add(dbDisplayName); + } + } + dbLeaderboard.put(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name(), competitorDisplayNames); + } + + /** + * Stores the result discarding rule to dbObject's field identified by field if the result discarding + * rule is not null and is of type {@link ThresholdBasedResultDiscardingRule}. Otherwise, it is assumed that the + * result discarding rule is otherwise implicitly obtained, e.g., from a definition of a regatta with its series, stored elsewhere. + */ + private void storeResultDiscardingRule(DBObject dbObject, + final ResultDiscardingRule resultDiscardingRule, FieldNames field) { + if (resultDiscardingRule != null && resultDiscardingRule instanceof ThresholdBasedResultDiscardingRule) { + BasicDBList dbResultDiscardingThresholds = new BasicDBList(); + for (int threshold : ((ThresholdBasedResultDiscardingRule) resultDiscardingRule).getDiscardIndexResultsStartingWithHowManyRaces()) { + dbResultDiscardingThresholds.add(threshold); + } + dbObject.put(field.name(), dbResultDiscardingThresholds); + } + } + + private BasicDBObject storeRaceColumn(RaceColumn raceColumn) { + BasicDBObject dbRaceColumn = new BasicDBObject(); + dbRaceColumn.put(FieldNames.LEADERBOARD_COLUMN_NAME.name(), raceColumn.getName()); + dbRaceColumn.put(FieldNames.LEADERBOARD_IS_MEDAL_RACE_COLUMN.name(), raceColumn.isMedalRace()); + storeRaceIdentifiers(raceColumn, dbRaceColumn); + return dbRaceColumn; + } + + private void storeScoreCorrections(Leaderboard leaderboard, BasicDBObject dbScoreCorrections) { + TimePoint now = MillisecondsTimePoint.now(); + SettableScoreCorrection scoreCorrection = leaderboard.getScoreCorrection(); + for (RaceColumn raceColumn : scoreCorrection.getRaceColumnsThatHaveCorrections()) { + BasicDBList dbCorrectionForRace = new BasicDBList(); + for (Competitor competitor : scoreCorrection.getCompetitorsThatHaveCorrectionsIn(raceColumn)) { + // TODO bug 655: make score corrections time dependent + if (scoreCorrection.isScoreCorrected(competitor, raceColumn, now)) { + BasicDBObject dbCorrectionForCompetitor = new BasicDBObject(); + dbCorrectionForCompetitor.put(FieldNames.COMPETITOR_ID.name(), competitor.getId()); + MaxPointsReason maxPointsReason = scoreCorrection.getMaxPointsReason(competitor, raceColumn, now); + if (maxPointsReason != MaxPointsReason.NONE) { + dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), + maxPointsReason.name()); + } + Double explicitScoreCorrection = scoreCorrection + .getExplicitScoreCorrection(competitor, raceColumn); + if (explicitScoreCorrection != null) { + dbCorrectionForCompetitor.put(FieldNames.LEADERBOARD_CORRECTED_SCORE.name(), + explicitScoreCorrection); + } + dbCorrectionForRace.add(dbCorrectionForCompetitor); + } + } + if (!dbCorrectionForRace.isEmpty()) { + // using the column name as the key for the score corrections requires re-writing the score corrections + // of a meta-leaderboard if the name of one of its leaderboards changes + dbScoreCorrections.put(MongoUtils.escapeDollarAndDot(raceColumn.getName()), dbCorrectionForRace); + } + } + final TimePoint timePointOfLastCorrectionsValidity = scoreCorrection.getTimePointOfLastCorrectionsValidity(); + if (timePointOfLastCorrectionsValidity != null) { + dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_TIMESTAMP.name(), timePointOfLastCorrectionsValidity.asMillis()); + } + if (scoreCorrection.getComment() != null) { + dbScoreCorrections.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_COMMENT.name(), scoreCorrection.getComment()); + } + } + + @Override + public void removeLeaderboard(String leaderboardName) { + DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboardName); + leaderboardCollection.remove(query); + } + + @Override + public void renameLeaderboard(String oldName, String newName) { + DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), oldName); + BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), newName)); + leaderboardCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void storeLeaderboardGroup(LeaderboardGroup leaderboardGroup) { + DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); + DBCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); + + try { + leaderboardGroupCollection.createIndex(new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), 1)); + } catch (NullPointerException npe) { + // sometimes, for reasons yet to be clarified, ensuring an index on the name field causes an NPE + logger.log(Level.SEVERE, "storeLeaderboardGroup", npe); + } + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), leaderboardGroup.getName()); + BasicDBObject dbLeaderboardGroup = new BasicDBObject(); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_UUID.name(), leaderboardGroup.getId()); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_NAME.name(), leaderboardGroup.getName()); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DESCRIPTION.name(), leaderboardGroup.getDescription()); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_NAME.name(), leaderboardGroup.getDisplayName()); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_DISPLAY_IN_REVERSE_ORDER.name(), leaderboardGroup.isDisplayGroupsInReverseOrder()); + final Leaderboard overallLeaderboard = leaderboardGroup.getOverallLeaderboard(); + if (overallLeaderboard != null) { + BasicDBObject overallLeaderboardQuery = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), overallLeaderboard.getName()); + DBObject dbOverallLeaderboard = leaderboardCollection.findOne(overallLeaderboardQuery); + if (dbOverallLeaderboard == null) { + storeLeaderboard(overallLeaderboard); + dbOverallLeaderboard = leaderboardCollection.findOne(overallLeaderboardQuery); + } + ObjectId dbOverallLeaderboardId = (ObjectId) dbOverallLeaderboard.get("_id"); + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_OVERALL_LEADERBOARD.name(), dbOverallLeaderboardId); + } + BasicDBList dbLeaderboardIds = new BasicDBList(); + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + BasicDBObject leaderboardQuery = new BasicDBObject(FieldNames.LEADERBOARD_NAME.name(), leaderboard.getName()); + DBObject dbLeaderboard = leaderboardCollection.findOne(leaderboardQuery); + if (dbLeaderboard == null) { + storeLeaderboard(leaderboard); + dbLeaderboard = leaderboardCollection.findOne(leaderboardQuery); + } + ObjectId dbLeaderboardId = (ObjectId) dbLeaderboard.get("_id"); + dbLeaderboardIds.add(dbLeaderboardId); + } + dbLeaderboardGroup.put(FieldNames.LEADERBOARD_GROUP_LEADERBOARDS.name(), dbLeaderboardIds); + leaderboardGroupCollection.update(query, dbLeaderboardGroup, true, false, WriteConcern.SAFE); + } + + @Override + public void removeLeaderboardGroup(String groupName) { + DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), groupName); + leaderboardGroupCollection.remove(query); + } + + @Override + public void renameLeaderboardGroup(String oldName, String newName) { + DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), oldName); + BasicDBObject update = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), newName)); + leaderboardGroupCollection.update(query, update, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void storeServerConfiguration(SailingServerConfiguration serverConfiguration) { + DBCollection serverCollection = database.getCollection(CollectionNames.SERVER_CONFIGURATION.name()); + DBObject newServerConfig = new BasicDBObject(); + newServerConfig.put(FieldNames.SERVER_IS_STANDALONE.name(), serverConfiguration.isStandaloneServer()); + DBObject currentServerConfig = serverCollection.findOne(); + if(currentServerConfig != null) { + serverCollection.update(currentServerConfig, newServerConfig, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } else { + serverCollection.save(newServerConfig); + } + } + + @Override + public void storeSailingServer(RemoteSailingServerReference server) { + DBCollection serverCollection = database.getCollection(CollectionNames.SAILING_SERVERS.name()); + serverCollection.createIndex(new BasicDBObject(FieldNames.SERVER_NAME.name(), 1)); + DBObject query = new BasicDBObject(); + query.put(FieldNames.SERVER_NAME.name(), server.getName()); + DBObject serverDBObject = new BasicDBObject(); + serverDBObject.put(FieldNames.SERVER_NAME.name(), server.getName()); + serverDBObject.put(FieldNames.SERVER_URL.name(), server.getURL().toExternalForm()); + serverCollection.update(query, serverDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void removeSailingServer(String name) { + DBCollection serverCollection = database.getCollection(CollectionNames.SAILING_SERVERS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.SERVER_NAME.name(), name); + serverCollection.remove(query); + } + + /** + * StoreEvent() uses some deprecated methods of event to keep backward compatibility. + */ + @SuppressWarnings("deprecation") + @Override + public void storeEvent(Event event) { + DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name()); + eventCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); + DBObject query = new BasicDBObject(); + query.put(FieldNames.EVENT_ID.name(), event.getId()); + DBObject eventDBObject = new BasicDBObject(); + eventDBObject.put(FieldNames.EVENT_NAME.name(), event.getName()); + eventDBObject.put(FieldNames.EVENT_DESCRIPTION.name(), event.getDescription()); + eventDBObject.put(FieldNames.EVENT_ID.name(), event.getId()); + eventDBObject.put(FieldNames.EVENT_LOGO_IMAGE_URL.name(), event.getLogoImageURL() != null ? event.getLogoImageURL().toString() : null); + eventDBObject.put(FieldNames.EVENT_OFFICIAL_WEBSITE_URL.name(), event.getOfficialWebsiteURL() != null ? event.getOfficialWebsiteURL().toString() : null); + eventDBObject.put(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name(), event.getSailorsInfoWebsiteURL() != null ? event.getSailorsInfoWebsiteURL().toString() : null); + storeTimePoint(event.getStartDate(), eventDBObject, FieldNames.EVENT_START_DATE); + storeTimePoint(event.getEndDate(), eventDBObject, FieldNames.EVENT_END_DATE); + eventDBObject.put(FieldNames.EVENT_IS_PUBLIC.name(), event.isPublic()); + DBObject venueDBObject = getVenueAsDBObject(event.getVenue()); + eventDBObject.put(FieldNames.VENUE.name(), venueDBObject); + BasicDBList imageURLs = new BasicDBList(); + for (URL imageURL : event.getImageURLs()) { + imageURLs.add(imageURL.toString()); + } + eventDBObject.put(FieldNames.EVENT_IMAGE_URLS.name(), imageURLs); + BasicDBList videoURLs = new BasicDBList(); + for (URL videoURL : event.getVideoURLs()) { + videoURLs.add(videoURL.toString()); + } + eventDBObject.put(FieldNames.EVENT_VIDEO_URLS.name(), videoURLs); + BasicDBList sponsorImageURLs = new BasicDBList(); + for (URL sponsorImageURL : event.getSponsorImageURLs()) { + sponsorImageURLs.add(sponsorImageURL.toString()); + } + eventDBObject.put(FieldNames.EVENT_SPONSOR_IMAGE_URLS.name(), sponsorImageURLs); + BasicDBList images = new BasicDBList(); + for (ImageDescriptor image : event.getImages()) { + DBObject imageObject = createImageObject(image); + images.add(imageObject); + } + eventDBObject.put(FieldNames.EVENT_IMAGES.name(), images); + BasicDBList videos = new BasicDBList(); + for (VideoDescriptor video: event.getVideos()) { + DBObject videoObject = createVideoObject(video); + videos.add(videoObject); + } + eventDBObject.put(FieldNames.EVENT_VIDEOS.name(), videos); + eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + // now store the links to the leaderboard groups + DBCollection linksCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUP_LINKS_FOR_EVENTS.name()); + linksCollection.createIndex(new BasicDBObject(FieldNames.EVENT_ID.name(), 1)); + BasicDBList lgUUIDs = new BasicDBList(); + for (LeaderboardGroup lg : event.getLeaderboardGroups()) { + lgUUIDs.add(lg.getId()); + } + DBObject dbLinks = new BasicDBObject(); + dbLinks.put(FieldNames.EVENT_ID.name(), event.getId()); + dbLinks.put(FieldNames.LEADERBOARD_GROUP_UUID.name(), lgUUIDs); + linksCollection.update(query, dbLinks, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void renameEvent(Serializable id, String newName) { + DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.EVENT_ID.name(), id); + BasicDBObject renameUpdate = new BasicDBObject("$set", new BasicDBObject(FieldNames.EVENT_NAME.name(), newName)); + eventCollection.update(query, renameUpdate, /* upsert */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void removeEvent(Serializable id) { + DBCollection eventsCollection = database.getCollection(CollectionNames.EVENTS.name()); + BasicDBObject query = new BasicDBObject(FieldNames.EVENT_ID.name(), id); + eventsCollection.remove(query); + } + + private DBObject getVenueAsDBObject(Venue venue) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.VENUE_NAME.name(), venue.getName()); + BasicDBList courseAreaList = new BasicDBList(); + result.put(FieldNames.COURSE_AREAS.name(), courseAreaList); + for (CourseArea courseArea : venue.getCourseAreas()) { + DBObject dbCourseArea = new BasicDBObject(); + courseAreaList.add(dbCourseArea); + dbCourseArea.put(FieldNames.COURSE_AREA_NAME.name(), courseArea.getName()); + dbCourseArea.put(FieldNames.COURSE_AREA_ID.name(), courseArea.getId()); + } + return result; + } + + @Override + public void storeRegatta(Regatta regatta) { + DBCollection regattasCollection = database.getCollection(CollectionNames.REGATTAS.name()); + regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_NAME.name(), 1)); + regattasCollection.createIndex(new BasicDBObject(FieldNames.REGATTA_ID.name(), 1)); + DBObject dbRegatta = new BasicDBObject(); + DBObject query = new BasicDBObject(FieldNames.REGATTA_NAME.name(), regatta.getName()); + dbRegatta.put(FieldNames.REGATTA_NAME.name(), regatta.getName()); + dbRegatta.put(FieldNames.REGATTA_ID.name(), regatta.getId()); + storeTimePoint(regatta.getStartDate(), dbRegatta, FieldNames.REGATTA_START_DATE); + storeTimePoint(regatta.getEndDate(), dbRegatta, FieldNames.REGATTA_END_DATE); + dbRegatta.put(FieldNames.SCORING_SCHEME_TYPE.name(), regatta.getScoringScheme().getType().name()); + if (regatta.getBoatClass() != null) { + dbRegatta.put(FieldNames.BOAT_CLASS_NAME.name(), regatta.getBoatClass().getName()); + dbRegatta.put(FieldNames.BOAT_CLASS_TYPICALLY_STARTS_UPWIND.name(), regatta.getBoatClass().typicallyStartsUpwind()); + } + dbRegatta.put(FieldNames.REGATTA_SERIES.name(), storeSeries(regatta.getSeries())); + + if (regatta.getDefaultCourseArea() != null) { + dbRegatta.put(FieldNames.COURSE_AREA_ID.name(), regatta.getDefaultCourseArea().getId().toString()); + } else { + dbRegatta.put(FieldNames.COURSE_AREA_ID.name(), null); + } + if (regatta.getRegattaConfiguration() != null) { + JsonSerializer serializer = RegattaConfigurationJsonSerializer.create(); + JSONObject json = serializer.serialize(regatta.getRegattaConfiguration()); + DBObject configurationObject = (DBObject) JSON.parse(json.toString()); + dbRegatta.put(FieldNames.REGATTA_REGATTA_CONFIGURATION.name(), configurationObject); + } + dbRegatta.put(FieldNames.REGATTA_USE_START_TIME_INFERENCE.name(), regatta.useStartTimeInference()); + dbRegatta.put(FieldNames.REGATTA_RANKING_METRIC.name(), storeRankingMetric(regatta)); + regattasCollection.update(query, dbRegatta, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + private DBObject storeRankingMetric(Regatta regatta) { + DBObject rankingMetricJson = new BasicDBObject(); + final String rankingMetricTypeName = regatta.getRankingMetricType().name(); + rankingMetricJson.put(FieldNames.REGATTA_RANKING_METRIC_TYPE.name(), rankingMetricTypeName); + return rankingMetricJson; + } + + @Override + public void removeRegatta(Regatta regatta) { + DBCollection regattasCollection = database.getCollection(CollectionNames.REGATTAS.name()); + DBObject query = new BasicDBObject(FieldNames.REGATTA_NAME.name(), regatta.getName()); + regattasCollection.remove(query); + } + + private BasicDBList storeSeries(Iterable series) { + BasicDBList dbSeries = new BasicDBList(); + for (Series s : series) { + dbSeries.add(storeSeries(s)); + } + return dbSeries; + } + + private DBObject storeSeries(Series s) { + DBObject dbSeries = new BasicDBObject(); + dbSeries.put(FieldNames.SERIES_NAME.name(), s.getName()); + dbSeries.put(FieldNames.SERIES_IS_MEDAL.name(), s.isMedal()); + dbSeries.put(FieldNames.SERIES_HAS_SPLIT_FLEET_CONTIGUOUS_SCORING.name(), s.hasSplitFleetContiguousScoring()); + dbSeries.put(FieldNames.SERIES_STARTS_WITH_ZERO_SCORE.name(), s.isStartsWithZeroScore()); + dbSeries.put(FieldNames.SERIES_STARTS_WITH_NON_DISCARDABLE_CARRY_FORWARD.name(), s.isFirstColumnIsNonDiscardableCarryForward()); + BasicDBList dbFleets = new BasicDBList(); + for (Fleet fleet : s.getFleets()) { + dbFleets.add(storeFleet(fleet)); + } + dbSeries.put(FieldNames.SERIES_FLEETS.name(), dbFleets); + BasicDBList dbRaceColumns = new BasicDBList(); + for (RaceColumn raceColumn : s.getRaceColumns()) { + dbRaceColumns.add(storeRaceColumn(raceColumn)); + } + dbSeries.put(FieldNames.SERIES_RACE_COLUMNS.name(), dbRaceColumns); + if (s.getResultDiscardingRule() != null) { + storeResultDiscardingRule(dbSeries, s.getResultDiscardingRule(), FieldNames.SERIES_DISCARDING_THRESHOLDS); + } + return dbSeries; + } + + private DBObject storeFleet(Fleet fleet) { + DBObject dbFleet = new BasicDBObject(FieldNames.FLEET_NAME.name(), fleet.getName()); + if (fleet instanceof FleetImpl) { + dbFleet.put(FieldNames.FLEET_ORDERING.name(), ((FleetImpl) fleet).getOrdering()); + if(fleet.getColor() != null) { + com.sap.sse.common.Util.Triple colorAsRGB = fleet.getColor().getAsRGB(); + // we save the color as a integer value representing the RGB values + int colorAsInt = (256 * 256 * colorAsRGB.getC()) + colorAsRGB.getB() * 256 + colorAsRGB.getA(); + dbFleet.put(FieldNames.FLEET_COLOR.name(), colorAsInt); + } else { + dbFleet.put(FieldNames.FLEET_COLOR.name(), null); + } + } + return dbFleet; + } + + @Override + public void storeRegattaForRaceID(String raceIDAsString, Regatta regatta) { + DBCollection regattaForRaceIDCollection = database.getCollection(CollectionNames.REGATTA_FOR_RACE_ID.name()); + DBObject query = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); + DBObject entry = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); + entry.put(FieldNames.REGATTA_NAME.name(), regatta.getName()); + regattaForRaceIDCollection.update(query, entry, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + @Override + public void removeRegattaForRaceID(String raceIDAsString, Regatta regatta) { + DBCollection regattaForRaceIDCollection = database.getCollection(CollectionNames.REGATTA_FOR_RACE_ID.name()); + DBObject query = new BasicDBObject(FieldNames.RACE_ID_AS_STRING.name(), raceIDAsString); + regattaForRaceIDCollection.remove(query); + } + + public DBCollection getRaceLogCollection() { + DBCollection result = database.getCollection(CollectionNames.RACE_LOGS.name()); + result.createIndex(new BasicDBObject(FieldNames.RACE_LOG_IDENTIFIER.name(), null)); + return result; + } + + private void storeRaceLogEventAuthor(DBObject dbObject, AbstractLogEventAuthor author) { + if (author != null) { + dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_NAME.name(), author.getName()); + dbObject.put(FieldNames.RACE_LOG_EVENT_AUTHOR_PRIORITY.name(), author.getPriority()); + } + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFlagEvent flagEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFlagEvent(flagEvent)); + return result; + } + + private void storeRaceLogIdentifier(RaceLogIdentifier raceLogIdentifier, DBObject result) { + result.put(FieldNames.RACE_LOG_IDENTIFIER.name(), TripleSerializer.serialize(raceLogIdentifier.getIdentifier())); + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartTimeEvent startTimeEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartTimeEvent(startTimeEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogPassChangeEvent passChangeEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogPassChangeEvent(passChangeEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRaceStatusEvent raceStatusEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRaceStatusEvent(raceStatusEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCourseAreaChangedEvent courseAreaChangedEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCourseAreaChangedEvent(courseAreaChangedEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCourseDesignChangedEvent courseDesignChangedEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCourseDesignChangedEvent(courseDesignChangedEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFinishPositioningListChangedEvent finishPositioningListChangedEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFinishPositioningListChangedEvent(finishPositioningListChangedEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFinishPositioningConfirmedEvent(finishPositioningConfirmedEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogPathfinderEvent pathfinderEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogPathfinderEvent(pathfinderEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogGateLineOpeningTimeEvent gateLineOpeningTimeEvent) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogGateLineOpeningTimeEvent(gateLineOpeningTimeEvent)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartProcedureChangedEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartProcedureChangedEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogProtestStartTimeEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogProtestStartTimeEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogWindFixEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogWindFix(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDeviceCompetitorMappingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDeviceCompetitorMappingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDeviceMarkMappingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDeviceMarkMappingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDenoteForTrackingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDenoteForTrackingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartTrackingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartTrackingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRevokeEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRevokeEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogRegisterCompetitorEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogRegisterCompetitorEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDefineMarkEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDefineMarkEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogCloseOpenEndedDeviceMappingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogCloseOpenEndedDeviceMappingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogEndOfTrackingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogEndOfTrackingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogStartOfTrackingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogStartOfTrackingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogAdditionalScoringInformationEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeAdditionalScoringInformation(event)); + return result; + } + + private Object storeAdditionalScoringInformation(RaceLogAdditionalScoringInformationEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogAdditionalScoringInformationEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_ADDITIONAL_SCORING_INFORMATION_TYPE.name(), event.getType().name()); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogFixedMarkPassingEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogFixedMarkPassingEvent(event)); + return result; + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogSuppressedMarkPassingsEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogSuppressedMarkPassingsEvent(event)); + return result; + } + + private Object storeRaceLogWindFix(RaceLogWindFixEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogWindFixEvent.class.getSimpleName()); + result.put(FieldNames.WIND.name(), storeWind(event.getWindFix())); + result.put(FieldNames.IS_MAGNETIC.name(), event.isMagnetic()); + return result; + } + + private Object storeRaceLogProtestStartTimeEvent(RaceLogProtestStartTimeEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogProtestStartTimeEvent.class.getSimpleName()); + storeTimePoint(event.getProtestStartTime(), result, FieldNames.RACE_LOG_PROTEST_START_TIME); + return result; + } + + private Object storeRaceLogEndOfTrackingEvent(RaceLogEndOfTrackingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogEndOfTrackingEvent.class.getSimpleName()); + return result; + } + + private Object storeRaceLogStartOfTrackingEvent(RaceLogStartOfTrackingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartOfTrackingEvent.class.getSimpleName()); + return result; + } + + private Object storeRaceLogStartProcedureChangedEvent(RaceLogStartProcedureChangedEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartProcedureChangedEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_START_PROCEDURE_TYPE.name(), event.getStartProcedureType().name()); + return result; + } + + private Object storeRaceLogPathfinderEvent(RaceLogPathfinderEvent pathfinderEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(pathfinderEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogPathfinderEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_PATHFINDER_ID.name(), pathfinderEvent.getPathfinderId()); + return result; + } + + private void storeDeviceMappingEvent(DeviceMappingEvent event, DBObject result, FieldNames fromField, FieldNames toField) { + try { + result.put(FieldNames.DEVICE_ID.name(), storeDeviceId(deviceIdentifierServiceFinder, event.getDevice())); + } catch (TransformationException | NoCorrespondingServiceRegisteredException e) { + logger.log(Level.WARNING, "Could not store device identifier for mappng event", e); + } + if (event.getFrom() != null) { + storeTimePoint(event.getFrom(), result, fromField); + } + if (event.getTo() != null) { + storeTimePoint(event.getTo(), result, toField); + } + } + + private Object storeRaceLogDeviceCompetitorMappingEvent(RaceLogDeviceCompetitorMappingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceCompetitorMappingEvent.class.getSimpleName()); + storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO); + result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId()); + return result; + } + + private Object storeRaceLogDeviceMarkMappingEvent(RaceLogDeviceMarkMappingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceMarkMappingEvent.class.getSimpleName()); + storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO); + result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo())); + return result; + } + + private Object storeRaceLogDenoteForTrackingEvent(RaceLogDenoteForTrackingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDenoteForTrackingEvent.class.getSimpleName()); + result.put(FieldNames.RACE_NAME.name(), event.getRaceName()); + result.put(FieldNames.BOAT_CLASS_NAME.name(), event.getBoatClass().getName()); + result.put(FieldNames.RACE_ID.name(), event.getRaceId()); + return result; + } + + private Object storeRaceLogStartTrackingEvent(RaceLogStartTrackingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartTrackingEvent.class.getSimpleName()); + return result; + } + + private Object storeRaceLogRevokeEvent(RaceLogRevokeEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRevokeEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_REVOKED_EVENT_ID.name(), event.getRevokedEventId()); + result.put(FieldNames.RACE_LOG_REVOKED_EVENT_TYPE.name(), event.getRevokedEventType()); + result.put(FieldNames.RACE_LOG_REVOKED_EVENT_SHORT_INFO.name(), event.getRevokedEventShortInfo()); + result.put(FieldNames.RACE_LOG_REVOKED_REASON.name(), event.getReason()); + return result; + } + + private Object storeRaceLogRegisterCompetitorEvent(RaceLogRegisterCompetitorEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRegisterCompetitorEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + return result; + } + + private Object storeRaceLogDefineMarkEvent(RaceLogDefineMarkEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDefineMarkEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_MARK.name(), storeMark(event.getMark())); + return result; + } + + private Object storeRaceLogCloseOpenEndedDeviceMappingEvent(RaceLogCloseOpenEndedDeviceMappingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_DEVICE_MAPPING_EVENT_ID.name(), event.getDeviceMappingEventId()); + storeTimePoint(event.getClosingTimePoint(), result, FieldNames.RACE_LOG_CLOSING_TIMEPOINT); + return result; + } + + private Object storeRaceLogFixedMarkPassingEvent(RaceLogFixedMarkPassingEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFixedMarkPassingEvent.class.getSimpleName()); + result.put(FieldNames.INDEX_OF_PASSED_WAYPOINT.name(), event.getZeroBasedIndexOfPassedWaypoint()); + result.put(FieldNames.TIMEPOINT_OF_FIXED_MARKPASSING.name(), event.getTimePointOfFixedPassing().asMillis()); + return result; + } + + private Object storeRaceLogSuppressedMarkPassingsEvent(RaceLogSuppressedMarkPassingsEvent event) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(event, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogSuppressedMarkPassingsEvent.class.getSimpleName()); + result.put(FieldNames.INDEX_OF_FIRST_SUPPRESSED_WAYPOINT.name(), event.getZeroBasedIndexOfFirstSuppressedWaypoint()); + return result; + } + + public DBObject storeRaceLogFlagEvent(RaceLogFlagEvent flagEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(flagEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFlagEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_EVENT_FLAG_UPPER.name(), flagEvent.getUpperFlag().name()); + result.put(FieldNames.RACE_LOG_EVENT_FLAG_LOWER.name(), flagEvent.getLowerFlag().name()); + result.put(FieldNames.RACE_LOG_EVENT_FLAG_DISPLAYED.name(), String.valueOf(flagEvent.isDisplayed())); + return result; + } + + private DBObject storeRaceLogStartTimeEvent(RaceLogStartTimeEvent startTimeEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(startTimeEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogStartTimeEvent.class.getSimpleName()); + storeTimePoint(startTimeEvent.getStartTime(), result, FieldNames.RACE_LOG_EVENT_START_TIME); + result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), startTimeEvent.getNextStatus().name()); + return result; + } + + private void storeRaceLogEventProperties(RaceLogEvent event, DBObject result) { + // for compatibility reasons we reuse the field name of Timed + storeTimePoint(event.getLogicalTimePoint(), result, FieldNames.TIME_AS_MILLIS); + storeTimePoint(event.getCreatedAt(), result, FieldNames.RACE_LOG_EVENT_CREATED_AT); + result.put(FieldNames.RACE_LOG_EVENT_ID.name(), event.getId()); + result.put(FieldNames.RACE_LOG_EVENT_PASS_ID.name(), event.getPassId()); + result.put(FieldNames.RACE_LOG_EVENT_INVOLVED_BOATS.name(), storeInvolvedBoatsForRaceLogEvent(event.getInvolvedBoats())); + storeRaceLogEventAuthor(result, event.getAuthor()); + } + + + private BasicDBList storeInvolvedBoatsForRaceLogEvent(List competitors) { + BasicDBList dbInvolvedCompetitorIds = new BasicDBList(); + for (Competitor competitor : competitors) { + dbInvolvedCompetitorIds.add(competitor.getId()); + } + return dbInvolvedCompetitorIds; + } + + private DBObject storeRaceLogPassChangeEvent(RaceLogPassChangeEvent passChangeEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(passChangeEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogPassChangeEvent.class.getSimpleName()); + return result; + } + + private DBObject storeRaceLogDependentStartTimeEvent(RaceLogDependentStartTimeEvent dependentStartTimeEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(dependentStartTimeEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDependentStartTimeEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_REGATTALIKE.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getRegattaLikeParentName()); + result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_RACECOLUMN.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getRaceColumnName()); + result.put(FieldNames.RACE_LOG_DEPDENDENT_ON_FLEET.name(), dependentStartTimeEvent.getDependentOnRaceIdentifier().getFleetName()); + storeDuration(dependentStartTimeEvent.getStartTimeDifference(), result, FieldNames.RACE_LOG_START_TIME_DIFFERENCE_IN_MS); + result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), dependentStartTimeEvent.getNextStatus().name()); + return result; + } + + private void storeDuration(Duration duration, DBObject result, FieldNames fieldName) { + if (duration != null) { + result.put(fieldName.name(), duration.asMillis()); + } + } + + private DBObject storeRaceLogRaceStatusEvent(RaceLogRaceStatusEvent raceStatusEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(raceStatusEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogRaceStatusEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_EVENT_NEXT_STATUS.name(), raceStatusEvent.getNextStatus().name()); + return result; + } + + private DBObject storeRaceLogCourseAreaChangedEvent(RaceLogCourseAreaChangedEvent courseAreaChangedEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(courseAreaChangedEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCourseAreaChangedEvent.class.getSimpleName()); + result.put(FieldNames.COURSE_AREA_ID.name(), courseAreaChangedEvent.getCourseAreaId()); + return result; + } + + private DBObject storeRaceLogCourseDesignChangedEvent(RaceLogCourseDesignChangedEvent courseDesignChangedEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(courseDesignChangedEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogCourseDesignChangedEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_COURSE_DESIGN_NAME.name(), courseDesignChangedEvent.getCourseDesign().getName()); + result.put(FieldNames.RACE_LOG_COURSE_DESIGN.name(), storeCourseBase(courseDesignChangedEvent.getCourseDesign())); + return result; + } + + private Object storeRaceLogFinishPositioningListChangedEvent(RaceLogFinishPositioningListChangedEvent finishPositioningListChangedEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(finishPositioningListChangedEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningListChangedEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningListChangedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + + return result; + } + + private Object storeRaceLogFinishPositioningConfirmedEvent(RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent) { + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(finishPositioningConfirmedEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogFinishPositioningConfirmedEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_POSITIONED_COMPETITORS.name(), storePositionedCompetitors(finishPositioningConfirmedEvent.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + + return result; + } + + private Object storeRaceLogGateLineOpeningTimeEvent(RaceLogGateLineOpeningTimeEvent gateLineOpeningTimeEvent){ + DBObject result = new BasicDBObject(); + storeRaceLogEventProperties(gateLineOpeningTimeEvent, result); + result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogGateLineOpeningTimeEvent.class.getSimpleName()); + result.put(FieldNames.RACE_LOG_GATE_LINE_OPENING_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGateLaunchStopTime()); + result.put(FieldNames.RACE_LOG_GOLF_DOWN_TIME.name(), gateLineOpeningTimeEvent.getGateLineOpeningTimes().getGolfDownTime()); + return result; + } + + private BasicDBList storePositionedCompetitors(List> positionedCompetitors) { + BasicDBList dbList = new BasicDBList(); + if (positionedCompetitors != null) { + for (com.sap.sse.common.Util.Triple competitorPair : positionedCompetitors) { + dbList.add(storePositionedCompetitor(competitorPair)); + } + } + return dbList; + } + + private DBObject storePositionedCompetitor(com.sap.sse.common.Util.Triple competitorTriple) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.COMPETITOR_ID.name(), competitorTriple.getA()); + result.put(FieldNames.COMPETITOR_DISPLAY_NAME.name(), competitorTriple.getB()); + result.put(FieldNames.LEADERBOARD_SCORE_CORRECTION_MAX_POINTS_REASON.name(), competitorTriple.getC().name()); + + return result; + } + + private BasicDBList storeCourseBase(CourseBase courseData) { + BasicDBList dbList = new BasicDBList(); + + for (Waypoint waypoint : courseData.getWaypoints()) { + dbList.add(storeWaypoint(waypoint)); + } + return dbList; + } + + private DBObject storeWaypoint(Waypoint waypoint) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.WAYPOINT_PASSINGINSTRUCTIONS.name(), getPassingInstructions(waypoint.getPassingInstructions())); + result.put(FieldNames.CONTROLPOINT.name(), storeControlPoint(waypoint.getControlPoint())); + return result; + } + + private DBObject storeControlPoint(ControlPoint controlPoint) { + DBObject result = new BasicDBObject(); + if (controlPoint instanceof Mark) { + result.put(FieldNames.CONTROLPOINT_CLASS.name(), Mark.class.getSimpleName()); + result.put(FieldNames.CONTROLPOINT_VALUE.name(), storeMark((Mark) controlPoint)); + } else if (controlPoint instanceof ControlPointWithTwoMarks) { + result.put(FieldNames.CONTROLPOINT_CLASS.name(), ControlPointWithTwoMarks.class.getSimpleName()); + result.put(FieldNames.CONTROLPOINT_VALUE.name(), storeControlPointWithTwoMarks((ControlPointWithTwoMarks) controlPoint)); + } + return result; + } + + private DBObject storeControlPointWithTwoMarks(ControlPointWithTwoMarks cpwtm) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_ID.name(), cpwtm.getId()); + result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_NAME.name(), cpwtm.getName()); + result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_LEFT.name(), storeMark(cpwtm.getLeft())); + result.put(FieldNames.CONTROLPOINTWITHTWOMARKS_RIGHT.name(), storeMark(cpwtm.getRight())); + return result; + } + + private DBObject storeMark(Mark mark) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.MARK_ID.name(), mark.getId()); + result.put(FieldNames.MARK_COLOR.name(), mark.getColor()); + result.put(FieldNames.MARK_NAME.name(), mark.getName()); + result.put(FieldNames.MARK_PATTERN.name(), mark.getPattern()); + result.put(FieldNames.MARK_SHAPE.name(), mark.getShape()); + result.put(FieldNames.MARK_TYPE.name(), mark.getType() == null ? null : mark.getType().name()); + return result; + } + + private String getPassingInstructions(PassingInstruction passingInstructions) { + final String passing; + if (passingInstructions != null) { + passing = passingInstructions.name(); + } else { + passing = null; + } + return passing; + } + @Override + public void storeCompetitor(Competitor competitor) { + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + JSONObject json = competitorSerializer.serialize(competitor); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + DBObject entry = (DBObject) JSON.parse(json.toString()); + collection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); + } + + @Override + public void removeAllCompetitors() { + logger.info("Removing all persistent competitor info"); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + collection.drop(); + } + + @Override + public void removeCompetitor(Competitor competitor) { + logger.info("Removing persistent competitor info for competitor "+competitor.getName()+" with ID "+competitor.getId()); + DBCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); + DBObject query = (DBObject) JSON.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); + collection.remove(query, WriteConcern.SAFE); + } + + @Override + public void storeDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) { + DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name()); + + DBObject query = new BasicDBObject(); + query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); + + DBObject entryObject = new BasicDBObject(); + entryObject.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); + entryObject.put(FieldNames.CONFIGURATION_MATCHER.name(), createDeviceConfigurationMatcherObject(matcher)); + entryObject.put(FieldNames.CONFIGURATION_CONFIG.name(), createDeviceConfigurationObject(configuration)); + + configurationsCollections.update(query, entryObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE); + } + + private DBObject createDeviceConfigurationMatcherObject(DeviceConfigurationMatcher matcher) { + DBObject matcherObject = new BasicDBObject(); + matcherObject.put(FieldNames.CONFIGURATION_MATCHER_TYPE.name(), matcher.getMatcherType().name()); + if (matcher instanceof DeviceConfigurationMatcherSingle) { + BasicDBList client = new BasicDBList(); + client.add(((DeviceConfigurationMatcherSingle)matcher).getClientIdentifier()); + matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), client); + } else if (matcher instanceof DeviceConfigurationMatcherMulti) { + BasicDBList clients = new BasicDBList(); + Util.addAll(((DeviceConfigurationMatcherMulti)matcher).getClientIdentifiers(), clients); + matcherObject.put(FieldNames.CONFIGURATION_MATCHER_CLIENTS.name(), clients); + } + return matcherObject; + } + + private DBObject createDeviceConfigurationObject(DeviceConfiguration configuration) { + JsonSerializer serializer = DeviceConfigurationJsonSerializer.create(); + JSONObject json = serializer.serialize(configuration); + DBObject entry = (DBObject) JSON.parse(json.toString()); + return entry; + } + + @Override + public void removeDeviceConfiguration(DeviceConfigurationMatcher matcher) { + DBCollection configurationsCollections = database.getCollection(CollectionNames.CONFIGURATIONS.name()); + DBObject query = new BasicDBObject(); + query.put(FieldNames.CONFIGURATION_MATCHER_ID.name(), matcher.getMatcherIdentifier()); + configurationsCollections.remove(query); + } + + public static DBObject storeDeviceId( + TypeBasedServiceFinder deviceIdentifierServiceFinder, DeviceIdentifier device) + throws TransformationException, NoCorrespondingServiceRegisteredException { + String type = device.getIdentifierType(); + DeviceIdentifierMongoHandler handler = deviceIdentifierServiceFinder.findService(type); + com.sap.sse.common.Util.Pair pair = handler.serialize(device); + type = pair.getA(); + Object deviceTypeSpecificId = pair.getB(); + return new BasicDBObjectBuilder() + .add(FieldNames.DEVICE_TYPE.name(), type) + .add(FieldNames.DEVICE_TYPE_SPECIFIC_ID.name(), deviceTypeSpecificId) + .add(FieldNames.DEVICE_STRING_REPRESENTATION.name(), device.getStringRepresentation()).get(); + } + + void storeRaceLogEventEvent(DBObject eventEntry) { + getRaceLogCollection().insert(eventEntry); + } + + @Override + public void removeRaceLog(RaceLogIdentifier identifier) { + DBObject query = new BasicDBObject(); + storeRaceLogIdentifier(identifier, query); + getRaceLogCollection().remove(query); + } + + @Override + public void removeRegattaLog(RegattaLikeIdentifier identifier) { + DBObject query = new BasicDBObject(); + addRegattaLikeIdentifier(identifier, query); + getRegattaLogCollection().remove(query); + } + + @Override + public void storeResultUrl(String resultProviderName, URL url) { + DBCollection resultUrlsCollection = database.getCollection(CollectionNames.RESULT_URLS.name()); + DBObject query = new BasicDBObject(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName); + DBObject entry = new BasicDBObject(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName); + entry.put(FieldNames.RESULT_URL.name(), url.toString()); + resultUrlsCollection.update(query, entry, /* upsrt */true, /* multi */false, WriteConcern.SAFE); + } + + @Override + public void removeResultUrl(String resultProviderName, URL url) { + DBCollection resultUrlsCollection = database.getCollection(CollectionNames.RESULT_URLS.name()); + DBObject query = new BasicDBObjectBuilder().add(FieldNames.RESULT_PROVIDERNAME.name(), resultProviderName) + .add(FieldNames.RESULT_URL.name(), url.toString()).get(); + resultUrlsCollection.remove(query); + } + + public DBCollection getRegattaLogCollection() { + DBCollection result = database.getCollection(CollectionNames.REGATTA_LOGS.name()); + DBObject index = new BasicDBObject(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), null); + index.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), null); + result.createIndex(index); + return result; + } + + private DBObject createBasicRegattaLogEventDBObject(RegattaLogEvent event) { + DBObject result = new BasicDBObject(); + storeTimed(event, result); + storeTimePoint(event.getCreatedAt(), result, FieldNames.REGATTA_LOG_EVENT_CREATED_AT); + result.put(FieldNames.REGATTA_LOG_EVENT_ID.name(), event.getId()); + result.put(FieldNames.REGATTA_LOG_EVENT_AUTHOR_NAME.name(), event.getAuthor().getName()); + result.put(FieldNames.REGATTA_LOG_EVENT_AUTHOR_PRIORITY.name(), event.getAuthor().getPriority()); + return result; + } + + private void addRegattaLikeIdentifier(RegattaLikeIdentifier regattaLikeId, DBObject toObject) { + toObject.put(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), regattaLikeId.getIdentifierType()); + toObject.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), regattaLikeId.getName()); + } + + private void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, DBObject innerObject) { + DBObject result = new BasicDBObject(FieldNames.REGATTA_LOG_EVENT.name(), innerObject); + addRegattaLikeIdentifier(regattaLikeId, result); + getRegattaLogCollection().insert(result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceCompetitorMappingEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName()); + storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO); + result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceMarkMappingEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceMarkMappingEvent.class.getSimpleName()); + storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO); + result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo())); + storeRegattaLogEvent(regattaLikeId, result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRevokeEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRevokeEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_ID.name(), event.getRevokedEventId()); + result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_TYPE.name(), event.getRevokedEventType()); + result.put(FieldNames.REGATTA_LOG_REVOKED_EVENT_SHORT_INFO.name(), event.getRevokedEventShortInfo()); + result.put(FieldNames.REGATTA_LOG_REVOKED_REASON.name(), event.getReason()); + storeRegattaLogEvent(regattaLikeId, result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogRegisterCompetitorEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogRegisterCompetitorEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + storeRegattaLogEvent(regattaLikeId, result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogCloseOpenEndedDeviceMappingEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_DEVICE_MAPPING_EVENT_ID.name(), event.getDeviceMappingEventId()); + storeTimePoint(event.getClosingTimePoint(), result, FieldNames.REGATTA_LOG_CLOSING_TIMEPOINT); + storeRegattaLogEvent(regattaLikeId, result); + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.REGATTA_LOG_TIME_ON_TIME_FACTOR.name(), event.getTimeOnTimeFactor()); + } + + public DBObject storeRaceLogEntry(RaceLogIdentifier raceLogIdentifier, RaceLogDependentStartTimeEvent event) { + BasicDBObject result = new BasicDBObject(); + storeRaceLogIdentifier(raceLogIdentifier, result); + result.put(FieldNames.RACE_LOG_EVENT.name(), storeRaceLogDependentStartTimeEvent(event)); + return result; + } + + public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) { + DBObject result = createBasicRegattaLogEventDBObject(event); + result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName()); + result.put(FieldNames.REGATTA_LOG_COMPETITOR_ID.name(), event.getCompetitor().getId()); + result.put(FieldNames.REGATTA_LOG_TIME_ON_DISTANCE_SECONDS_ALLOWANCE_PER_NAUTICAL_MILE.name(), event.getTimeOnDistanceAllowancePerNauticalMile().asSeconds()); + storeRegattaLogEvent(regattaLikeId, result); + } + + private DBObject createImageObject(ImageDescriptor image) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.IMAGE_URL.name(), image.getURL().toString()); + result.put(FieldNames.IMAGE_LOCALE.name(), image.getLocale() != null ? image.getLocale().toLanguageTag() : null); + result.put(FieldNames.IMAGE_TITLE.name(), image.getTitle()); + result.put(FieldNames.IMAGE_SUBTITLE.name(), image.getSubtitle()); + result.put(FieldNames.IMAGE_COPYRIGHT.name(), image.getCopyright()); + result.put(FieldNames.IMAGE_WIDTH_IN_PX.name(), image.getWidthInPx()); + result.put(FieldNames.IMAGE_HEIGHT_IN_PX.name(), image.getHeightInPx()); + storeTimePoint(image.getCreatedAtDate(), result, FieldNames.IMAGE_CREATEDATDATE); + BasicDBList tags = new BasicDBList(); + for (String tag : image.getTags()) { + tags.add(tag); + } + result.put(FieldNames.IMAGE_TAGS.name(), tags); + return result; + } + + private DBObject createVideoObject(VideoDescriptor video) { + DBObject result = new BasicDBObject(); + result.put(FieldNames.VIDEO_URL.name(), video.getURL().toString()); + result.put(FieldNames.VIDEO_LOCALE.name(), video.getLocale() != null ? video.getLocale().toLanguageTag() : null); + result.put(FieldNames.VIDEO_THUMBNAIL_URL.name(), video.getThumbnailURL() != null ? video.getThumbnailURL().toString() : null); + result.put(FieldNames.VIDEO_TITLE.name(), video.getTitle()); + result.put(FieldNames.VIDEO_SUBTITLE.name(), video.getSubtitle()); + result.put(FieldNames.VIDEO_MIMETYPE.name(), video.getMimeType() != null ? video.getMimeType().name() : null); + result.put(FieldNames.VIDEO_COPYRIGHT.name(), video.getCopyright()); + result.put(FieldNames.VIDEO_LENGTH_IN_SECONDS.name(), video.getLengthInSeconds()); + storeTimePoint(video.getCreatedAtDate(), result, FieldNames.VIDEO_CREATEDATDATE); + BasicDBList tags = new BasicDBList(); + for (String tag : video.getTags()) { + tags.add(tag); + } + result.put(FieldNames.VIDEO_TAGS.name(), tags); + return result; + } +} diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java index 679b6b97455..f48a27959ec 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/AbstractGPSFixStoreTest.java @@ -9,8 +9,9 @@ import org.junit.Before; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Mark; @@ -66,8 +67,8 @@ public class AbstractGPSFixStoreTest { } protected void map(RaceLog raceLog, Competitor comp, DeviceIdentifier device, long from, long to) { - raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceCompetitorMappingEvent(MillisecondsTimePoint.now(), author, device, - comp, 0, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to))); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), author, 0, + comp, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to))); } protected void map(Competitor comp, DeviceIdentifier device, long from, long to) { @@ -75,8 +76,8 @@ public class AbstractGPSFixStoreTest { } protected void map(Mark mark, DeviceIdentifier device, long from, long to) { - raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceMarkMappingEvent(MillisecondsTimePoint.now(), author, device, - mark, 0, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to))); + raceLog.add(new RaceLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), author, 0, + mark, device, new MillisecondsTimePoint(from), new MillisecondsTimePoint(to))); } protected void testNumberOfRawFixes(Track track, long expected) { diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java index f43277c8b1d..17302ae2345 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelogtracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -19,7 +19,8 @@ import org.junit.rules.ExpectedException; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +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.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; @@ -68,8 +69,6 @@ public class CreateAndTrackWithRaceLogTest { private long time = 0; - private static final RaceLogEventFactory factory = RaceLogEventFactory.INSTANCE; - @Before public void setup() { service = new RacingEventServiceImpl(true, new MockSmartphoneImeiServiceFinderFactory()); @@ -172,9 +171,9 @@ public class CreateAndTrackWithRaceLogTest { Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); - raceLog.add(factory.createDeviceCompetitorMappingEvent(t(), author, dev1, comp1, 0, t(0), t(10))); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(t(), author, 0, comp1, dev1, t(0), t(10))); addFixes0(dev1); - raceLog.add(factory.createRegisterCompetitorEvent(t(), author, 0, comp1)); + raceLog.add(new RaceLogRegisterCompetitorEventImpl(t(), author, 0, comp1)); // start tracking adapter.startTracking(service, leaderboard, column, fleet); @@ -185,7 +184,7 @@ public class CreateAndTrackWithRaceLogTest { race.waitForLoadingFromGPSFixStoreToFinishRunning(raceLog); addFixes1(race, comp1, dev1); - raceLog.add(factory.createDeviceCompetitorMappingEvent(t(), author, dev1, comp1, 0, t(11), t(20))); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(t(), author, 0, comp1, dev1, t(11), t(20))); // add another mapping on the fly, other old fixes should be loaded addFixes2(race, comp1, dev1); @@ -207,10 +206,10 @@ public class CreateAndTrackWithRaceLogTest { Competitor comp1 = DomainFactory.INSTANCE.getOrCreateCompetitor("comp1", "comp1", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); DeviceIdentifier dev1 = new SmartphoneImeiIdentifier("dev1"); - regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), author, t(), UUID.randomUUID(), comp1, dev1, + regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, t(0), t(10))); addFixes0(dev1); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(t(), author, t(), UUID.randomUUID(), comp1)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(t(), t(), author, UUID.randomUUID(), comp1)); // start tracking adapter.startTracking(service, leaderboard, column, fleet); @@ -223,7 +222,7 @@ public class CreateAndTrackWithRaceLogTest { addFixes1(race, comp1, dev1); // add another mapping on the fly, other old fixes should be loaded - regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), author, t(), UUID.randomUUID(), comp1, dev1, + regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), comp1, dev1, t(11), t(20))); addFixes2(race, comp1, dev1); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java index 309f42ec296..60b93d28a46 100755 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogTrackingAdapterImpl.java @@ -29,14 +29,22 @@ import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; import com.sap.sailing.domain.abstractlog.impl.LastEventOfTypeFinder; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; @@ -101,7 +109,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { } RegattaIdentifier regatta = ((RegattaLeaderboard) leaderboard).getRegatta().getRegattaIdentifier(); if (raceLogTrackingState != RaceLogTrackingState.TRACKING) { - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createStartTrackingEvent(MillisecondsTimePoint.now(), + RaceLogEvent event = new RaceLogStartTrackingEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), raceLog.getCurrentPassId()); raceLog.add(event); } @@ -157,7 +165,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { throw new NotDenotableForRaceLogTrackingException("Already denoted for tracking"); } - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDenoteForTrackingEvent(MillisecondsTimePoint.now(), + RaceLogEvent event = new RaceLogDenoteForTrackingEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), raceLog.getCurrentPassId(), raceName, boatClass, UUID.randomUUID()); raceLog.add(event); } @@ -225,15 +233,15 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { newCourse.addWaypoint(i++, oldWaypoint); } for (Mark mark : marks) { - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDefineMarkEvent(now, - service.getServerAuthor(), toRaceLog.getCurrentPassId(), mark); + RaceLogEvent event = new RaceLogDefineMarkEventImpl(now, service.getServerAuthor(), + toRaceLog.getCurrentPassId(), mark); toRaceLog.add(event); } for (RaceLogEvent raceLogDeviceMarkMappingEvent : raceLogDeviceMarkMappingEvents) { toRaceLog.add(raceLogDeviceMarkMappingEvent); } int passId = toRaceLog.getCurrentPassId(); - RaceLogEvent newCourseEvent = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now, + RaceLogEvent newCourseEvent = new RaceLogCourseDesignChangedEventImpl(now, service.getServerAuthor(), passId, newCourse); toRaceLog.add(newCourseEvent); } @@ -243,8 +251,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { } @Override - public void copyCompetitors(RaceLog fromRaceLog, Set toRaceLogs, - RacingEventService service) { + public void copyCompetitors(RaceLog fromRaceLog, Set toRaceLogs, RacingEventService service) { final Set competitors = new RegisteredCompetitorsAnalyzer<>(fromRaceLog).analyze(); for (RaceLog toRaceLog : toRaceLogs) { registerCompetitors(service, toRaceLog, competitors); @@ -271,17 +278,25 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { @Override public void pingMark(RaceLog raceLog, Mark mark, GPSFix gpsFix, RacingEventService service) { - pingMark(raceLog, mark, gpsFix, service, - (DeviceIdentifier dev, TimePoint timePoint) -> RaceLogEventFactory.INSTANCE - .createDeviceMarkMappingEvent(timePoint, service.getServerAuthor(), dev, mark, - raceLog.getCurrentPassId(), timePoint, timePoint), new PingDeviceIdentifierImpl()); + DeviceMarkMappingEventFactory raceLogEventFactory = + (DeviceIdentifier dev, TimePoint timePoint) -> new RaceLogDeviceMarkMappingEventImpl(timePoint, service + .getServerAuthor(), raceLog.getCurrentPassId(), mark, dev, timePoint, timePoint); + pingMark( + raceLog, + mark, + gpsFix, + service, + raceLogEventFactory, + new PingDeviceIdentifierImpl()); } @Override public void pingMark(RegattaLog regattaLog, Mark mark, GPSFix gpsFix, RacingEventService service) { - pingMark(regattaLog, mark, gpsFix, service, + DeviceMarkMappingEventFactory regattaLogEventFactory = (DeviceIdentifier dev, TimePoint timePoint) -> new RegattaLogDeviceMarkMappingEventImpl(timePoint, - service.getServerAuthor(), timePoint, UUID.randomUUID(), mark, dev, timePoint, timePoint), + timePoint, service.getServerAuthor(), UUID.randomUUID(), mark, dev, timePoint, timePoint); + pingMark(regattaLog, mark, gpsFix, service, + regattaLogEventFactory, new PingDeviceIdentifierImpl()); } @@ -337,19 +352,16 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { @Override public void registerCompetitors(RacingEventService service, RaceLog raceLog, Set competitors) { - registerCompetitors( - service.getServerAuthor(), - raceLog, - competitors, - c -> RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), - service.getServerAuthor(), raceLog.getCurrentPassId(), c)); + registerCompetitors(service.getServerAuthor(), raceLog, competitors, + c -> new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), + raceLog.getCurrentPassId(), c)); } @Override public void registerCompetitors(RacingEventService service, RegattaLog regattaLog, Set competitors) { registerCompetitors(service.getServerAuthor(), regattaLog, competitors, - c -> new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), service.getServerAuthor(), - MillisecondsTimePoint.now(), UUID.randomUUID(), c)); + c -> new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), + MillisecondsTimePoint.now(), service.getServerAuthor(), UUID.randomUUID(), c)); } private MailService getMailService() { diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/DependentStartTimeFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/DependentStartTimeFinderTest.java index a9653af5044..bb89960120a 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/DependentStartTimeFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/DependentStartTimeFinderTest.java @@ -21,6 +21,7 @@ import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEve import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -64,16 +65,16 @@ public class DependentStartTimeFinderTest { @Test public void testDependentStartTimeUpdate() { final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(5000); - raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB)); + raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB, RaceLogRaceStatus.SCHEDULED)); StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC); // Tests for correct behaviour, when race depending on has no start time set assertNull(finder.analyze().getStartTime()); final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(6000); - raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA)); + raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA, RaceLogRaceStatus.SCHEDULED)); finder = new StartTimeFinder(raceLogResolver, raceLogB); StartTimeFinderResult result = finder.analyze(); @@ -98,7 +99,8 @@ public class DependentStartTimeFinderTest { assertEquals(expectedDependingOnRaces, result.getRacesDependingOn()); TimePoint now = MillisecondsTimePoint.now(); - raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000))); + raceLogA.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(5000), + RaceLogRaceStatus.SCHEDULED)); finder = new StartTimeFinder(raceLogResolver, raceLogB); result = finder.analyze(); @@ -111,7 +113,8 @@ public class DependentStartTimeFinderTest { assertEquals(5000, result.getStartTimeDiff().asMillis()); // Test correct behaviour, when middle element changes - raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(15000))); + raceLogB.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(15000), + RaceLogRaceStatus.SCHEDULED)); finder = new StartTimeFinder(raceLogResolver, raceLogA); result = finder.analyze(); assertEquals(5000, result.getStartTime().asMillis()); @@ -131,16 +134,16 @@ public class DependentStartTimeFinderTest { @Test public void testDependentStartTimeCycle() { final MillisecondsDurationImpl cAfterB = new MillisecondsDurationImpl(6000); - raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB)); + raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("B", "", ""), cAfterB, RaceLogRaceStatus.SCHEDULED)); final MillisecondsDurationImpl bAfterA = new MillisecondsDurationImpl(7000); - raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA)); + raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("A", "", ""), bAfterA, RaceLogRaceStatus.SCHEDULED)); final MillisecondsDurationImpl aAfterC = new MillisecondsDurationImpl(8000); - raceLogA.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("C", "", ""), aAfterC)); + raceLogA.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("C", "", ""), aAfterC, RaceLogRaceStatus.SCHEDULED)); // Check that all resolve to null in case of a cycle StartTimeFinder finder = new StartTimeFinder(raceLogResolver, raceLogC); @@ -157,7 +160,8 @@ public class DependentStartTimeFinderTest { // Check that all resolve correctly after changing some element in cycle TimePoint now = MillisecondsTimePoint.now(); - raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000))); + raceLogB.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(5000), + RaceLogRaceStatus.SCHEDULED)); // now A -> C -> B finder = new StartTimeFinder(raceLogResolver, raceLogA); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java index 02ceb503d7e..d7734f9bd2a 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/analyzing/test/MultiLogAnalyzerTest.java @@ -72,11 +72,11 @@ public class MultiLogAnalyzerTest { Competitor c2 = createCompetitor(2); Competitor c3 = createCompetitor(3); - raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), author, now(), uuid(), 0, c1)); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), author, now(), uuid(), c2)); + raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), 0, c1)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), c2)); - raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), author, now(), uuid(), 0, c3)); - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), author, now(), uuid(), c3)); + raceLog.add(new RaceLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), 0, c3)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(now(), now(), author, uuid(), c3)); Set result = new MultiLogAnalyzer<>( RegisteredCompetitorsAnalyzer.Factory.INSTANCE, new MultiLogAnalyzer.SetReducer(), raceLog, @@ -96,12 +96,12 @@ public class MultiLogAnalyzerTest { DeviceIdentifier d1 = createDevice(); DeviceIdentifier d2 = createDevice(); - raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), author, now(), 0, 0, c1, d1, t(0), t(10))); - raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), author, now(), 1, 0, c1, d2, t(30), t(40))); - regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), author, now(), 2, c2, d2, t(10), t(20))); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), now(), author, 0, 0, c1, d1, t(0), t(10))); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), now(), author, 1, 0, c1, d2, t(30), t(40))); + regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 2, c2, d2, t(10), t(20))); // and one for same item (competitor) in other log - regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), author, now(), 3, c1, d1, t(10), + regattaLog.add(new RegattaLogDeviceCompetitorMappingEventImpl(now(), now(), author, 3, c1, d1, t(10), t(20))); Map>> result = new MultiLogAnalyzer<>( diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/DependentRaceStateTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/DependentRaceStateTest.java index 534c6fcfbb5..29472750181 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/DependentRaceStateTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/DependentRaceStateTest.java @@ -11,7 +11,6 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; @@ -27,6 +26,7 @@ import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl.Racing import com.sap.sailing.domain.base.configuration.ConfigurationLoader; import com.sap.sailing.domain.base.configuration.RegattaConfiguration; import com.sap.sailing.domain.base.configuration.impl.EmptyRegattaConfiguration; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -46,17 +46,15 @@ public class DependentRaceStateTest { private RaceStateChangedListener listenerC; private AbstractLogEventAuthor author; - private RaceLogEventFactory factory; private ConfigurationLoader configuration; private TimePoint nowMock; - + private RaceLogResolver raceLogResolver; @Before public void setUp() { author = new LogEventAuthorImpl("Test", 1); - factory = RaceLogEventFactory.INSTANCE; configuration = new EmptyRegattaConfiguration(); raceLogA = new RaceLogImpl("raceLogA"); @@ -82,12 +80,12 @@ public class DependentRaceStateTest { } }; - stateA = new RaceStateImpl(raceLogResolver, raceLogA, author, factory, new RacingProcedureFactoryImpl(author, - factory, configuration)); - stateB = new RaceStateImpl(raceLogResolver, raceLogB, author, factory, new RacingProcedureFactoryImpl(author, - factory, configuration)); - stateC = new RaceStateImpl(raceLogResolver, raceLogC, author, factory, new RacingProcedureFactoryImpl(author, - factory, configuration)); + stateA = new RaceStateImpl(raceLogResolver, raceLogA, author, new RacingProcedureFactoryImpl(author, + configuration)); + stateB = new RaceStateImpl(raceLogResolver, raceLogB, author, new RacingProcedureFactoryImpl(author, + configuration)); + stateC = new RaceStateImpl(raceLogResolver, raceLogC, author, new RacingProcedureFactoryImpl(author, + configuration)); stateA.addChangedListener(listenerA); stateB.addChangedListener(listenerB); @@ -96,27 +94,27 @@ public class DependentRaceStateTest { @Test public void testCorrectAmountOfStartTimeChanges() { - raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000))); + raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000), RaceLogRaceStatus.SCHEDULED)); - raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000))); - - TimePoint now = MillisecondsTimePoint.now(); - raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000))); - - verify(listenerC, times(3)).onStartTimeChanged(stateC); - verify(listenerB, times(2)).onStartTimeChanged(stateB); - verify(listenerA, times(1)).onStartTimeChanged(stateA); + raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000), RaceLogRaceStatus.SCHEDULED)); + + TimePoint now = MillisecondsTimePoint.now(); + raceLogA.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(5000), RaceLogRaceStatus.SCHEDULED)); + + verify(listenerC, times(3)).onStartTimeChanged(stateC); + verify(listenerB, times(2)).onStartTimeChanged(stateB); + verify(listenerA, times(1)).onStartTimeChanged(stateA); } @Test public void testInitialRegistrationOfRaceState() { final MillisecondsDurationImpl delta = new MillisecondsDurationImpl(5000); - raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, + raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, 12, new SimpleRaceLogIdentifierImpl("A", "", ""), delta)); - final RaceState stateB2 = new RaceStateImpl(raceLogResolver, raceLogB, author, factory, - new RacingProcedureFactoryImpl(author, factory, configuration)); + final RaceState stateB2 = new RaceStateImpl(raceLogResolver, raceLogB, author, new RacingProcedureFactoryImpl( + author, configuration)); final TimePoint[] bTime = new TimePoint[1]; stateB2.addChangedListener(new BaseRaceStateChangedListener() { @Override @@ -125,25 +123,25 @@ public class DependentRaceStateTest { } }); TimePoint now = MillisecondsTimePoint.now(); - raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, now)); + raceLogA.add(new RaceLogStartTimeEventImpl(now, author, 12, now)); assertEquals(now.plus(delta), bTime[0]); - } + } @Test public void testCorrectAmountOfStartTimeChanges2() { - raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000))); + raceLogC.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("B", "", ""), new MillisecondsDurationImpl(5000), RaceLogRaceStatus.SCHEDULED)); - raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, author, nowMock, "12", null, 12, - new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000))); - - TimePoint now = MillisecondsTimePoint.now(); - raceLogA.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(5000))); - - raceLogB.add(new RaceLogStartTimeEventImpl(now, author, now, "12", null, 12, new MillisecondsTimePoint(20000))); - - verify(listenerA, times(1)).onStartTimeChanged(stateA); - verify(listenerB, times(3)).onStartTimeChanged(stateB); - verify(listenerC, times(4)).onStartTimeChanged(stateC); + raceLogB.add(new RaceLogDependentStartTimeEventImpl(nowMock, nowMock, author, "12", 12, + new SimpleRaceLogIdentifierImpl("A", "", ""), new MillisecondsDurationImpl(5000), RaceLogRaceStatus.SCHEDULED)); + + TimePoint now = MillisecondsTimePoint.now(); + raceLogA.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(5000), RaceLogRaceStatus.SCHEDULED)); + + raceLogB.add(new RaceLogStartTimeEventImpl(now, now, author, "12", 12, new MillisecondsTimePoint(20000), RaceLogRaceStatus.SCHEDULED)); + + verify(listenerA, times(1)).onStartTimeChanged(stateA); + verify(listenerB, times(3)).onStartTimeChanged(stateB); + verify(listenerC, times(4)).onStartTimeChanged(stateC); } } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/RaceStateTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/RaceStateTest.java index 99937e4f81a..6d53331d754 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/RaceStateTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/state/test/RaceStateTest.java @@ -19,7 +19,6 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; @@ -48,7 +47,6 @@ public class RaceStateTest { private RaceLog raceLog; private AbstractLogEventAuthor author; - private RaceLogEventFactory factory; private RacingProcedureType defaultRacingProcedureType; private ConfigurationLoader configuration; private RaceStateChangedListener listener; @@ -60,13 +58,12 @@ public class RaceStateTest { public void setUp() { raceLog = new RaceLogImpl("test-log"); author = new LogEventAuthorImpl("Test", 1); - factory = RaceLogEventFactory.INSTANCE; defaultRacingProcedureType = RacingProcedureType.RRS26; configuration = new EmptyRegattaConfiguration(); listener = mock(RaceStateChangedListener.class); nowMock = mock(TimePoint.class); - state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration)); + state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, new RacingProcedureFactoryImpl(author, configuration)); } @Test @@ -96,7 +93,7 @@ public class RaceStateTest { config.setBasicConfiguration(mock(RacingProcedureConfiguration.class)); configuration = mock(ConfigurationLoader.class); when(configuration.load()).thenReturn(config); - state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration)); + state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, new RacingProcedureFactoryImpl(author, configuration)); assertEquals(RacingProcedureType.BASIC, state.getRacingProcedure().getType()); } @@ -110,8 +107,8 @@ public class RaceStateTest { config.setESSConfiguration(mock(ESSConfiguration.class)); configuration = mock(ConfigurationLoader.class); when(configuration.load()).thenReturn(config); - raceLog.add(new RaceLogStartProcedureChangedEventImpl(nowMock, author, nowMock, "12", null, 0, RacingProcedureType.ESS)); - state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, factory, new RacingProcedureFactoryImpl(author, factory, configuration)); + raceLog.add(new RaceLogStartProcedureChangedEventImpl(nowMock, nowMock, author, "12", 0, RacingProcedureType.ESS)); + state = new RaceStateImpl(mock(RaceLogResolver.class), raceLog, author, new RacingProcedureFactoryImpl(author, configuration)); assertEquals(RacingProcedureType.ESS, state.getRacingProcedure().getType()); } @@ -136,8 +133,8 @@ public class RaceStateTest { @Test public void testSetIndividualRecall() { assertFalse(state.getRacingProcedure().isIndividualRecallDisplayed()); - raceLog.add(new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID - .randomUUID(), null, /* pass */0, Flags.XRAY, Flags.NONE, /* pIsDisplayed */true)); + raceLog.add(new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID + .randomUUID(), /* pass */0, Flags.XRAY, Flags.NONE, /* pIsDisplayed */true)); assertTrue(state.getRacingProcedure().isIndividualRecallDisplayed()); } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogEventImplTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogEventImplTest.java index 91b10656b99..ecb4cf09cb5 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogEventImplTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogEventImplTest.java @@ -30,7 +30,7 @@ public class RaceLogEventImplTest { public TestRaceLogEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, List pInvolvedBoats, int pPassId) { - super(createdAt, author, logicalTimePoint, pId, pInvolvedBoats, pPassId); + super(createdAt, logicalTimePoint, author, pId, pInvolvedBoats, pPassId); } @Override diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogRevocationTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogRevocationTest.java index 895ab6a854c..b6a6612727b 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogRevocationTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogRevocationTest.java @@ -14,10 +14,10 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -107,7 +107,7 @@ public class RaceLogRevocationTest { @Test public void sameEventRevokedByTwoClientsBeforeSync() throws NotRevokableException { - RaceLogDenoteForTrackingEvent event = RaceLogEventFactory.INSTANCE.createDenoteForTrackingEvent( + RaceLogDenoteForTrackingEvent event = new RaceLogDenoteForTrackingEventImpl( now(), serverAuthor, 0, "race", null, null); serverRaceLog.add(event); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java index 361816d7068..6d0b270353a 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/RaceLogTest.java @@ -23,12 +23,12 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -40,8 +40,8 @@ public class RaceLogTest { private static class MockRaceLogEventForSorting extends RaceLogEventImpl { public MockRaceLogEventForSorting(long createdAtMillis) { super(new MillisecondsTimePoint(createdAtMillis), - /* author */ new LogEventAuthorImpl("Dummy Author", /* priority */ 0), - MillisecondsTimePoint.now(), /* ID */ UUID.randomUUID(), /* pInvolvedBoats */ null, /* pass ID */ 1); + MillisecondsTimePoint.now(), + /* author */ new LogEventAuthorImpl("Dummy Author", /* priority */ 0), /* ID */ UUID.randomUUID(), /* pInvolvedBoats */ null, /* pass ID */ 1); } private static final long serialVersionUID = 4928452859543831451L; @@ -433,14 +433,14 @@ public class RaceLogTest { UUID client1Id = UUID.randomUUID(); UUID client2Id = UUID.randomUUID(); final TimePoint now = MillisecondsTimePoint.now(); - RaceLogStartTimeEvent startTimeEvent1 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 1, now.plus(1)); + RaceLogStartTimeEvent startTimeEvent1 = new RaceLogStartTimeEventImpl(now, author, 1, now.plus(1)); Iterable empty = raceLog.add(startTimeEvent1, client1Id); assertTrue(Util.isEmpty(empty)); - RaceLogStartTimeEvent startTimeEvent2 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now.plus(2), author, 1, now.plus(3)); + RaceLogStartTimeEvent startTimeEvent2 = new RaceLogStartTimeEventImpl(now.plus(2), author, 1, now.plus(3)); Iterable nonEmpty = raceLog.add(startTimeEvent2, client2Id); assertEquals(1, Util.size(nonEmpty)); assertSame(startTimeEvent1, nonEmpty.iterator().next()); - RaceLogStartTimeEvent startTimeEvent3 = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now.plus(4), author, 1, now.plus(5)); + RaceLogStartTimeEvent startTimeEvent3 = new RaceLogStartTimeEventImpl(now.plus(4), author, 1, now.plus(5)); Iterable nonEmpty2 = raceLog.add(startTimeEvent3, client1Id); assertEquals(1, Util.size(nonEmpty2)); assertSame(startTimeEvent2, nonEmpty2.iterator().next()); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/SerializeRaceLogEventsTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/SerializeRaceLogEventsTest.java index 035e393f9c7..b2bc042d036 100755 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/SerializeRaceLogEventsTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/test/SerializeRaceLogEventsTest.java @@ -13,10 +13,11 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.racelog.tracking.test.mock.SmartphoneImeiIdentifier; import com.sap.sailing.domain.test.AbstractLeaderboardTest; import com.sap.sse.common.Util; @@ -32,14 +33,12 @@ public class SerializeRaceLogEventsTest { private ObjectOutputStream oos; private ByteArrayOutputStream bos; private RaceLog raceLog; - private RaceLogEventFactory eventFactory; @Before public void setUp() throws IOException { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); raceLog = new RaceLogImpl("Test Race Log"); - eventFactory = RaceLogEventFactory.INSTANCE; } @Test @@ -59,7 +58,7 @@ public class SerializeRaceLogEventsTest { @Test public void testRaceLogSerializationWithSingleEvent() throws IOException, ClassNotFoundException { - RaceLogStartTimeEvent startTimeEvent = eventFactory.createStartTimeEvent(MillisecondsTimePoint.now(), + RaceLogStartTimeEvent startTimeEvent = new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Author Name", /* priority */0), /* passId */1, /* startTime */ MillisecondsTimePoint.now()); raceLog.add(startTimeEvent); @@ -79,9 +78,9 @@ public class SerializeRaceLogEventsTest { @Test public void testRaceLogSerializationWithEventContainingDeviceIdentifier() throws IOException, ClassNotFoundException { - RaceLogDeviceCompetitorMappingEvent mappingEvent = eventFactory.createDeviceCompetitorMappingEvent( - MillisecondsTimePoint.now(), new LogEventAuthorImpl("Author Name", /* priority */0), new SmartphoneImeiIdentifier("1948364938463903"), - AbstractLeaderboardTest.createCompetitor("Test Competitor"), 0, new MillisecondsTimePoint(0), new MillisecondsTimePoint(10)); + RaceLogDeviceCompetitorMappingEvent mappingEvent = new RaceLogDeviceCompetitorMappingEventImpl( + MillisecondsTimePoint.now(), new LogEventAuthorImpl("Author Name", /* priority */0), 0, + AbstractLeaderboardTest.createCompetitor("Test Competitor"), new SmartphoneImeiIdentifier("1948364938463903"), new MillisecondsTimePoint(0), new MillisecondsTimePoint(10)); raceLog.add(mappingEvent); oos.writeObject(raceLog); ObjectInputStream ois = getObjectInputStream(); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/AbstractRaceLogTrackingTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/AbstractRaceLogTrackingTest.java index 251fa779f10..2235f824acd 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/AbstractRaceLogTrackingTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/AbstractRaceLogTrackingTest.java @@ -5,7 +5,6 @@ import org.junit.Before; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -17,7 +16,6 @@ public abstract class AbstractRaceLogTrackingTest { protected final AbstractLogEventAuthor author1 = new LogEventAuthorImpl("author1", 1); protected final TimePoint now = MillisecondsTimePoint.now(); - protected final RaceLogEventRestoreFactory factory = RaceLogEventRestoreFactory.INSTANCE; public AbstractRaceLogTrackingTest() { super(); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java index bef31f43e99..212503f37c7 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java @@ -12,6 +12,8 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.impl.CompetitorImpl; @@ -41,14 +43,14 @@ public class DeviceMappingFinderTest extends AbstractRaceLogTrackingTest { } private Serializable addMapping(AbstractLogEventAuthor author, DeviceIdentifier device, Long from, Long to, Competitor item) { - RaceLogEvent mapping = factory.createDeviceCompetitorMappingEvent(t(), author, t(), UUID.randomUUID(), device, item, 0, + RaceLogEvent mapping = new RaceLogDeviceCompetitorMappingEventImpl(t(), t(), author, UUID.randomUUID(), 0, item, device, t(from), t(to)); log.add(mapping); return mapping.getId(); } private void closeMapping(AbstractLogEventAuthor author, DeviceIdentifier device, Serializable mappingId, long millis) { - RaceLogEvent mapping = factory.createCloseOpenEndedDeviceMappingEvent(t(), author, t(), UUID.randomUUID(), 0, mappingId, + RaceLogEvent mapping = new RaceLogCloseOpenEndedDeviceMappingEventImpl(t(), t(), author, UUID.randomUUID(), 0, mappingId, new MillisecondsTimePoint(millis)); log.add(mapping); } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/RevokeEventTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/RevokeEventTest.java index 6344333f059..c3d00398143 100644 --- a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/RevokeEventTest.java +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/RevokeEventTest.java @@ -8,13 +8,15 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; import com.sap.sse.common.Util; public class RevokeEventTest extends AbstractRaceLogTrackingTest { @Test public void revokedEventIsExcluded() { - RaceLogEvent event = factory.createDeviceCompetitorMappingEvent(now, author, now, UUID.randomUUID(), null, null, 0, null, null); - RaceLogRevokeEvent revokeEvent = factory.createRevokeEvent(now.plus(1), author, now.plus(1), UUID.randomUUID(), 0, event.getId(), + RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null); + RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), 0, event.getId(), null, null, null); log.add(event); @@ -27,8 +29,8 @@ public class RevokeEventTest extends AbstractRaceLogTrackingTest { @Test public void eventRevokedByAuthorWithLowerPrioIsNotExcluded() { - RaceLogEvent event = factory.createDeviceCompetitorMappingEvent(now, author, now, UUID.randomUUID(), null, null, 0, null, null); - RaceLogRevokeEvent revokeEvent = factory.createRevokeEvent(now.plus(1), author1, now.plus(1), UUID.randomUUID(), 0, event.getId(), + RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null); + RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author1, UUID.randomUUID(), 0, event.getId(), null, null, null); log.add(event); @@ -41,10 +43,10 @@ public class RevokeEventTest extends AbstractRaceLogTrackingTest { @Test public void revokingRevokeEventIsNotHarmful() { - RaceLogEvent event = factory.createDeviceCompetitorMappingEvent(now, author, now, UUID.randomUUID(), null, null, 0, null, null); - RaceLogRevokeEvent revokeEvent = factory.createRevokeEvent(now.plus(1), author, now.plus(1), UUID.randomUUID(), 0, event.getId(), + RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), 0, null, null, null, null); + RaceLogRevokeEvent revokeEvent = new RaceLogRevokeEventImpl(now.plus(1), now.plus(1), author, UUID.randomUUID(), 0, event.getId(), null, null, null); - RaceLogRevokeEvent revokeEvent2 = factory.createRevokeEvent(now.plus(2), author, now.plus(2), UUID.randomUUID(), 2, revokeEvent.getId(), + RaceLogRevokeEvent revokeEvent2 = new RaceLogRevokeEventImpl(now.plus(2), now.plus(2), author, UUID.randomUUID(), 2, revokeEvent.getId(), null, null, null); log.add(event); diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailinig/domain/based/impl/BoatClassCacheTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailinig/domain/based/impl/BoatClassCacheTest.java new file mode 100644 index 00000000000..c54e6d663ad --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailinig/domain/based/impl/BoatClassCacheTest.java @@ -0,0 +1,75 @@ +package com.sap.sailinig.domain.based.impl; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.SharedDomainFactory; +import com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl; +import com.sap.sailing.domain.common.BoatClassMasterdata; + +/** + * Tests creation and caching of boat classes. See also bug 3347 + * (http://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3347). + * + * @author Axel Uhl (d043530) + * + */ +public class BoatClassCacheTest { + private SharedDomainFactory sharedDomainFactory; + + @Before + public void setUp() { + sharedDomainFactory = new SharedDomainFactoryImpl(/* raceLogResolver */ null); + } + + @Test + public void testQueryingBoatClassByDisplayNameFirstThenCanonicalizedAlternativeName() { + final BoatClassMasterdata laserMasterData = BoatClassMasterdata.LASER_INT; + final String laserAlternativeName = laserMasterData.getAlternativeNames()[0]; + final String unifiedAlternativeName = BoatClassMasterdata.unifyBoatClassName(laserAlternativeName); + final BoatClass laserByDisplayName = sharedDomainFactory.getOrCreateBoatClass(laserMasterData.getDisplayName()); + final BoatClass laserByUnifiedAlternativeName = sharedDomainFactory.getOrCreateBoatClass(unifiedAlternativeName); + assertSame(laserByDisplayName, laserByUnifiedAlternativeName); + } + + @Test + public void testQueryingBoatClassByAlternativeNameFirstThenCanonicalizedDisplayName() { + final BoatClassMasterdata laserMasterData = BoatClassMasterdata.LASER_INT; + final String laserAlternativeName = laserMasterData.getAlternativeNames()[0]; + final BoatClass laserByAlternativeName = sharedDomainFactory.getOrCreateBoatClass(laserAlternativeName); + final String unifiedDisplayName = BoatClassMasterdata.unifyBoatClassName(laserMasterData.getDisplayName()); + final BoatClass laserByUnifiedDisplayName = sharedDomainFactory.getOrCreateBoatClass(unifiedDisplayName); + assertSame(laserByAlternativeName, laserByUnifiedDisplayName); + } + + @Test + public void testQueryingBoatClassByDisplayNameFirstThenCanonicalizedDisplayName() { + final BoatClassMasterdata laserMasterData = BoatClassMasterdata.LASER_INT; + final BoatClass laserByDisplayName = sharedDomainFactory.getOrCreateBoatClass(laserMasterData.getDisplayName()); + final String unifiedDisplayName = BoatClassMasterdata.unifyBoatClassName(laserMasterData.getDisplayName()); + final BoatClass laserByUnifiedDisplayName = sharedDomainFactory.getOrCreateBoatClass(unifiedDisplayName); + assertSame(laserByDisplayName, laserByUnifiedDisplayName); + } + + @Test + public void testQueryingBoatClassByAlternativeNameFirstThenCanonicalizedAlternativeName() { + final BoatClassMasterdata laserMasterData = BoatClassMasterdata.LASER_INT; + final String laserAlternativeName = laserMasterData.getAlternativeNames()[0]; + final BoatClass laserByAlternativeName = sharedDomainFactory.getOrCreateBoatClass(laserAlternativeName); + final String unifiedAlternativeName = BoatClassMasterdata.unifyBoatClassName(laserAlternativeName); + final BoatClass laserByUnifiedAlternativeName = sharedDomainFactory.getOrCreateBoatClass(unifiedAlternativeName); + assertSame(laserByAlternativeName, laserByUnifiedAlternativeName); + } + + @Test + public void testEssMayHaveNonUpwindStart() { + for (final String boatClassName : new String[] { "extreme40", "ess", "ess40" }) { + final BoatClass ess40 = sharedDomainFactory.getOrCreateBoatClass(boatClassName); + assertFalse("Boat class "+boatClassName+" expected to allow for non-upwind starts", ess40.typicallyStartsUpwind()); + } + } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/AbstractLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/AbstractLogEventImpl.java index d6e50866d1c..7c6595e1eb5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/AbstractLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/AbstractLogEventImpl.java @@ -1,10 +1,12 @@ package com.sap.sailing.domain.abstractlog.impl; import java.io.Serializable; +import java.util.UUID; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; public abstract class AbstractLogEventImpl implements AbstractLogEvent { @@ -15,13 +17,27 @@ public abstract class AbstractLogEventImpl implements AbstractLogEvent private final Serializable id; private final AbstractLogEventAuthor author; - public AbstractLogEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public AbstractLogEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId) { this.createdAt = createdAt; this.author = author; this.logicalTimePoint = logicalTimePoint; this.id = pId; } + + /** + * To be used by constructors creating new events as the value for {@link #createdAt}. + */ + protected static final TimePoint now() { + return MillisecondsTimePoint.now(); + } + + /** + * To be used by constructors creating new events as the value for {@link #id}. + */ + protected static final Serializable randId() { + return UUID.randomUUID(); + } @Override public TimePoint getCreatedAt() { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/RevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/RevokeEventImpl.java index 57aa58e9890..8bc9a637983 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/RevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/impl/RevokeEventImpl.java @@ -18,14 +18,14 @@ public abstract class RevokeEventImpl extends AbstractLogEventImpl toRevoke, String reason) { - this(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), + this(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), toRevoke.getId(), toRevoke.getClass().getName(), toRevoke.getShortInfo(), reason); } - public RevokeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public RevokeEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Serializable revokedEventId, String revokedEventType, String revokedEventShortInfo, String reason) { - super(createdAt, author, logicalTimePoint, pId); + super(createdAt, logicalTimePoint, author, pId); this.revokedEventId = revokedEventId; this.reason = reason; this.revokedEventType = revokedEventType; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventFactory.java deleted file mode 100644 index dd6c9169caf..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventFactory.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race; - -import java.io.Serializable; -import java.util.List; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventFactoryImpl; -import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; - -public interface RaceLogEventFactory { - RaceLogEventFactory INSTANCE = new RaceLogEventFactoryImpl(); - - RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, List involvedBoats, - int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed); - - RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, Flags upperFlag, - Flags lowerFlag, boolean isDisplayed); - - RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List involvedBoats, int passId, TimePoint startTime); - - RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, TimePoint startTime); - - RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, int passId, RaceLogRaceStatus nextStatus); - - RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, RaceLogRaceStatus nextStatus); - - RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, int passId); - - RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId); - - RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, Serializable courseAreaId); - - RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Serializable courseAreaId); - - RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, CourseBase courseData); - - RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, CourseBase courseData); - - RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, List competitors, - int passId, CompetitorResults positionedCompetitors); - - RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, CompetitorResults positionedCompetitors); - - RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, CompetitorResults positionedCompetitors); - - RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, CompetitorResults positionedCompetitors); - - RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, int passId, String pathfinderId); - - RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, String pathfinderId); - - RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, Long gateLaunchStopTime, Long golfDownTime); - - RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Long gateLaunchStopTime, Long golfDownTime); - - RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, RacingProcedureType type); - - RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, RacingProcedureType type); - - RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, TimePoint protestStartTime); - - RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, TimePoint protestStartTime); - - RaceLogWindFixEvent createWindFixEvent(TimePoint eventTime, AbstractLogEventAuthor author, int currentPassId, Wind wind, boolean isMagnetic); - - RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, Wind wind, boolean isMagnetic); - - RaceLogDeviceCompetitorMappingEvent createDeviceCompetitorMappingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - DeviceIdentifier device, Competitor mappedTo, int passId, TimePoint from, TimePoint to); - - RaceLogDeviceMarkMappingEvent createDeviceMarkMappingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - DeviceIdentifier device, Mark mappedTo, int passId, TimePoint from, TimePoint to); - - RaceLogDenoteForTrackingEvent createDenoteForTrackingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, - String raceName, BoatClass boatClass, Serializable raceId); - - RaceLogStartTrackingEvent createStartTrackingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId); - - RaceLogRevokeEvent createRevokeEvent(AbstractLogEventAuthor author, int passId, RaceLogEvent toRevoke, String reason); - - RaceLogRegisterCompetitorEvent createRegisterCompetitorEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, Competitor competitor); - - RaceLogDefineMarkEvent createDefineMarkEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, Mark mark); - - RaceLogCloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, - Serializable deviceMappingEventId, TimePoint closingTimePoint); - - RaceLogFixedMarkPassingEvent createFixedMarkPassingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, Integer passId, TimePoint ofFixedPassing, Integer zeroBasedIndexOfWaypoint); - - RaceLogAdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint timePoint, Serializable id, AbstractLogEventAuthor author, int currentPassId, - AdditionalScoringInformationType informationType); - - RaceLogSuppressedMarkPassingsEvent createSuppressedMarkPassingsEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, Integer passId, Integer zeroBasedIndexOfFirstSuppressedWaypoint); - - RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, List involvedBoats, int passId, SimpleRaceLogIdentifier dependentOnRace, - Duration startTimeDifference); - - RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference); - - RaceLogStartOfTrackingEvent createStartOfTrackingEvent(TimePoint startOfTracking, AbstractLogEventAuthor author, - Serializable id, List competitors, Integer passId); - - RaceLogEndOfTrackingEvent createEndOfTrackingEvent(TimePoint endOfTracking, AbstractLogEventAuthor author, - Serializable id, List competitors, Integer passId); - - -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventRestoreFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventRestoreFactory.java deleted file mode 100644 index 1219911d501..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/RaceLogEventRestoreFactory.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race; - -import java.io.Serializable; -import java.util.List; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventRestoreFactoryImpl; -import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; - -public interface RaceLogEventRestoreFactory extends RaceLogEventFactory { - RaceLogEventRestoreFactory INSTANCE = new RaceLogEventRestoreFactoryImpl(); - - RaceLogFlagEvent createFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed); - - RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List involvedBoats, int passId, TimePoint startTime, RaceLogRaceStatus nextStatue); - - RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List competitors, int passId, RaceLogRaceStatus nextStatus); - - RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List competitors, int passId); - - RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, Serializable courseAreaId); - - RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, CourseBase courseData); - - RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List competitors, - int passId, CompetitorResults positionedCompetitors); - - RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List competitors, - int passId, CompetitorResults positionedCompetitors); - - RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List competitors, int passId, String pathfinderId); - - RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, Long gateLaunchStopTime, - Long golfDownTime); - - RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, RacingProcedureType type); - - RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, TimePoint protestStartTime); - - RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List competitors, Integer passId, Wind wind, boolean isMagnetic); - - RaceLogDeviceCompetitorMappingEvent createDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, DeviceIdentifier device, Competitor mappedTo, int passId, TimePoint from, TimePoint to); - - RaceLogDeviceMarkMappingEvent createDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, DeviceIdentifier device, Mark mappedTo, int passId, TimePoint from, TimePoint to); - - RaceLogDenoteForTrackingEvent createDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, String raceName, BoatClass boatClass, Serializable raceId); - - RaceLogStartTrackingEvent createStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId); - - RaceLogRevokeEvent createRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, Serializable revokedEventId, - String revokedEventType, String revokedEventShortInfo, String reason); - - RaceLogRegisterCompetitorEvent createRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, Competitor competitor); - - RaceLogDefineMarkEvent createDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, Mark mark); - - RaceLogCloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint); - - RaceLogAdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, List competitors, int passId, - AdditionalScoringInformationType informationType); - - RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List involvedBoats, int passId, - SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference, RaceLogRaceStatus nextStatus); -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java index edfc7a1d45a..e5ead97f468 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/analyzing/impl/MarkPassingDataFinder.java @@ -3,9 +3,9 @@ package com.sap.sailing.domain.abstractlog.race.analyzing.impl; import java.util.HashSet; import java.util.Set; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java index f0aed5f9999..1c9038da9a5 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/BaseRaceLogEventVisitor.java @@ -1,13 +1,13 @@ package com.sap.sailing.domain.abstractlog.race.impl; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; @@ -18,8 +18,8 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseAreaChangeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseAreaChangeEventImpl.java index c56772b5540..3f0074c24cd 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseAreaChangeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseAreaChangeEventImpl.java @@ -1,26 +1,28 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogCourseAreaChangeEventImpl extends RaceLogEventImpl implements -RaceLogCourseAreaChangedEvent { +public class RaceLogCourseAreaChangeEventImpl extends RaceLogEventImpl implements RaceLogCourseAreaChangedEvent { private static final long serialVersionUID = -3943108136024977860L; private final Serializable courseAreaId; - public RaceLogCourseAreaChangeEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pInvolvedBoats, int pPassId, Serializable courseAreaId) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogCourseAreaChangeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, Serializable courseAreaId) { + super(createdAt, pTimePoint, author, pId, pPassId); this.courseAreaId = courseAreaId; } + public RaceLogCourseAreaChangeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + Serializable courseAreaId) { + this(now(), logicalTimePoint, author, randId(), pPassId, courseAreaId); + } + @Override public Serializable getCourseAreaId() { return courseAreaId; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseDesignChangedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseDesignChangedEventImpl.java index 5fd11a31252..c295cf8d891 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseDesignChangedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogCourseDesignChangedEventImpl.java @@ -1,26 +1,30 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; import com.sap.sse.common.TimePoint; public class RaceLogCourseDesignChangedEventImpl extends RaceLogEventImpl implements RaceLogCourseDesignChangedEvent { private static final long serialVersionUID = 1565936170747420547L; - + private final CourseBase courseDesign; - public RaceLogCourseDesignChangedEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pInvolvedBoats, int pPassId, CourseBase courseDesign) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogCourseDesignChangedEventImpl(TimePoint createdAt, TimePoint pTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, + CourseBase courseDesign) { + super(createdAt, pTimePoint, author, pId, pPassId); this.courseDesign = courseDesign; } + public RaceLogCourseDesignChangedEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + CourseBase courseDesign) { + this(now(), logicalTimePoint, author, randId(), pPassId, courseDesign); + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogDependentStartTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogDependentStartTimeEventImpl.java index 8b082d54dce..a2038c91ffb 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogDependentStartTimeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogDependentStartTimeEventImpl.java @@ -1,32 +1,36 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; -public class RaceLogDependentStartTimeEventImpl extends RaceLogRaceStatusEventImpl implements RaceLogDependentStartTimeEvent, Revokable { +public class RaceLogDependentStartTimeEventImpl extends RaceLogRaceStatusEventImpl implements + RaceLogDependentStartTimeEvent, Revokable { private static final long serialVersionUID = -2555082771473210123L; private final Duration startTimeDifference; private SimpleRaceLogIdentifier dependentOnRace; - public RaceLogDependentStartTimeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, SimpleRaceLogIdentifier dependentOnRace, - Duration startTimeDifference) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId, RaceLogRaceStatus.SCHEDULED); + public RaceLogDependentStartTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, SimpleRaceLogIdentifier dependentOnRace, + Duration startTimeDifference, RaceLogRaceStatus nextStatus) { + super(createdAt, pTimePoint, author, pId, pPassId, nextStatus); this.dependentOnRace = dependentOnRace; this.startTimeDifference = startTimeDifference; } + public RaceLogDependentStartTimeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference) { + this(now(), logicalTimePoint, author, randId(), pPassId, dependentOnRace, startTimeDifference, RaceLogRaceStatus.SCHEDULED); + } + @Override public Duration getStartTimeDifference() { return startTimeDifference; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEndOfTrackingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEndOfTrackingEventImpl.java index 054933cba7b..29eb91d36c1 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEndOfTrackingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEndOfTrackingEventImpl.java @@ -1,31 +1,32 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogEndOfTrackingEventImpl extends RaceLogEventImpl implements RaceLogEndOfTrackingEvent { private static final long serialVersionUID = 3130293807404190473L; - public RaceLogEndOfTrackingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint endOfTracking, Serializable pId, List pInvolvedBoats, int pPassId) { - super(createdAt, author, endOfTracking, pId, pInvolvedBoats, pPassId); + public RaceLogEndOfTrackingEventImpl(TimePoint createdAt, TimePoint endOfTracking, AbstractLogEventAuthor author, + Serializable pId, int pPassId) { + super(createdAt, endOfTracking, author, pId, pPassId); + } + public RaceLogEndOfTrackingEventImpl(TimePoint endOfTracking, AbstractLogEventAuthor author, int pPassId) { + super(endOfTracking, author, pPassId); } @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } - + @Override public String getShortInfo() { return "endOfTrackingTime=" + getLogicalTimePoint(); } - + } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventFactoryImpl.java deleted file mode 100644 index ff3b35d6a20..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventFactoryImpl.java +++ /dev/null @@ -1,329 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race.impl; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.CompetitorResults; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -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.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; -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.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class RaceLogEventFactoryImpl implements RaceLogEventFactory { - - @Override - public RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) { - return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, involvedBoats, passId, - upperFlag, lowerFlag, isDisplayed); - } - - @Override - public RaceLogFlagEvent createFlagEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, Flags upperFlag, - Flags lowerFlag, boolean isDisplayed) { - return createFlagEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, upperFlag, - lowerFlag, isDisplayed); - } - - @Override - public RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List involvedBoats, int passId, TimePoint startTime) { - return new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, involvedBoats, - passId, startTime); - } - - @Override - public RaceLogStartTimeEvent createStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, TimePoint startTime) { - return createStartTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, startTime); - } - - @Override - public RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List involvedBoats, int passId, SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference) { - return new RaceLogDependentStartTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, involvedBoats, - passId, dependentOnRace, startTimeDifference); - } - - @Override - public RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference) { - return createDependentStartTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, - dependentOnRace, startTimeDifference); - } - - @Override - public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, RaceLogRaceStatus nextStatus) { - return new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, - passId, nextStatus); - } - - @Override - public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, RaceLogRaceStatus nextStatus) { - return createRaceStatusEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, nextStatus); - } - - @Override - public RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId) { - return new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId); - } - - @Override - public RaceLogPassChangeEvent createPassChangeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { - return createPassChangeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId); - } - - @Override - public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, Serializable courseAreaId) { - return new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, - passId, courseAreaId); - } - - @Override - public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Serializable courseAreaId) { - return createCourseAreaChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), - passId, courseAreaId); - } - - @Override - public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, CourseBase courseData) { - return new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, - passId, courseData); - } - - @Override - public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, CourseBase courseData) { - return createCourseDesignChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), - passId, courseData); - } - - @Override - public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, List competitors, - int passId, CompetitorResults positionedCompetitors) { - return new RaceLogFinishPositioningListChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, - id, competitors, passId, positionedCompetitors); - } - - @Override - public RaceLogFinishPositioningListChangedEventImpl createFinishPositioningListChangedEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, CompetitorResults positionedCompetitors) { - return createFinishPositioningListChangedEvent(logicalTimePoint, author, UUID.randomUUID(), - new ArrayList(), passId, positionedCompetitors); - } - - @Override - public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable id, List competitors, int passId, CompetitorResults positionedCompetitors) { - return new RaceLogFinishPositioningConfirmedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, - competitors, passId, positionedCompetitors); - } - - @Override - public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, CompetitorResults positionedCompetitors) { - return createFinishPositioningConfirmedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, positionedCompetitors); - } - - @Override - public RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, String pathfinderId) { - return new RaceLogPathfinderEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, - passId, pathfinderId); - } - - @Override - public RaceLogPathfinderEvent createPathfinderEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, String pathfinderId) { - return createPathfinderEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, pathfinderId); - } - - @Override - public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, Long gateLaunchStopTime, Long golfDownTime) { - return new RaceLogGateLineOpeningTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, - passId, gateLaunchStopTime, golfDownTime); - } - - @Override - public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Long gateLaunchStopTime, Long golfDownTime) { - return createGateLineOpeningTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), - passId, gateLaunchStopTime, golfDownTime); - } - - @Override - public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, RacingProcedureType type) { - return new RaceLogStartProcedureChangedEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, - competitors, passId, type); - } - - @Override - public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, RacingProcedureType type) { - return createStartProcedureChangedEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, type); - } - - @Override - public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, int passId, TimePoint protestStartTime) { - return new RaceLogProtestStartTimeEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, - competitors, passId, protestStartTime); - } - - @Override - public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, TimePoint protestStartTime) { - return createProtestStartTimeEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), - passId, protestStartTime); - } - - @Override - public RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, Wind wind, boolean isMagnetic) { - return createWindFixEvent(logicalTimePoint, author, UUID.randomUUID(), new ArrayList(), passId, wind, isMagnetic); - } - - @Override - public RaceLogWindFixEvent createWindFixEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, int passId, Wind wind, boolean isMagnetic) { - return new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId, wind, isMagnetic); - } - - @Override - public RaceLogDeviceCompetitorMappingEvent createDeviceCompetitorMappingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - DeviceIdentifier device, Competitor mappedTo, int passId, TimePoint from, TimePoint to) { - return new RaceLogDeviceCompetitorMappingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), - passId, mappedTo, device, from, to); - } - - @Override - public RaceLogDeviceMarkMappingEvent createDeviceMarkMappingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - DeviceIdentifier device, Mark mappedTo, int passId, TimePoint from, TimePoint to) { - return new RaceLogDeviceMarkMappingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), - passId, mappedTo, device, from, to); - } - - @Override - public RaceLogDenoteForTrackingEvent createDenoteForTrackingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId, - String raceName, BoatClass boatClass, Serializable raceId) { - return new RaceLogDenoteForTrackingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), passId, raceName, - boatClass, raceId); - } - - @Override - public RaceLogStartTrackingEvent createStartTrackingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int passId) { - return new RaceLogStartTrackingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), passId); - } - - @Override - public RaceLogRevokeEvent createRevokeEvent(AbstractLogEventAuthor author, int passId, RaceLogEvent toRevoke, String reason) { - return new RaceLogRevokeEventImpl(author, passId, toRevoke, reason); - } - - @Override - public RaceLogRegisterCompetitorEvent createRegisterCompetitorEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Competitor competitor) { - return new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), passId, competitor); - } - - @Override - public RaceLogDefineMarkEvent createDefineMarkEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - int passId, Mark mark) { - return new RaceLogDefineMarkEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, UUID.randomUUID(), passId, mark); - } - - @Override - public RaceLogCloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint logicalTimePoint, - AbstractLogEventAuthor author, int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint) { - return new RaceLogCloseOpenEndedDeviceMappingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, - UUID.randomUUID(), passId, deviceMappingEventId, closingTimePoint); - } - - @Override - public RaceLogAdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint timePoint, Serializable id, - AbstractLogEventAuthor author, int currentPassId, AdditionalScoringInformationType informationType) { - return new RaceLogAdditionalScoringInformationEventImpl(MillisecondsTimePoint.now(), author, timePoint, id, - Collections. emptyList(), currentPassId, informationType); - } - - @Override - public RaceLogFixedMarkPassingEvent createFixedMarkPassingEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, - Serializable id, List competitors, Integer passId, TimePoint ofFixedPassing, Integer zeroBasedIndexOfWaypoint) { - return new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId, ofFixedPassing, - zeroBasedIndexOfWaypoint); - } - - @Override - public RaceLogSuppressedMarkPassingsEvent createSuppressedMarkPassingsEvent(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable id, - List competitors, Integer passId, Integer zeroBasedIndexOfFirstSuppressedWaypoint) { - return new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), author, logicalTimePoint, id, competitors, passId, - zeroBasedIndexOfFirstSuppressedWaypoint); - } - - @Override - public RaceLogStartOfTrackingEvent createStartOfTrackingEvent(TimePoint startOfTracking, AbstractLogEventAuthor author, Serializable id, - List competitors, Integer passId) { - return new RaceLogStartOfTrackingEventImpl(MillisecondsTimePoint.now(), author, startOfTracking, id, competitors, passId); - } - - @Override - public RaceLogEndOfTrackingEvent createEndOfTrackingEvent(TimePoint endOfTracking, AbstractLogEventAuthor author, Serializable id, - List competitors, Integer passId) { - return new RaceLogEndOfTrackingEventImpl(MillisecondsTimePoint.now(), author, endOfTracking, id, competitors, passId); - } -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java index d3d5ad55d8c..41da8329cb0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventImpl.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; +import java.util.Collections; import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; @@ -15,11 +16,24 @@ public abstract class RaceLogEventImpl extends AbstractLogEventImpl pInvolvedBoats, int pPassId) { - super(createdAt, author, logicalTimePoint, pId); + super(createdAt, logicalTimePoint, author, pId); this.raceLogEventData = new RaceLogEventDataImpl(pInvolvedBoats, pPassId); } + + public RaceLogEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId) { + this(createdAt, logicalTimePoint, author, pId, Collections.emptyList(), pPassId); + } + + public RaceLogEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, Competitor competitor, int pPassId) { + this(now(), logicalTimePoint, author, randId(), Collections.singletonList(competitor), pPassId); + } + + public RaceLogEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId) { + this(now(), logicalTimePoint, author, randId(), Collections.emptyList(), pPassId); + } @Override public List getInvolvedBoats() { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventRestoreFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventRestoreFactoryImpl.java deleted file mode 100644 index 36588de8091..00000000000 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogEventRestoreFactoryImpl.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.sap.sailing.domain.abstractlog.race.impl; - -import java.io.Serializable; -import java.util.List; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.CompetitorResults; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; -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.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; - -public class RaceLogEventRestoreFactoryImpl extends RaceLogEventFactoryImpl implements RaceLogEventRestoreFactory { - - @Override - public RaceLogFlagEvent createFlagEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List involvedBoats, int passId, Flags upperFlag, Flags lowerFlag, boolean isDisplayed) { - return new RaceLogFlagEventImpl(createdAt, author, logicalTimePoint, id, involvedBoats, passId, upperFlag, lowerFlag, isDisplayed); - } - - @Override - public RaceLogStartTimeEvent createStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List involvedBoats, int passId, TimePoint startTime, RaceLogRaceStatus nextStatue) { - return new RaceLogStartTimeEventImpl(createdAt, author, logicalTimePoint, id, involvedBoats, passId, startTime); - } - - @Override - public RaceLogRaceStatusEvent createRaceStatusEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, RaceLogRaceStatus nextStatus) { - return new RaceLogRaceStatusEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, nextStatus); - } - - @Override - public RaceLogPassChangeEvent createPassChangeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId) { - return new RaceLogPassChangeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId); - } - - @Override - public RaceLogCourseAreaChangedEvent createCourseAreaChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, Serializable courseAreaId) { - return new RaceLogCourseAreaChangeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, courseAreaId); - } - - @Override - public RaceLogCourseDesignChangedEvent createCourseDesignChangedEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List competitors, int passId, CourseBase courseData) { - return new RaceLogCourseDesignChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, courseData); - } - - @Override - public RaceLogFinishPositioningListChangedEvent createFinishPositioningListChangedEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List competitors, int passId, CompetitorResults positionedCompetitors) { - return new RaceLogFinishPositioningListChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors); - } - - @Override - public RaceLogFinishPositioningConfirmedEvent createFinishPositioningConfirmedEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List competitors, int passId, CompetitorResults positionedCompetitors) { - return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, positionedCompetitors); - } - - @Override - public RaceLogPathfinderEvent createPathfinderEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, String pathfinderId) { - return new RaceLogPathfinderEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, pathfinderId); - } - - @Override - public RaceLogGateLineOpeningTimeEvent createGateLineOpeningTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, Long gateLaunchStopTime, - Long golfDownTime) { - return new RaceLogGateLineOpeningTimeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, gateLaunchStopTime, - golfDownTime); - } - - @Override - public RaceLogStartProcedureChangedEvent createStartProcedureChangedEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, RacingProcedureType type) { - return new RaceLogStartProcedureChangedEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, type); - } - - @Override - public RaceLogProtestStartTimeEvent createProtestStartTimeEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, List competitors, int passId, TimePoint protestStartTime) { - return new RaceLogProtestStartTimeEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, protestStartTime); - } - - @Override - public RaceLogWindFixEvent createWindFixEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable id, List competitors, Integer passId, Wind wind, boolean isMagnetic) { - return new RaceLogWindFixEventImpl(createdAt, author, logicalTimePoint, id, competitors, passId, wind, isMagnetic); - } - - @Override - public RaceLogDeviceCompetitorMappingEvent createDeviceCompetitorMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, DeviceIdentifier device, Competitor mappedTo, int passId, TimePoint from, TimePoint to) { - return new RaceLogDeviceCompetitorMappingEventImpl(createdAt, author, logicalTimePoint, pId, passId, mappedTo, device, from, to); - } - - @Override - public RaceLogDeviceMarkMappingEvent createDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, DeviceIdentifier device, Mark mappedTo, int passId, TimePoint from, - TimePoint to) { - return new RaceLogDeviceMarkMappingEventImpl(createdAt, author, logicalTimePoint, pId, passId, mappedTo, device, from, to); - } - - @Override - public RaceLogDenoteForTrackingEvent createDenoteForTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int passId, String raceName, BoatClass boatClass, Serializable raceId) { - return new RaceLogDenoteForTrackingEventImpl(createdAt, author, logicalTimePoint, pId, passId, raceName, boatClass, raceId); - } - - @Override - public RaceLogStartTrackingEvent createStartTrackingEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int passId) { - return new RaceLogStartTrackingEventImpl(createdAt, author, logicalTimePoint, pId, passId); - } - - @Override - public RaceLogRevokeEvent createRevokeEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int passId, Serializable revokedEventId, String revokedEventType, String revokedEventShortInfo, String reason) { - return new RaceLogRevokeEventImpl(createdAt, author, logicalTimePoint, pId, passId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); - } - - @Override - public RaceLogRegisterCompetitorEvent createRegisterCompetitorEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int passId, Competitor competitor) { - return new RaceLogRegisterCompetitorEventImpl(createdAt, author, logicalTimePoint, pId, passId, competitor); - } - - @Override - public RaceLogDefineMarkEvent createDefineMarkEvent(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int passId, Mark mark) { - return new RaceLogDefineMarkEventImpl(createdAt, author, logicalTimePoint, pId, passId, mark); - } - - @Override - public RaceLogCloseOpenEndedDeviceMappingEvent createCloseOpenEndedDeviceMappingEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, int passId, - Serializable deviceMappingEventId, TimePoint closingTimePoint) { - return new RaceLogCloseOpenEndedDeviceMappingEventImpl(createdAt, author, logicalTimePoint, pId, passId, - deviceMappingEventId, closingTimePoint); - } - - @Override - public RaceLogAdditionalScoringInformationEvent createAdditionalScoringInformationEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, List competitors, int passId, - AdditionalScoringInformationType informationType) { - return new RaceLogAdditionalScoringInformationEventImpl(createdAt, author, logicalTimePoint, pId, competitors, passId, informationType); - } - - @Override - public RaceLogDependentStartTimeEvent createDependentStartTimeEvent(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, List involvedBoats, - int passId, SimpleRaceLogIdentifier dependentOnRace, Duration startTimeDifference, RaceLogRaceStatus nextStatus) { - return new RaceLogDependentStartTimeEventImpl(createdAt, author, logicalTimePoint, id, involvedBoats, passId, - dependentOnRace, startTimeDifference); - } -} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningConfirmedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningConfirmedEventImpl.java index 7ce91ea3d68..d99930ece66 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningConfirmedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningConfirmedEventImpl.java @@ -1,22 +1,27 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogFinishPositioningConfirmedEventImpl extends RaceLogFinishPositioningEventImpl implements RaceLogFinishPositioningConfirmedEvent { - +public class RaceLogFinishPositioningConfirmedEventImpl extends RaceLogFinishPositioningEventImpl implements + RaceLogFinishPositioningConfirmedEvent { + private static final long serialVersionUID = 5028181339200048499L; - - public RaceLogFinishPositioningConfirmedEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pCompetitors, int pPassId, CompetitorResults positionedCompetitors) { - super(createdAt, author, pTimePoint, pId, pCompetitors, pPassId, positionedCompetitors); + + public RaceLogFinishPositioningConfirmedEventImpl(TimePoint createdAt, TimePoint pTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, + CompetitorResults positionedCompetitors) { + super(createdAt, pTimePoint, author, pId, pPassId, positionedCompetitors); + } + + public RaceLogFinishPositioningConfirmedEventImpl(TimePoint pTimePoint, AbstractLogEventAuthor author, int pPassId, + CompetitorResults positionedCompetitors) { + super(pTimePoint, author, pPassId, positionedCompetitors); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningEventImpl.java index 6d8b84c3734..11114eb24f9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningEventImpl.java @@ -1,26 +1,30 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public abstract class RaceLogFinishPositioningEventImpl extends RaceLogEventImpl implements RaceLogFinishPositioningEvent { +public abstract class RaceLogFinishPositioningEventImpl extends RaceLogEventImpl implements + RaceLogFinishPositioningEvent { private static final long serialVersionUID = -8168584588697908309L; - + private final CompetitorResults positionedCompetitors; - public RaceLogFinishPositioningEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, CompetitorResults positionedCompetitors) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogFinishPositioningEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, CompetitorResults positionedCompetitors) { + super(createdAt, pTimePoint, author, pId, pPassId); this.positionedCompetitors = positionedCompetitors; } - + + public RaceLogFinishPositioningEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + CompetitorResults positionedCompetitors) { + this(now(), logicalTimePoint, author, randId(), pPassId, positionedCompetitors); + } + @Override public CompetitorResults getPositionedCompetitorsIDsNamesMaxPointsReasons() { return positionedCompetitors; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningListChangedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningListChangedEventImpl.java index 0a744893e8b..57999894412 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningListChangedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFinishPositioningListChangedEventImpl.java @@ -1,22 +1,27 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogFinishPositioningListChangedEventImpl extends RaceLogFinishPositioningEventImpl implements RaceLogFinishPositioningListChangedEvent { - +public class RaceLogFinishPositioningListChangedEventImpl extends RaceLogFinishPositioningEventImpl implements + RaceLogFinishPositioningListChangedEvent { + private static final long serialVersionUID = -8167472925561954739L; - - public RaceLogFinishPositioningListChangedEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List competitors, int pPassId, CompetitorResults positionedCompetitors) { - super(createdAt, author, pTimePoint, pId, competitors, pPassId, positionedCompetitors); + + public RaceLogFinishPositioningListChangedEventImpl(TimePoint createdAt, TimePoint pTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, + CompetitorResults positionedCompetitors) { + super(createdAt, pTimePoint, author, pId, pPassId, positionedCompetitors); + } + + public RaceLogFinishPositioningListChangedEventImpl(TimePoint pTimePoint, AbstractLogEventAuthor author, + int pPassId, CompetitorResults positionedCompetitors) { + super(pTimePoint, author, pPassId, positionedCompetitors); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java index 71b6978ac43..b2c5b0b23b3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFixedMarkPassingEventImpl.java @@ -1,28 +1,35 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; +import java.util.Collections; import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; - public class RaceLogFixedMarkPassingEventImpl extends RaceLogEventImpl implements RaceLogFixedMarkPassingEvent { private final Integer zeroBasedIndexOfWaypointOfPassing; - + private final TimePoint timePointOfPassing; - public RaceLogFixedMarkPassingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, TimePoint timePoint, Integer zeroBasedIndexOfWaypointOfPassing) { - super(createdAt, author, logicalTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogFixedMarkPassingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, List pInvolvedBoats, int pPassId, + TimePoint timePoint, Integer zeroBasedIndexOfWaypointOfPassing) { + super(createdAt, logicalTimePoint, author, pId, pInvolvedBoats, pPassId); this.timePointOfPassing = timePoint; this.zeroBasedIndexOfWaypointOfPassing = zeroBasedIndexOfWaypointOfPassing; } + public RaceLogFixedMarkPassingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Competitor competitor, int pPassId, TimePoint timePoint, Integer zeroBasedIndexOfWaypointOfPassing) { + this(now(), logicalTimePoint, author, randId(), Collections.singletonList(competitor), pPassId, timePoint, + zeroBasedIndexOfWaypointOfPassing); + } + private static final long serialVersionUID = -1796278009919318553L; @Override @@ -42,6 +49,7 @@ public class RaceLogFixedMarkPassingEventImpl extends RaceLogEventImpl implement @Override public String getShortInfo() { - return getInvolvedBoats().get(0).getName()+" at mark "+getZeroBasedIndexOfPassedWaypoint()+" at "+getTimePointOfFixedPassing(); + return getInvolvedBoats().get(0).getName() + " at mark " + getZeroBasedIndexOfPassedWaypoint() + " at " + + getTimePointOfFixedPassing(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFlagEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFlagEventImpl.java index 2ce2aba9444..9af4b2119fb 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFlagEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogFlagEventImpl.java @@ -1,12 +1,10 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sse.common.TimePoint; @@ -17,13 +15,20 @@ public class RaceLogFlagEventImpl extends RaceLogEventImpl implements RaceLogFla private final Flags lowerFlag; private final boolean isDisplayed; - public RaceLogFlagEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pInvolvedBoats, int pPassId, Flags pUpperFlag, Flags pLowerFlag, boolean pIsDisplayed) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogFlagEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, Flags pUpperFlag, Flags pLowerFlag, + boolean pIsDisplayed) { + super(createdAt, pTimePoint, author, pId, pPassId); this.upperFlag = pUpperFlag; this.lowerFlag = pLowerFlag; this.isDisplayed = pIsDisplayed; } + public RaceLogFlagEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, Flags pUpperFlag, + Flags pLowerFlag, boolean pIsDisplayed) { + this(now(), logicalTimePoint, author, randId(), pPassId, pUpperFlag, pLowerFlag, pIsDisplayed); + } + @Override public Flags getUpperFlag() { return upperFlag; @@ -49,4 +54,4 @@ public class RaceLogFlagEventImpl extends RaceLogEventImpl implements RaceLogFla return "upperFlag=" + upperFlag + ", lowerFlag=" + lowerFlag + ", isDisplayed=" + isDisplayed; } - } +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogGateLineOpeningTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogGateLineOpeningTimeEventImpl.java index 77c6a3a72b3..fe90c350dd7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogGateLineOpeningTimeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogGateLineOpeningTimeEventImpl.java @@ -1,26 +1,29 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogGateLineOpeningTimeEventImpl extends RaceLogEventImpl implements RaceLogGateLineOpeningTimeEvent { - + private static final long serialVersionUID = 793529890804809490L; private final GateLineOpeningTimes gateLineOpeningTimes; - public RaceLogGateLineOpeningTimeEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pCompetitors, int pPassId, + public RaceLogGateLineOpeningTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, long gateLaunchStopTime, long golfDownTime) { - super(createdAt, author, pTimePoint, pId, pCompetitors, pPassId); + super(createdAt, pTimePoint, author, pId, pPassId); this.gateLineOpeningTimes = new GateLineOpeningTimes(gateLaunchStopTime, golfDownTime); } + public RaceLogGateLineOpeningTimeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + long gateLaunchStopTime, long golfDownTime) { + this(now(), logicalTimePoint, author, randId(), pPassId, gateLaunchStopTime, golfDownTime); + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogImpl.java index 408ca29df46..290bbea15e9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogImpl.java @@ -7,7 +7,6 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; 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.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.tracking.Track; import com.sap.sailing.domain.tracking.impl.PartialNavigableSetView; @@ -55,7 +54,7 @@ public class RaceLogImpl extends AbstractLogImpl pInvolvedBoats, int pPassId) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogPassChangeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId) { + super(createdAt, pTimePoint, author, pId, pPassId); + } + + public RaceLogPassChangeEventImpl(TimePoint pTimePoint, AbstractLogEventAuthor author, int pPassId) { + super(pTimePoint, author, pPassId); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogPathfinderEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogPathfinderEventImpl.java index 821ec6d6ec3..481d48d284b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogPathfinderEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogPathfinderEventImpl.java @@ -1,25 +1,28 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogPathfinderEventImpl extends RaceLogEventImpl implements RaceLogPathfinderEvent { - + private static final long serialVersionUID = -1654474931330970804L; private final String pathfinderId; - public RaceLogPathfinderEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint pTimePoint, Serializable pId, List pCompetitors, int pPassId, String pathfinderId) { - super(createdAt, author, pTimePoint, pId, pCompetitors, pPassId); + public RaceLogPathfinderEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, String pathfinderId) { + super(createdAt, pTimePoint, author, pId, pPassId); this.pathfinderId = pathfinderId; } + public RaceLogPathfinderEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + String pathfinderId) { + this(now(), logicalTimePoint, author, randId(), pPassId, pathfinderId); + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogProtestStartTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogProtestStartTimeEventImpl.java index 0fe7db6e07f..270d276792c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogProtestStartTimeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogProtestStartTimeEventImpl.java @@ -1,25 +1,28 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogProtestStartTimeEventImpl extends RaceLogEventImpl implements RaceLogProtestStartTimeEvent { private static final long serialVersionUID = -1800827552916395996L; - + private final TimePoint protestStartTime; - - public RaceLogProtestStartTimeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, TimePoint protestStartTime) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + + public RaceLogProtestStartTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, TimePoint protestStartTime) { + super(createdAt, pTimePoint, author, pId, pPassId); this.protestStartTime = protestStartTime; } + public RaceLogProtestStartTimeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + TimePoint protestStartTime) { + this(now(), logicalTimePoint, author, randId(), pPassId, protestStartTime); + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRaceStatusEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRaceStatusEventImpl.java index 69a92a9b13a..560f743c050 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRaceStatusEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRaceStatusEventImpl.java @@ -1,12 +1,10 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sse.common.TimePoint; @@ -15,12 +13,17 @@ public class RaceLogRaceStatusEventImpl extends RaceLogEventImpl implements Race private final RaceLogRaceStatus nextStatus; - public RaceLogRaceStatusEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, RaceLogRaceStatus nextStatus) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogRaceStatusEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, RaceLogRaceStatus nextStatus) { + super(createdAt, pTimePoint, author, pId, pPassId); this.nextStatus = nextStatus; } + public RaceLogRaceStatusEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + RaceLogRaceStatus nextStatus) { + this(now(), logicalTimePoint, author, randId(), pPassId, nextStatus); + } + @Override public RaceLogRaceStatus getNextStatus() { return nextStatus; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java index faaadf7faf7..8f5d7560275 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogRevokeEventImpl.java @@ -21,10 +21,10 @@ public class RaceLogRevokeEventImpl extends RevokeEventImpl this.raceLogEventData = new RaceLogEventDataImpl(null, passId); } - public RaceLogRevokeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public RaceLogRevokeEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int passId, Serializable revokedEventId, String revokedEventType, String revokedEventShortInfo, String reason) { - super(createdAt, author, logicalTimePoint, pId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); + super(createdAt, logicalTimePoint, author, pId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartOfTrackingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartOfTrackingEventImpl.java index 58005300c6a..5878b3fd7f8 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartOfTrackingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartOfTrackingEventImpl.java @@ -1,27 +1,29 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogStartOfTrackingEventImpl extends RaceLogEventImpl implements RaceLogStartOfTrackingEvent { private static final long serialVersionUID = -4134608549471817247L; - public RaceLogStartOfTrackingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint startOfTracking, Serializable pId, List pInvolvedBoats, int pPassId) { - super(createdAt, author, startOfTracking, pId, pInvolvedBoats, pPassId); + public RaceLogStartOfTrackingEventImpl(TimePoint createdAt, TimePoint startOfTracking, + AbstractLogEventAuthor author, Serializable pId, int pPassId) { + super(createdAt, startOfTracking, author, pId, pPassId); + } + + public RaceLogStartOfTrackingEventImpl(TimePoint startOfTracking, AbstractLogEventAuthor author, int pPassId) { + super(startOfTracking, author, pPassId); } @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); } - + @Override public String getShortInfo() { return "startOfTrackingTime=" + getLogicalTimePoint(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartProcedureChangedEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartProcedureChangedEventImpl.java index 896b6c723af..10929f871d7 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartProcedureChangedEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartProcedureChangedEventImpl.java @@ -1,12 +1,10 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sse.common.TimePoint; @@ -17,13 +15,17 @@ public class RaceLogStartProcedureChangedEventImpl extends RaceLogEventImpl impl private final RacingProcedureType startProcedureType; - public RaceLogStartProcedureChangedEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint pTimePoint, Serializable pId, List pInvolvedBoats, int pPassId, RacingProcedureType startProcedureType) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); - + public RaceLogStartProcedureChangedEventImpl(TimePoint createdAt, TimePoint pTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, RacingProcedureType startProcedureType) { + super(createdAt, pTimePoint, author, pId, pPassId); this.startProcedureType = startProcedureType; } + public RaceLogStartProcedureChangedEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int pPassId, RacingProcedureType startProcedureType) { + this(now(), logicalTimePoint, author, randId(), pPassId, startProcedureType); + } + @Override public RacingProcedureType getStartProcedureType() { return startProcedureType; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartTimeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartTimeEventImpl.java index 3d926a02016..3dcf95a655d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartTimeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogStartTimeEventImpl.java @@ -1,12 +1,10 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sse.common.TimePoint; @@ -15,12 +13,17 @@ public class RaceLogStartTimeEventImpl extends RaceLogRaceStatusEventImpl implem private static final long serialVersionUID = 8185811395997196162L; private final TimePoint startTime; - public RaceLogStartTimeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, TimePoint pStartTime) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId, RaceLogRaceStatus.SCHEDULED); + public RaceLogStartTimeEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, TimePoint pStartTime, RaceLogRaceStatus nextStatus) { + super(createdAt, pTimePoint, author, pId, pPassId, nextStatus); this.startTime = pStartTime; } + public RaceLogStartTimeEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + TimePoint pStartTime) { + this(now(), logicalTimePoint, author, randId(), pPassId, pStartTime, RaceLogRaceStatus.SCHEDULED); + } + @Override public TimePoint getStartTime() { return startTime; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java index 87c45b3e975..2e1028af18b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogSuppressedMarkPassingsEventImpl.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; +import java.util.Collections; import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; @@ -9,17 +10,24 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEven import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogSuppressedMarkPassingsEventImpl extends RaceLogEventImpl implements RaceLogSuppressedMarkPassingsEvent { +public class RaceLogSuppressedMarkPassingsEventImpl extends RaceLogEventImpl implements + RaceLogSuppressedMarkPassingsEvent { private static final long serialVersionUID = 3665678555023150888L; private final Integer indexOfFirstSuppressedWaypoint; - public RaceLogSuppressedMarkPassingsEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, - List pInvolvedBoats, int pPassId, Integer indexOfFirstSuppressedWaypoint) { - super(createdAt, author, logicalTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogSuppressedMarkPassingsEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, List pInvolvedBoats, int pPassId, + Integer indexOfFirstSuppressedWaypoint) { + super(createdAt, logicalTimePoint, author, pId, pInvolvedBoats, pPassId); this.indexOfFirstSuppressedWaypoint = indexOfFirstSuppressedWaypoint; + } + public RaceLogSuppressedMarkPassingsEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Competitor competitor, int pPassId, Integer indexOfFirstSuppressedWaypoint) { + this(now(), logicalTimePoint, author, randId(), Collections.singletonList(competitor), pPassId, + indexOfFirstSuppressedWaypoint); } @Override @@ -34,6 +42,6 @@ public class RaceLogSuppressedMarkPassingsEventImpl extends RaceLogEventImpl imp @Override public String getShortInfo() { - return getInvolvedBoats().get(0).getName()+" at mark "+getZeroBasedIndexOfFirstSuppressedWaypoint(); + return getInvolvedBoats().get(0).getName() + " at mark " + getZeroBasedIndexOfFirstSuppressedWaypoint(); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogWindFixEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogWindFixEventImpl.java index e12b27465a9..d8291210efa 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogWindFixEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/RaceLogWindFixEventImpl.java @@ -1,12 +1,10 @@ package com.sap.sailing.domain.abstractlog.race.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.Wind; import com.sap.sse.common.TimePoint; @@ -16,12 +14,17 @@ public class RaceLogWindFixEventImpl extends RaceLogEventImpl implements RaceLog private final Wind windFix; private final boolean isMagnetic; - public RaceLogWindFixEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint pTimePoint, - Serializable pId, List pInvolvedBoats, int pPassId, Wind windFix, boolean isMagnetic) { - super(createdAt, author, pTimePoint, pId, pInvolvedBoats, pPassId); + public RaceLogWindFixEventImpl(TimePoint createdAt, TimePoint pTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, Wind windFix, boolean isMagnetic) { + super(createdAt, pTimePoint, author, pId, pPassId); this.windFix = windFix; this.isMagnetic = isMagnetic; } + + public RaceLogWindFixEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + int pPassId, Wind windFix, boolean isMagnetic) { + this(now(), logicalTimePoint, author, randId(), pPassId, windFix, isMagnetic); + } @Override public void accept(RaceLogEventVisitor visitor) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/scoring/impl/RaceLogAdditionalScoringInformationEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/scoring/impl/RaceLogAdditionalScoringInformationEventImpl.java index f6c54428bc5..54cf87b8eb9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/scoring/impl/RaceLogAdditionalScoringInformationEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/scoring/impl/RaceLogAdditionalScoringInformationEventImpl.java @@ -1,14 +1,12 @@ package com.sap.sailing.domain.abstractlog.race.scoring.impl; import java.io.Serializable; -import java.util.List; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogAdditionalScoringInformationEventImpl extends RaceLogEventImpl implements RaceLogAdditionalScoringInformationEvent { @@ -16,11 +14,16 @@ public class RaceLogAdditionalScoringInformationEventImpl extends RaceLogEventIm private final AdditionalScoringInformationType informationType; - public RaceLogAdditionalScoringInformationEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, List competitors, int pPassId, AdditionalScoringInformationType informationType) { - super(createdAt, author, logicalTimePoint, pId, competitors, pPassId); + public RaceLogAdditionalScoringInformationEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Serializable pId, int pPassId, AdditionalScoringInformationType informationType) { + super(createdAt, logicalTimePoint, author, pId, pPassId); this.informationType = informationType; } + + public RaceLogAdditionalScoringInformationEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + int pPassId, AdditionalScoringInformationType informationType) { + this(now(), logicalTimePoint, author, randId(), pPassId, informationType); + } @Override public void accept(RaceLogEventVisitor visitor) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java index 5ce1d637e05..96ec8bb31cb 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/impl/RaceStateImpl.java @@ -1,7 +1,6 @@ package com.sap.sailing.domain.abstractlog.race.state.impl; import java.util.Collections; -import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -9,14 +8,25 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AdditionalScoringInformationFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.DependentStartTimeResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceStatusAnalyzer; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.state.RaceState; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure; @@ -42,7 +52,6 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { private static final Logger logger = Logger.getLogger(RaceStateImpl.class.getName()); private final AbstractLogEventAuthor author; - private final RaceLogEventFactory factory; public static ReadonlyRaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog) { return create(raceLogResolver, raceLog, /* forRaceLogIdentifier */ null, Collections.emptyMap()); @@ -60,22 +69,19 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { */ public static RaceState create(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, ConfigurationLoader configuration) { return new RaceStateImpl(raceLogResolver, raceLog, author, - RaceLogEventFactory.INSTANCE, - new RacingProcedureFactoryImpl(author, RaceLogEventFactory.INSTANCE, configuration)); + new RacingProcedureFactoryImpl(author, configuration)); } - public RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory eventFactory, + public RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, RacingProcedureFactory procedureFactory) { - this(raceLogResolver, raceLog, author, eventFactory, new RaceStatusAnalyzer.StandardClock(), procedureFactory); + this(raceLogResolver, raceLog, author, new RaceStatusAnalyzer.StandardClock(), procedureFactory); } - private RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory eventFactory, RaceStatusAnalyzer.Clock analyzersClock, + private RaceStateImpl(RaceLogResolver raceLogResolver, RaceLog raceLog, AbstractLogEventAuthor author, RaceStatusAnalyzer.Clock analyzersClock, RacingProcedureFactory procedureFactory) { super(raceLogResolver, raceLog, /* forRaceLogIdentifier */ null, analyzersClock, procedureFactory, Collections.emptyMap(), /* update */ true); this.author = author; - this.factory = eventFactory; } @Override @@ -107,7 +113,7 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { @Override public void setRacingProcedure(TimePoint timePoint, RacingProcedureType newType) { - raceLog.add(factory.createStartProcedureChangedEvent(timePoint, author, raceLog.getCurrentPassId(), newType)); + raceLog.add(new RaceLogStartProcedureChangedEventImpl(timePoint, author, raceLog.getCurrentPassId(), newType)); } @Override @@ -115,7 +121,7 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { RacingProcedurePrerequisite.FulfillmentFunction function = new RacingProcedurePrerequisite.FulfillmentFunction() { @Override public void execute() { - raceLog.add(factory.createStartTimeEvent(now, author, raceLog.getCurrentPassId(), startTime)); + raceLog.add(new RaceLogStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), startTime)); } }; @@ -124,12 +130,12 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { @Override public void forceNewStartTime(TimePoint now, TimePoint startTime) { - raceLog.add(factory.createStartTimeEvent(now, author, raceLog.getCurrentPassId(), startTime)); + raceLog.add(new RaceLogStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), startTime)); } @Override public void requestNewDependentStartTime(final TimePoint now, final Duration startTimeDifference, final SimpleRaceLogIdentifier dependentRace, RaceLogResolver raceLogResolver, RacingProcedurePrerequisite.Resolver resolver) { - final RaceLogDependentStartTimeEvent dependentStartTimeEvent = factory.createDependentStartTimeEvent(now, author, raceLog.getCurrentPassId(), dependentRace, startTimeDifference); + final RaceLogDependentStartTimeEvent dependentStartTimeEvent = new RaceLogDependentStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), dependentRace, startTimeDifference); RacingProcedurePrerequisite.FulfillmentFunction function = new RacingProcedurePrerequisite.FulfillmentFunction() { @Override @@ -148,60 +154,60 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { @Override public void forceNewDependentStartTime(TimePoint now, final Duration startTimeDifference, final SimpleRaceLogIdentifier dependentOnRace) { - raceLog.add(factory.createDependentStartTimeEvent(now, author, raceLog.getCurrentPassId(), dependentOnRace, startTimeDifference)); + raceLog.add(new RaceLogDependentStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), dependentOnRace, startTimeDifference)); } @Override public void setFinishingTime(TimePoint timePoint) { - raceLog.add(factory.createRaceStatusEvent(timePoint, author, raceLog.getCurrentPassId(), RaceLogRaceStatus.FINISHING)); + raceLog.add(new RaceLogRaceStatusEventImpl(timePoint, author, raceLog.getCurrentPassId(), RaceLogRaceStatus.FINISHING)); } @Override public void setFinishedTime(TimePoint timePoint) { - raceLog.add(factory.createRaceStatusEvent(timePoint, author, raceLog.getCurrentPassId(), RaceLogRaceStatus.FINISHED)); + raceLog.add(new RaceLogRaceStatusEventImpl(timePoint, author, raceLog.getCurrentPassId(), RaceLogRaceStatus.FINISHED)); } @Override public void setProtestTime(TimePoint now, TimePoint timePoint) { - raceLog.add(factory.createProtestStartTimeEvent(now, author, raceLog.getCurrentPassId(), timePoint)); + raceLog.add(new RaceLogProtestStartTimeEventImpl(now, author, raceLog.getCurrentPassId(), timePoint)); } @Override public void setAdvancePass(TimePoint timePoint) { - raceLog.add(factory.createPassChangeEvent(timePoint, author, raceLog.getCurrentPassId() + 1)); + raceLog.add(new RaceLogPassChangeEventImpl(timePoint, author, raceLog.getCurrentPassId() + 1)); } @Override public void setAborted(TimePoint timePoint, boolean isPostponed, Flags reasonFlag) { Flags markerFlag = isPostponed ? Flags.AP : Flags.NOVEMBER; - raceLog.add(factory.createFlagEvent(timePoint, author, raceLog.getCurrentPassId(), markerFlag, reasonFlag, true)); + raceLog.add(new RaceLogFlagEventImpl(timePoint, author, raceLog.getCurrentPassId(), markerFlag, reasonFlag, true)); } @Override public void setGeneralRecall(TimePoint timePoint) { - raceLog.add(factory.createFlagEvent(timePoint, author, raceLog.getCurrentPassId(), Flags.FIRSTSUBSTITUTE, Flags.NONE, true)); + raceLog.add(new RaceLogFlagEventImpl(timePoint, author, raceLog.getCurrentPassId(), Flags.FIRSTSUBSTITUTE, Flags.NONE, true)); } @Override public void setFinishPositioningListChanged(TimePoint timePoint, CompetitorResults positionedCompetitors) { - raceLog.add(factory.createFinishPositioningListChangedEvent( + raceLog.add(new RaceLogFinishPositioningListChangedEventImpl( timePoint, author, raceLog.getCurrentPassId(), positionedCompetitors)); } @Override public void setFinishPositioningConfirmed(TimePoint timePoint) { - raceLog.add(factory.createFinishPositioningConfirmedEvent( + raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl( timePoint, author, raceLog.getCurrentPassId(), getFinishPositioningList())); } @Override public void setCourseDesign(TimePoint timePoint, CourseBase courseDesign) { - raceLog.add(factory.createCourseDesignChangedEvent(timePoint, author, raceLog.getCurrentPassId(), courseDesign)); + raceLog.add(new RaceLogCourseDesignChangedEventImpl(timePoint, author, raceLog.getCurrentPassId(), courseDesign)); } @Override public void setWindFix(TimePoint timePoint, Wind wind, boolean isMagnetic) { - raceLog.add(factory.createWindFixEvent(timePoint, author, raceLog.getCurrentPassId(), wind, isMagnetic)); + raceLog.add(new RaceLogWindFixEventImpl(timePoint, author, raceLog.getCurrentPassId(), wind, isMagnetic)); } @Override @@ -209,7 +215,7 @@ public class RaceStateImpl extends ReadonlyRaceStateImpl implements RaceState { final RaceLogAdditionalScoringInformationEvent event = new AdditionalScoringInformationFinder(raceLog).analyze(/*filterBy*/informationType); if (enable) { if (event == null) { - raceLog.add(factory.createAdditionalScoringInformationEvent(timePoint, UUID.randomUUID(), author, raceLog.getCurrentPassId(), informationType)); + raceLog.add(new RaceLogAdditionalScoringInformationEventImpl(timePoint, author, raceLog.getCurrentPassId(), informationType)); } } else { if (event != null) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java index 909c4f138f7..88c96b8b79b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/basic/impl/BasicRacingProcedureImpl.java @@ -6,7 +6,6 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; @@ -25,9 +24,9 @@ import com.sap.sse.common.TimePoint; public class BasicRacingProcedureImpl extends BaseRacingProcedure { - public BasicRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, + public BasicRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, RacingProcedureConfiguration configuration, RaceLogResolver raceLogResolver) { - super(raceLog, author, factory, configuration, raceLogResolver); + super(raceLog, author, configuration, raceLogResolver); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java index 08cff9f9fdd..e1a4fc5a1f6 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/ess/impl/ESSRacingProcedureImpl.java @@ -6,7 +6,6 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; @@ -33,13 +32,13 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa private final static long startPhaseESSThreeUpInterval = 3 * 60 * 1000; // minutes * seconds * milliseconds private final static long startPhaseESSTwoUpInterval = 2 * 60 * 1000; // minutes * seconds * milliseconds private final static long startPhaseESSOneUpInterval = 1 * 60 * 1000; // minutes * seconds * milliseconds - + @SuppressWarnings("unused") private final ESSConfiguration configuration; - - public ESSRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, ESSConfiguration configuration, RaceLogResolver raceLogResolver) { - super(raceLog, author, factory, configuration, raceLogResolver); + + public ESSRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, ESSConfiguration configuration, + RaceLogResolver raceLogResolver) { + super(raceLog, author, configuration, raceLogResolver); this.configuration = configuration; update(); } @@ -48,7 +47,7 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa public RacingProcedureType getType() { return RacingProcedureType.ESS; } - + @Override public RacingProcedurePrerequisite checkPrerequisitesForStart(TimePoint now, TimePoint startTime, FulfillmentFunction function) { @@ -66,12 +65,11 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa @Override protected Collection createStartStateEvents(TimePoint startTime) { - return Arrays. asList( - new RaceStateEventImpl(startTime.minus(startPhaseAPDownInterval), RaceStateEvents.ESS_AP_DOWN), - new RaceStateEventImpl(startTime.minus(startPhaseESSThreeUpInterval), RaceStateEvents.ESS_THREE_UP), - new RaceStateEventImpl(startTime.minus(startPhaseESSTwoUpInterval), RaceStateEvents.ESS_TWO_UP), - new RaceStateEventImpl(startTime.minus(startPhaseESSOneUpInterval), RaceStateEvents.ESS_ONE_UP), - new RaceStateEventImpl(startTime, RaceStateEvents.START)); + return Arrays. asList(new RaceStateEventImpl(startTime.minus(startPhaseAPDownInterval), + RaceStateEvents.ESS_AP_DOWN), new RaceStateEventImpl(startTime.minus(startPhaseESSThreeUpInterval), + RaceStateEvents.ESS_THREE_UP), new RaceStateEventImpl(startTime.minus(startPhaseESSTwoUpInterval), + RaceStateEvents.ESS_TWO_UP), new RaceStateEventImpl(startTime.minus(startPhaseESSOneUpInterval), + RaceStateEvents.ESS_ONE_UP), new RaceStateEventImpl(startTime, RaceStateEvents.START)); } @Override @@ -91,62 +89,51 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa @Override public FlagPoleState getActiveFlags(TimePoint startTime, TimePoint now) { if (now.before(startTime.minus(startPhaseAPDownInterval))) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.AP, true), new FlagPole(Flags.ESSTHREE, false)), null, - Arrays.asList(new FlagPole(Flags.AP, false), new FlagPole(Flags.ESSTHREE, false)), + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.AP, true), new FlagPole(Flags.ESSTHREE, false)), + null, Arrays.asList(new FlagPole(Flags.AP, false), new FlagPole(Flags.ESSTHREE, false)), startTime.minus(startPhaseAPDownInterval)); } else if (now.before(startTime.minus(startPhaseESSThreeUpInterval))) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.AP, false), new FlagPole(Flags.ESSTHREE, false)), - startTime.minus(startPhaseAPDownInterval), - Arrays.asList(new FlagPole(Flags.ESSTHREE, true), new FlagPole(Flags.ESSTWO, false)), - startTime.minus(startPhaseESSThreeUpInterval)); + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.AP, false), new FlagPole(Flags.ESSTHREE, false)), + startTime.minus(startPhaseAPDownInterval), Arrays.asList(new FlagPole(Flags.ESSTHREE, true), + new FlagPole(Flags.ESSTWO, false)), startTime.minus(startPhaseESSThreeUpInterval)); } else if (now.before(startTime.minus(startPhaseESSTwoUpInterval))) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.ESSTHREE, true), new FlagPole(Flags.ESSTWO, false)), - startTime.minus(startPhaseESSThreeUpInterval), - Arrays.asList(new FlagPole(Flags.ESSTWO, true), new FlagPole(Flags.ESSONE, false)), + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.ESSTHREE, true), + new FlagPole(Flags.ESSTWO, false)), startTime.minus(startPhaseESSThreeUpInterval), Arrays.asList( + new FlagPole(Flags.ESSTWO, true), new FlagPole(Flags.ESSONE, false)), startTime.minus(startPhaseESSTwoUpInterval)); } else if (now.before(startTime.minus(startPhaseESSOneUpInterval))) { return new FlagPoleState( Arrays.asList(new FlagPole(Flags.ESSTWO, true), new FlagPole(Flags.ESSONE, false)), - startTime.minus(startPhaseESSTwoUpInterval), - Arrays.asList(new FlagPole(Flags.ESSONE, true)), + startTime.minus(startPhaseESSTwoUpInterval), Arrays.asList(new FlagPole(Flags.ESSONE, true)), startTime.minus(startPhaseESSOneUpInterval)); - } if (now.before(startTime)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.ESSONE, true)), - startTime.minus(startPhaseESSOneUpInterval), - Arrays.asList(new FlagPole(Flags.ESSONE, false)), + } + if (now.before(startTime)) { + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.ESSONE, true)), + startTime.minus(startPhaseESSOneUpInterval), Arrays.asList(new FlagPole(Flags.ESSONE, false)), startTime); } else { if (isIndividualRecallDisplayed(now)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.XRAY, true)), - getIndividualRecallDisplayedTime(), - Arrays.asList(new FlagPole(Flags.XRAY, false)), + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.XRAY, true)), + getIndividualRecallDisplayedTime(), Arrays.asList(new FlagPole(Flags.XRAY, false)), getIndividualRecallRemovalTime()); } else if (isFinished(now)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.BLUE, false)), getFinishedTime()); + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.BLUE, false)), getFinishedTime()); } else if (isInFinishingPhase(now)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.BLUE, true)), - getFinishingTime(), - Arrays.asList(new FlagPole(Flags.BLUE, false)), - null); + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.BLUE, true)), getFinishingTime(), + Arrays.asList(new FlagPole(Flags.BLUE, false)), null); } else { TimePoint recallRemoved = getIndividualRecallRemovalTime(); - return new FlagPoleState(Collections.emptyList(), recallRemoved == null ? startTime : recallRemoved); + return new FlagPoleState(Collections. emptyList(), recallRemoved == null ? startTime + : recallRemoved); } } } - + @Override protected RacingProcedureChangedListeners createChangedListenerContainer() { return new ESSChangedListeners(); } - + @Override protected ESSChangedListeners getChangedListeners() { return (ESSChangedListeners) super.getChangedListeners(); @@ -156,7 +143,7 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa public void addChangedListener(ESSChangedListener listener) { getChangedListeners().add(listener); } - + @Override public TimePoint getTimeLimit(TimePoint startTime) { TimePoint firstBoatTime = new FinishingTimeFinder(raceLog).analyze(); @@ -165,12 +152,12 @@ public class ESSRacingProcedureImpl extends BaseRacingProcedure implements ESSRa } return null; } - + @Override protected boolean hasIndividualRecallByDefault() { return true; } - + @Override public ESSConfiguration getConfiguration() { return (ESSConfiguration) super.getConfiguration(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java index 2bcafb0f08a..276e7d0ee42 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/gate/impl/GateStartRacingProcedureImpl.java @@ -5,11 +5,12 @@ import java.util.Collection; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent.GateLineOpeningTimes; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.GateLineOpeningTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.PathfinderFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; @@ -43,14 +44,15 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements private boolean gateLineOpeningTimesHasBeenSet; private String cachedPathfinder; - public GateStartRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, + public GateStartRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, GateStartConfiguration configuration, RaceLogResolver raceLogResolver) { - super(raceLog, author, factory, configuration, raceLogResolver); + super(raceLog, author, configuration, raceLogResolver); this.gateLineOpeningTimeAnalyzer = new GateLineOpeningTimeFinder(raceLog); this.pathfinderAnalyzer = new PathfinderFinder(raceLog); long defaultGolfDownTime = getDefaultGolfDownTime(); - this.cachedGateLineOpeningTimes = new GateLineOpeningTimes(GateStartRacingProcedure.DefaultGateLaunchStopTime, defaultGolfDownTime); + this.cachedGateLineOpeningTimes = new GateLineOpeningTimes(GateStartRacingProcedure.DefaultGateLaunchStopTime, + defaultGolfDownTime); this.gateLineOpeningTimesHasBeenSet = false; update(); @@ -78,7 +80,8 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements public RacingProcedurePrerequisite checkPrerequisitesForStart(TimePoint now, TimePoint startTime, FulfillmentFunction function) { if (startTime.before(now)) { - if (getConfiguration().hasPathfinder() != null && getConfiguration().hasPathfinder() && getPathfinder() == null) { + if (getConfiguration().hasPathfinder() != null && getConfiguration().hasPathfinder() + && getPathfinder() == null) { return new PathfinderPrerequisite(function, this, now, startTime); } else if (!gateLineOpeningTimesHasBeenSet) { return new GateLaunchTimePrerequisite(function, this, now, startTime, getDefaultGolfDownTime()); @@ -125,8 +128,8 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements switch (event.getEventName()) { case START: if (!gateLineOpeningTimesHasBeenSet) { - setGateLineOpeningTimes(event.getTimePoint(), - cachedGateLineOpeningTimes.getGateLaunchStopTime(), cachedGateLineOpeningTimes.getGolfDownTime()); + setGateLineOpeningTimes(event.getTimePoint(), cachedGateLineOpeningTimes.getGateLaunchStopTime(), + cachedGateLineOpeningTimes.getGolfDownTime()); } rescheduleGateShutdownTime(event.getTimePoint()); return true; @@ -147,35 +150,29 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements TimePoint gateShutdownTime = getGateShutdownTimePoint(startTime); if (now.before(startTime.minus(startPhaseClassOverGolfUpIntervall))) { return new FlagPoleState(Arrays.asList(new FlagPole(classFlag, Flags.GOLF, false), new FlagPole(Flags.PAPA, - false)), null, Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, false)), - startTime.minus(startPhaseClassOverGolfUpIntervall)); + false)), null, Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, + false)), startTime.minus(startPhaseClassOverGolfUpIntervall)); } else if (now.before(startTime.minus(startPhasePapaUpInterval))) { return new FlagPoleState(Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, - false)), startTime.minus(startPhaseClassOverGolfUpIntervall), - Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, true)), - startTime.minus(startPhasePapaUpInterval)); + false)), startTime.minus(startPhaseClassOverGolfUpIntervall), Arrays.asList(new FlagPole(classFlag, + Flags.GOLF, true), new FlagPole(Flags.PAPA, true)), startTime.minus(startPhasePapaUpInterval)); } else if (now.before(startTime.minus(startPhasePapaDownInterval))) { return new FlagPoleState(Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, - true)), startTime.minus(startPhasePapaUpInterval), - Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, false)), - startTime.minus(startPhasePapaDownInterval)); + true)), startTime.minus(startPhasePapaUpInterval), Arrays.asList(new FlagPole(classFlag, + Flags.GOLF, true), new FlagPole(Flags.PAPA, false)), startTime.minus(startPhasePapaDownInterval)); } else if (now.before(startTime)) { return new FlagPoleState(Arrays.asList(new FlagPole(classFlag, Flags.GOLF, true), new FlagPole(Flags.PAPA, - false)), startTime.minus(startPhasePapaDownInterval), - Arrays.asList(new FlagPole(classFlag, false), new FlagPole(Flags.GOLF, true)), startTime); + false)), startTime.minus(startPhasePapaDownInterval), Arrays.asList(new FlagPole(classFlag, false), + new FlagPole(Flags.GOLF, true)), startTime); } else if (now.before(gateShutdownTime)) { return new FlagPoleState(Arrays.asList(new FlagPole(Flags.GOLF, true)), startTime, Arrays.asList(new FlagPole(Flags.GOLF, false)), gateShutdownTime); } else { if (isFinished(now)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.BLUE, false)), getFinishedTime()); + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.BLUE, false)), getFinishedTime()); } else if (isInFinishingPhase(now)) { - return new FlagPoleState( - Arrays.asList(new FlagPole(Flags.BLUE, true)), - getFinishingTime(), - Arrays.asList(new FlagPole(Flags.BLUE, false)), - null); + return new FlagPoleState(Arrays.asList(new FlagPole(Flags.BLUE, true)), getFinishingTime(), + Arrays.asList(new FlagPole(Flags.BLUE, false)), null); } else { return new FlagPoleState(Arrays.asList(new FlagPole(Flags.GOLF, false)), gateShutdownTime); } @@ -204,7 +201,8 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements @Override public void setGateLineOpeningTimes(TimePoint now, long gateLaunchStopTime, long golfDownTime) { - raceLog.add(factory.createGateLineOpeningTimeEvent(now, author, raceLog.getCurrentPassId(), gateLaunchStopTime, golfDownTime)); + raceLog.add(new RaceLogGateLineOpeningTimeEventImpl(now, author, raceLog.getCurrentPassId(), gateLaunchStopTime, + golfDownTime)); } @Override @@ -214,7 +212,7 @@ public class GateStartRacingProcedureImpl extends BaseRacingProcedure implements @Override public void setPathfinder(TimePoint timePoint, String sailingId) { - raceLog.add(factory.createPathfinderEvent(timePoint, author, raceLog.getCurrentPassId(), sailingId)); + raceLog.add(new RaceLogPathfinderEventImpl(timePoint, author, raceLog.getCurrentPassId(), sailingId)); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java index bfef08ff52a..7e848baba4f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/BaseRacingProcedure.java @@ -8,7 +8,6 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder; @@ -19,6 +18,7 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsInFinishingPhase import com.sap.sailing.domain.abstractlog.race.analyzing.impl.IsIndividualRecallDisplayedAnalyzer; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.WeakRaceLogChangedVisitor; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEventScheduler; @@ -52,7 +52,6 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i protected final RaceLog raceLog; protected final AbstractLogEventAuthor author; - protected final RaceLogEventFactory factory; private final RacingProcedureConfiguration configuration; private final RacingProcedureChangedListeners changedListeners; @@ -66,7 +65,6 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i private boolean cachedIsIndividualRecallDisplayed; - /** * When calling me, call {@link BaseRacingProcedure#update()} afterwards! * @@ -74,14 +72,13 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i * is required for a {@link StartTimeFinder} in order to make individual recall timeouts depend on start * time rather than the time the individual recall was issued */ - public BaseRacingProcedure(RaceLog raceLog, AbstractLogEventAuthor author, RaceLogEventFactory factory, + public BaseRacingProcedure(RaceLog raceLog, AbstractLogEventAuthor author, RacingProcedureConfiguration configuration, RaceLogResolver raceLogResolver) { if (configuration == null) { throw new IllegalArgumentException("configuration must not be null"); } this.raceLog = raceLog; this.author = author; - this.factory = factory; this.configuration = configuration; this.changedListeners = createChangedListenerContainer(); this.isRecallDisplayedAnalyzer = new IsIndividualRecallDisplayedAnalyzer(raceLog); @@ -94,18 +91,18 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i this.raceLog.addListener(this.raceLogListener); this.cachedIsIndividualRecallDisplayed = false; } - + @Override public void detach() { raceLog.removeListener(raceLogListener); changedListeners.removeAll(); } - + @Override public void addChangedListener(RacingProcedureChangedListener listener) { changedListeners.addBaseListener(listener); } - + public void removeChangedListener(RacingProcedureChangedListener listener) { changedListeners.remove(listener); }; @@ -155,7 +152,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i } return false; } - + @Override public TimePoint getIndividualRecallDisplayedTime() { if (hasIndividualRecall()) { @@ -163,7 +160,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i } return null; } - + @Override public TimePoint getIndividualRecallRemovalTime() { TimePoint displayed = getIndividualRecallDisplayedTime(); @@ -179,8 +176,11 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i if (raceStartTime != null) { referenceTimePoint = raceStartTime; } else { - logger.warning("An individual recall was set but we don't have a start time set for the race; using individual recall set time "+ - displayed+" + timeout ("+individualRecallRemovalTimeout+") for implicit termination of individual recall"); + logger.warning("An individual recall was set but we don't have a start time set for the race; using individual recall set time " + + displayed + + " + timeout (" + + individualRecallRemovalTimeout + + ") for implicit termination of individual recall"); referenceTimePoint = displayed; } return referenceTimePoint.plus(individualRecallRemovalTimeout); @@ -190,12 +190,14 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i @Override public void displayIndividualRecall(TimePoint displayTime) { - raceLog.add(factory.createFlagEvent(displayTime, author, raceLog.getCurrentPassId(), Flags.XRAY, Flags.NONE, true)); + raceLog.add(new RaceLogFlagEventImpl(displayTime, author, raceLog.getCurrentPassId(), Flags.XRAY, Flags.NONE, + true)); } @Override public void removeIndividualRecall(TimePoint timePoint) { - raceLog.add(factory.createFlagEvent(timePoint, author, raceLog.getCurrentPassId(), Flags.XRAY, Flags.NONE, false)); + raceLog.add(new RaceLogFlagEventImpl(timePoint, author, raceLog.getCurrentPassId(), Flags.XRAY, Flags.NONE, + false)); } @Override @@ -208,11 +210,11 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i return false; } } - + @Override public boolean hasIndividualRecall() { - return configuration.hasInidividualRecall() == null ? - hasIndividualRecallByDefault() : configuration.hasInidividualRecall(); + return configuration.hasInidividualRecall() == null ? hasIndividualRecallByDefault() : configuration + .hasInidividualRecall(); } protected abstract boolean hasIndividualRecallByDefault(); @@ -244,23 +246,23 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i unscheduleStateEvent(RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT); scheduleStateEvents(new RaceStateEventImpl(removalTime, RaceStateEvents.INDIVIDUAL_RECALL_TIMEOUT)); } - + protected void scheduleStateEvents(RaceStateEvent stateEvent) { scheduleStateEvents(Arrays.asList(stateEvent)); } - + protected void scheduleStateEvents(Collection stateEvents) { if (scheduler != null) { scheduler.scheduleStateEvents(stateEvents); } } - + protected void unscheduleStateEvent(RaceStateEvents raceStateEventName) { if (scheduler != null) { scheduler.unscheduleStateEvent(raceStateEventName); } } - + @Override public RacingProcedureConfiguration getConfiguration() { return configuration; @@ -276,7 +278,7 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i scheduler.scheduleStateEvents(createStartStateEvents(state.getStartTime())); } } - + @Override public void onAdvancePass(ReadonlyRaceState state) { unscheduleAllEvents(); @@ -288,21 +290,21 @@ public abstract class BaseRacingProcedure extends BaseRaceStateChangedListener i scheduler.unscheduleAllEvents(); } } - + protected boolean isFinished(TimePoint at) { IsFinishedAnalyzer analyzer = new IsFinishedAnalyzer(raceLog, finishedTimeFinder, at); return analyzer.analyze(); } - + protected boolean isInFinishingPhase(TimePoint at) { IsInFinishingPhaseAnalyzer analyzer = new IsInFinishingPhaseAnalyzer(raceLog, finishingTimeFinder, at); return analyzer.analyze(); } - + protected TimePoint getFinishingTime() { return finishingTimeFinder.analyze(); } - + protected TimePoint getFinishedTime() { return finishedTimeFinder.analyze(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java index 06617dd1902..b5960f24561 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/RacingProcedureFactoryImpl.java @@ -2,7 +2,6 @@ package com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedureFactory; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.ReadonlyRacingProcedure; @@ -13,17 +12,15 @@ import com.sap.sailing.domain.common.racelog.RacingProcedureType; public class RacingProcedureFactoryImpl extends ReadonlyRacingProcedureFactory implements RacingProcedureFactory { private final AbstractLogEventAuthor author; - private final RaceLogEventFactory factory; - public RacingProcedureFactoryImpl(AbstractLogEventAuthor author, RaceLogEventFactory factory, + public RacingProcedureFactoryImpl(AbstractLogEventAuthor author, ConfigurationLoader configuration) { super(configuration); this.author = author; - this.factory = factory; } @Override public ReadonlyRacingProcedure createRacingProcedure(RacingProcedureType type, RaceLog raceLog, RaceLogResolver raceLogResolver) { - return createProcedure(type, raceLog, author, factory, raceLogResolver); + return createProcedure(type, raceLog, author, raceLogResolver); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java index 971ac0caaa2..422effda297 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/impl/ReadonlyRacingProcedureFactory.java @@ -3,7 +3,6 @@ package com.sap.sailing.domain.abstractlog.race.state.racingprocedure.impl; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.impl.NoAddingRaceLogWrapper; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.RacingProcedure; @@ -38,20 +37,20 @@ public class ReadonlyRacingProcedureFactory implements RacingProcedureFactory { } protected ReadonlyRacingProcedure createProcedure(RacingProcedureType type, RaceLog raceLog, - AbstractLogEventAuthor author, RaceLogEventFactory factory, RaceLogResolver raceLogResolver) { + AbstractLogEventAuthor author, RaceLogResolver raceLogResolver) { RegattaConfiguration loadedConfiguration = configuration.load(); switch (type) { case ESS: - return new ESSRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getESSConfiguration(), raceLogResolver); + return new ESSRacingProcedureImpl(raceLog, author, loadedConfiguration.getESSConfiguration(), raceLogResolver); case GateStart: - return new GateStartRacingProcedureImpl(raceLog, author, factory, + return new GateStartRacingProcedureImpl(raceLog, author, loadedConfiguration.getGateStartConfiguration(), raceLogResolver); case RRS26: - return new RRS26RacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getRRS26Configuration(), raceLogResolver); + return new RRS26RacingProcedureImpl(raceLog, author, loadedConfiguration.getRRS26Configuration(), raceLogResolver); case BASIC: - return new BasicRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getBasicConfiguration(), raceLogResolver); + return new BasicRacingProcedureImpl(raceLog, author, loadedConfiguration.getBasicConfiguration(), raceLogResolver); case LEAGUE: - return new LeagueRacingProcedureImpl(raceLog, author, factory, loadedConfiguration.getLeagueConfiguration(), raceLogResolver); + return new LeagueRacingProcedureImpl(raceLog, author, loadedConfiguration.getLeagueConfiguration(), raceLogResolver); default: throw new UnsupportedOperationException("Unknown racing procedure " + type.toString()); } @@ -63,7 +62,7 @@ public class ReadonlyRacingProcedureFactory implements RacingProcedureFactory { AbstractLogEventAuthor author = new LogEventAuthorImpl("Illegal Author", 128); // Wrap the racelog to disable adding... RaceLog wrappedRaceLog = new NoAddingRaceLogWrapper(raceLog); - return createProcedure(type, wrappedRaceLog, author, RaceLogEventFactory.INSTANCE, raceLogResolver); + return createProcedure(type, wrappedRaceLog, author, raceLogResolver); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java index f3e5f2508df..4e78ca10eb1 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/league/impl/LeagueRacingProcedureImpl.java @@ -6,7 +6,6 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; @@ -34,8 +33,8 @@ public class LeagueRacingProcedureImpl extends BaseRacingProcedure implements Le private final static Flags startmodeFlag = Flags.PAPA; public LeagueRacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, LeagueConfiguration configuration, RaceLogResolver raceLogResolver) { - super(raceLog, author, factory, configuration, raceLogResolver); + LeagueConfiguration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, configuration, raceLogResolver); update(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java index a89cc6b95d5..11ec1eb18a9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/state/racingprocedure/rrs26/impl/RRS26RacingProcedureImpl.java @@ -6,10 +6,10 @@ import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RRS26StartModeFlagFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RacingProcedureTypeAnalyzer; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.abstractlog.race.state.RaceStateEvent; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEventImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateEvents; @@ -40,8 +40,8 @@ public class RRS26RacingProcedureImpl extends BaseRacingProcedure implements RRS private boolean startmodeFlagHasBeenSet; public RRS26RacingProcedureImpl(RaceLog raceLog, AbstractLogEventAuthor author, - RaceLogEventFactory factory, RRS26Configuration configuration, RaceLogResolver raceLogResolver) { - super(raceLog, author, factory, configuration, raceLogResolver); + RRS26Configuration configuration, RaceLogResolver raceLogResolver) { + super(raceLog, author, configuration, raceLogResolver); RacingProcedureTypeAnalyzer procedureAnalyzer = new RacingProcedureTypeAnalyzer(raceLog); if (configuration.getStartModeFlags() != null) { @@ -189,7 +189,7 @@ public class RRS26RacingProcedureImpl extends BaseRacingProcedure implements RRS @Override public void setStartModeFlag(TimePoint timePoint, Flags startMode) { - raceLog.add(factory.createFlagEvent(timePoint, author, raceLog.getCurrentPassId(), startMode, Flags.NONE, true)); + raceLog.add(new RaceLogFlagEventImpl(timePoint, author, raceLog.getCurrentPassId(), startMode, Flags.NONE, true)); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogOpenEndedDeviceMappingCloser.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogOpenEndedDeviceMappingCloser.java index f7183da288f..20e355f91ad 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogOpenEndedDeviceMappingCloser.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/analyzing/impl/RaceLogOpenEndedDeviceMappingCloser.java @@ -5,9 +5,9 @@ import java.io.Serializable; 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.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; import com.sap.sailing.domain.abstractlog.shared.analyzing.OpenEndedDeviceMappingCloser; import com.sap.sailing.domain.racelogtracking.DeviceMapping; import com.sap.sse.common.TimePoint; @@ -23,7 +23,7 @@ public class RaceLogOpenEndedDeviceMappingCloser extends @Override protected RaceLogCloseOpenEndedDeviceMappingEvent createCloseEvent(TimePoint logicalTimePoint, Serializable eventToCloseId) { - return RaceLogEventFactory.INSTANCE.createCloseOpenEndedDeviceMappingEvent( + return new RaceLogCloseOpenEndedDeviceMappingEventImpl( logicalTimePoint, author, getLog().getCurrentPassId(), eventToCloseId, closingTimePoint); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/AbstractRaceLogDeviceMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/AbstractRaceLogDeviceMappingEventImpl.java index 54b6e405c36..5729089b331 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/AbstractRaceLogDeviceMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/AbstractRaceLogDeviceMappingEventImpl.java @@ -19,13 +19,19 @@ extends AbstractDeviceMappingEventImpl implements Ra private static final long serialVersionUID = -5114645637316367845L; private final RaceLogEventData raceLogEventData; - public AbstractRaceLogDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, int passId, ItemT mappedTo, DeviceIdentifier device, + public AbstractRaceLogDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, int passId, ItemT mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to); + super(createdAt, logicalTimePoint, author, id, mappedTo, device, from, to); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); } + public AbstractRaceLogDeviceMappingEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int passId, ItemT mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + this(now(), logicalTimePoint, author, randId(), passId, mappedTo, device, from, to); + } + @Override public int getPassId() { return raceLogEventData.getPassId(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogCloseOpenEndedDeviceMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogCloseOpenEndedDeviceMappingEventImpl.java index fbd1631f9d6..bd20d1e61eb 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogCloseOpenEndedDeviceMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogCloseOpenEndedDeviceMappingEventImpl.java @@ -12,18 +12,24 @@ import com.sap.sailing.domain.abstractlog.shared.events.impl.BaseCloseOpenEndedD import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogCloseOpenEndedDeviceMappingEventImpl extends BaseCloseOpenEndedDeviceMappingEventImpl -implements RaceLogCloseOpenEndedDeviceMappingEvent { +public class RaceLogCloseOpenEndedDeviceMappingEventImpl extends + BaseCloseOpenEndedDeviceMappingEventImpl implements + RaceLogCloseOpenEndedDeviceMappingEvent { private static final long serialVersionUID = -5114645637316367845L; private final RaceLogEventData raceLogEventData; - - public RaceLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, int passId, Serializable deviceMappingEventId, + + public RaceLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint) { - super(createdAt, author, logicalTimePoint, id, deviceMappingEventId, closingTimePoint); + super(createdAt, logicalTimePoint, author, id, deviceMappingEventId, closingTimePoint); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); } - + + public RaceLogCloseOpenEndedDeviceMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + int passId, Serializable deviceMappingEventId, TimePoint closingTimePoint) { + this(now(), logicalTimePoint, author, randId(), passId, deviceMappingEventId, closingTimePoint); + } + @Override public int getPassId() { return raceLogEventData.getPassId(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDefineMarkEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDefineMarkEventImpl.java index b60ce4535c5..b4f919ffc5d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDefineMarkEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDefineMarkEventImpl.java @@ -1,13 +1,11 @@ package com.sap.sailing.domain.abstractlog.race.tracking.impl; import java.io.Serializable; -import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Mark; import com.sap.sse.common.TimePoint; @@ -16,11 +14,16 @@ public class RaceLogDefineMarkEventImpl extends RaceLogEventImpl implements Race private final Mark mark; - public RaceLogDefineMarkEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public RaceLogDefineMarkEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, int pPassId, Mark mark) { - super(createdAt, author, logicalTimePoint, pId, Collections.emptyList(), pPassId); + super(createdAt, logicalTimePoint, author, pId, pPassId); this.mark = mark; } + + public RaceLogDefineMarkEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + int pPassId, Mark mark) { + this(now(), logicalTimePoint, author, randId(), pPassId, mark); + } @Override public void accept(RaceLogEventVisitor visitor) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDenoteForTrackingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDenoteForTrackingEventImpl.java index 21d6d7ea445..66b81a2f3c4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDenoteForTrackingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDenoteForTrackingEventImpl.java @@ -1,34 +1,35 @@ package com.sap.sailing.domain.abstractlog.race.tracking.impl; import java.io.Serializable; -import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; -public class RaceLogDenoteForTrackingEventImpl extends RaceLogEventImpl implements -RaceLogDenoteForTrackingEvent { +public class RaceLogDenoteForTrackingEventImpl extends RaceLogEventImpl implements RaceLogDenoteForTrackingEvent { private static final long serialVersionUID = 6937741283401976385L; private final String raceName; private final BoatClass boatClass; private final Serializable raceId; - public RaceLogDenoteForTrackingEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int pPassId, - String raceName, BoatClass boatClass, Serializable raceId) { - super(createdAt, author, logicalTimePoint, pId, Collections.emptyList(), pPassId); + public RaceLogDenoteForTrackingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, String raceName, + BoatClass boatClass, Serializable raceId) { + super(createdAt, logicalTimePoint, author, pId, pPassId); this.raceName = raceName; this.boatClass = boatClass; this.raceId = raceId; } + public RaceLogDenoteForTrackingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + String raceName, BoatClass boatClass, Serializable raceId) { + this(now(), logicalTimePoint, author, randId(), pPassId, raceName, boatClass, raceId); + } + @Override public void accept(RaceLogEventVisitor visitor) { visitor.visit(this); @@ -43,7 +44,7 @@ RaceLogDenoteForTrackingEvent { public BoatClass getBoatClass() { return boatClass; } - + @Override public Serializable getRaceId() { return raceId; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceCompetitorMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceCompetitorMappingEventImpl.java index 41ef893339c..070972b396f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceCompetitorMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceCompetitorMappingEventImpl.java @@ -10,10 +10,16 @@ import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sse.common.TimePoint; public class RaceLogDeviceCompetitorMappingEventImpl extends AbstractRaceLogDeviceMappingEventImpl -implements RaceLogDeviceCompetitorMappingEvent { - public RaceLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int pPassId, Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, pId, pPassId, mappedTo, device, from, to); + implements RaceLogDeviceCompetitorMappingEvent { + public RaceLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, Competitor mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + super(createdAt, logicalTimePoint, author, pId, pPassId, mappedTo, device, from, to); + } + + public RaceLogDeviceCompetitorMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + int pPassId, Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { + super(logicalTimePoint, author, pPassId, mappedTo, device, from, to); } private static final long serialVersionUID = -1494030544804758753L; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceMarkMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceMarkMappingEventImpl.java index 4ad9650c8c4..abcdf21bfd9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceMarkMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogDeviceMarkMappingEventImpl.java @@ -9,13 +9,19 @@ import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sse.common.TimePoint; -public class RaceLogDeviceMarkMappingEventImpl extends AbstractRaceLogDeviceMappingEventImpl -implements RaceLogDeviceMarkMappingEvent { +public class RaceLogDeviceMarkMappingEventImpl extends AbstractRaceLogDeviceMappingEventImpl implements + RaceLogDeviceMarkMappingEvent { private static final long serialVersionUID = -7223543830755457196L; - public RaceLogDeviceMarkMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, int pPassId, Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, pId, pPassId, mappedTo, device, from, to); + public RaceLogDeviceMarkMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId, Mark mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + super(createdAt, logicalTimePoint, author, pId, pPassId, mappedTo, device, from, to); + } + + public RaceLogDeviceMarkMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, int pPassId, + Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { + super(logicalTimePoint, author, pPassId, mappedTo, device, from, to); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java index eb20dd7f79a..1c84b6b429b 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogRegisterCompetitorEventImpl.java @@ -22,13 +22,23 @@ public class RaceLogRegisterCompetitorEventImpl extends BaseRegisterCompetitorEv * @throws IllegalArgumentException * if {@code competitor} is null */ - public RaceLogRegisterCompetitorEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, int passId, Competitor competitor) + public RaceLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, int passId, Competitor competitor) throws IllegalArgumentException { - super(createdAt, author, logicalTimePoint, id, competitor); + super(createdAt, logicalTimePoint, author, id, competitor); this.raceLogEventData = new RaceLogEventDataImpl(null, passId); } + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RaceLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int passId, Competitor competitor) + throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), passId, competitor); + } + @Override public int getPassId() { return raceLogEventData.getPassId(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogStartTrackingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogStartTrackingEventImpl.java index 33a0fdca17b..ed62bc86a5f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogStartTrackingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/tracking/impl/RaceLogStartTrackingEventImpl.java @@ -1,22 +1,25 @@ package com.sap.sailing.domain.abstractlog.race.tracking.impl; import java.io.Serializable; -import java.util.Collections; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogStartTrackingEvent; -import com.sap.sailing.domain.base.Competitor; import com.sap.sse.common.TimePoint; public class RaceLogStartTrackingEventImpl extends RaceLogEventImpl implements RaceLogStartTrackingEvent { private static final long serialVersionUID = 6017954368580125221L; - public RaceLogStartTrackingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, int pPassId) { - super(createdAt, author, logicalTimePoint, pId, Collections.emptyList(), pPassId); + public RaceLogStartTrackingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, int pPassId) { + super(createdAt, logicalTimePoint, author, pId, pPassId); + } + + public RaceLogStartTrackingEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, int pPassId) { + super(logicalTimePoint, author, pPassId); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogCloseOpenEndedDeviceMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogCloseOpenEndedDeviceMappingEventImpl.java index ae0c3541e87..834b6a08bbe 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogCloseOpenEndedDeviceMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogCloseOpenEndedDeviceMappingEventImpl.java @@ -15,7 +15,13 @@ implements RegattaLogCloseOpenEndedDeviceMappingEvent { public RegattaLogCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, Serializable deviceMappingEventId, TimePoint closingTimePoint) { - super(createdAt, author, logicalTimePoint, id, deviceMappingEventId, closingTimePoint); + super(createdAt, logicalTimePoint, author, id, deviceMappingEventId, closingTimePoint); + } + + public RegattaLogCloseOpenEndedDeviceMappingEventImpl(AbstractLogEventAuthor author, + TimePoint logicalTimePoint, Serializable deviceMappingEventId, + TimePoint closingTimePoint) { + super(logicalTimePoint, author, deviceMappingEventId, closingTimePoint); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceCompetitorMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceCompetitorMappingEventImpl.java index 38398c2008c..aaf28ee10f2 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceCompetitorMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceCompetitorMappingEventImpl.java @@ -10,11 +10,19 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sse.common.TimePoint; -public class RegattaLogDeviceCompetitorMappingEventImpl extends AbstractDeviceMappingEventImpl -implements RegattaLogDeviceCompetitorMappingEvent { - public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, - Serializable pId, Competitor mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, pId, mappedTo, device, from, to); +public class RegattaLogDeviceCompetitorMappingEventImpl extends + AbstractDeviceMappingEventImpl implements + RegattaLogDeviceCompetitorMappingEvent { + public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to); + } + + public RegattaLogDeviceCompetitorMappingEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Competitor mappedTo, DeviceIdentifier device, + TimePoint from, TimePoint to) { + super(logicalTimePoint, author, mappedTo, device, from, to); } private static final long serialVersionUID = -1494030544804758753L; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceMarkMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceMarkMappingEventImpl.java index b30558fb509..f00b34d389d 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceMarkMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogDeviceMarkMappingEventImpl.java @@ -14,9 +14,14 @@ public class RegattaLogDeviceMarkMappingEventImpl extends AbstractDeviceMappingE implements RegattaLogDeviceMarkMappingEvent { private static final long serialVersionUID = -7223543830755457196L; - public RegattaLogDeviceMarkMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public RegattaLogDeviceMarkMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, pId, mappedTo, device, from, to); + super(createdAt, logicalTimePoint, author, pId, mappedTo, device, from, to); + } + + public RegattaLogDeviceMarkMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Mark mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { + super(logicalTimePoint, author, mappedTo, device, from, to); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorEventImpl.java index 7e61d369e59..d1f19322fa3 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRegisterCompetitorEventImpl.java @@ -17,9 +17,18 @@ public class RegattaLogRegisterCompetitorEventImpl extends BaseRegisterCompetito * @throws IllegalArgumentException * if {@code competitor} is null */ - public RegattaLogRegisterCompetitorEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, Competitor competitor) throws IllegalArgumentException { - super(createdAt, author, logicalTimePoint, id, competitor); + public RegattaLogRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, Competitor competitor) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, id, competitor); + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public RegattaLogRegisterCompetitorEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Competitor competitor) throws IllegalArgumentException { + super(logicalTimePoint, author, competitor); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRevokeEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRevokeEventImpl.java index be0808779f6..c486fb7ff23 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRevokeEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogRevokeEventImpl.java @@ -12,10 +12,10 @@ import com.sap.sse.common.TimePoint; public class RegattaLogRevokeEventImpl extends RevokeEventImpl implements RegattaLogRevokeEvent { private static final long serialVersionUID = -3470191515219206588L; - public RegattaLogRevokeEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, TimePoint logicalTimePoint, + public RegattaLogRevokeEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Serializable revokedEventId, String revokedEventType, String revokedEventShortInfo, String reason) { - super(createdAt, author, logicalTimePoint, pId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); + super(createdAt, logicalTimePoint, author, pId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); } public RegattaLogRevokeEventImpl(AbstractLogEventAuthor author, RegattaLogEvent toRevoke, String reason) { diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorHandicapInfoEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorHandicapInfoEventImpl.java index 89564c13581..271011daa27 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorHandicapInfoEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorHandicapInfoEventImpl.java @@ -15,9 +15,9 @@ public abstract class RegattaLogSetCompetitorHandicapInfoEventImpl extends Abstr private final Competitor competitor; - protected RegattaLogSetCompetitorHandicapInfoEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, Competitor competitor) { - super(createdAt, author, logicalTimePoint, pId); + protected RegattaLogSetCompetitorHandicapInfoEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor competitor) { + super(createdAt, logicalTimePoint, author, pId); this.competitor = competitor; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl.java index ce918739b21..1583b740755 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl.java @@ -16,9 +16,9 @@ public class RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventI private final Duration timeOnDistanceAllowancePerNauticalMile; public RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEventImpl(TimePoint createdAt, - AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable pId, Competitor competitor, + TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Competitor competitor, Duration timeOnDistanceAllowancePerNauticalMile) { - super(createdAt, author, logicalTimePoint, pId, competitor); + super(createdAt, logicalTimePoint, author, pId, competitor); this.timeOnDistanceAllowancePerNauticalMile = timeOnDistanceAllowancePerNauticalMile; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java index 5000db41223..8b60641f119 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java @@ -12,9 +12,9 @@ public class RegattaLogSetCompetitorTimeOnTimeFactorEventImpl extends RegattaLog private static final long serialVersionUID = -7891407213804859604L; private final Double timeOnTimeFactor; - public RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, Competitor competitor, Double timeOnTimeFactor) { - super(createdAt, author, logicalTimePoint, pId, competitor); + public RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor competitor, Double timeOnTimeFactor) { + super(createdAt, logicalTimePoint, author, pId, competitor); this.timeOnTimeFactor = timeOnTimeFactor; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogOpenEndedDeviceMappingCloser.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogOpenEndedDeviceMappingCloser.java index 03e9945894f..783d3872c1c 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogOpenEndedDeviceMappingCloser.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogOpenEndedDeviceMappingCloser.java @@ -1,7 +1,6 @@ package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; import java.io.Serializable; -import java.util.UUID; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; @@ -12,7 +11,6 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogCloseOpe import com.sap.sailing.domain.abstractlog.shared.analyzing.OpenEndedDeviceMappingCloser; import com.sap.sailing.domain.racelogtracking.DeviceMapping; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaLogOpenEndedDeviceMappingCloser extends OpenEndedDeviceMappingCloser { @@ -25,7 +23,7 @@ public class RegattaLogOpenEndedDeviceMappingCloser extends @Override protected RegattaLogCloseOpenEndedDeviceMappingEvent createCloseEvent(TimePoint logicalTimePoint, Serializable eventToCloseId) { - return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(MillisecondsTimePoint.now(), author, - logicalTimePoint, UUID.randomUUID(), eventToCloseId, closingTimePoint); + return new RegattaLogCloseOpenEndedDeviceMappingEventImpl(author, + logicalTimePoint, eventToCloseId, closingTimePoint); } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/AbstractDeviceMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/AbstractDeviceMappingEventImpl.java index edcfc7a5748..65a4d94129f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/AbstractDeviceMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/AbstractDeviceMappingEventImpl.java @@ -18,16 +18,22 @@ DeviceMappingEvent { private final TimePoint from; private final TimePoint to; - public AbstractDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable id, ItemType mappedTo, + public AbstractDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable id, ItemType mappedTo, DeviceIdentifier device, TimePoint from, TimePoint to) { - super(createdAt, author, logicalTimePoint, id); + super(createdAt, logicalTimePoint, author, id); this.mappedTo = mappedTo; this.device = device; this.from = from; this.to = to; } + public AbstractDeviceMappingEventImpl(TimePoint logicalTimePoint, + AbstractLogEventAuthor author, ItemType mappedTo, + DeviceIdentifier device, TimePoint from, TimePoint to) { + this(now(), logicalTimePoint, author, randId(), mappedTo, device, from, to); + } + public ItemType getMappedTo() { return mappedTo; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseCloseOpenEndedDeviceMappingEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseCloseOpenEndedDeviceMappingEventImpl.java index 7ad9ec08cd1..82f1b490017 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseCloseOpenEndedDeviceMappingEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseCloseOpenEndedDeviceMappingEventImpl.java @@ -8,20 +8,24 @@ import com.sap.sailing.domain.abstractlog.shared.events.CloseOpenEndedDeviceMapp import com.sap.sse.common.TimePoint; public abstract class BaseCloseOpenEndedDeviceMappingEventImpl extends AbstractLogEventImpl -implements CloseOpenEndedDeviceMappingEvent { + implements CloseOpenEndedDeviceMappingEvent { private static final long serialVersionUID = -2401732623610224918L; - + private final Serializable deviceMappingEventId; private final TimePoint closingTimePoint; - public BaseCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, Serializable deviceMappingEventId, - TimePoint closingTimePoint) { - super(createdAt, author, logicalTimePoint, pId); + public BaseCloseOpenEndedDeviceMappingEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Serializable deviceMappingEventId, TimePoint closingTimePoint) { + super(createdAt, logicalTimePoint, author, pId); this.deviceMappingEventId = deviceMappingEventId; this.closingTimePoint = closingTimePoint; } + public BaseCloseOpenEndedDeviceMappingEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Serializable deviceMappingEventId, TimePoint closingTimePoint) { + this(now(), logicalTimePoint, author, randId(), deviceMappingEventId, closingTimePoint); + } + @Override public Serializable getDeviceMappingEventId() { return deviceMappingEventId; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java index 71768eea58e..ac71017500e 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/shared/events/impl/BaseRegisterCompetitorEventImpl.java @@ -17,13 +17,26 @@ public abstract class BaseRegisterCompetitorEventImpl extends Abstract * @throws IllegalArgumentException * if {@code competitor} is null */ - public BaseRegisterCompetitorEventImpl(TimePoint createdAt, AbstractLogEventAuthor author, - TimePoint logicalTimePoint, Serializable pId, Competitor competitor) throws IllegalArgumentException { - super(createdAt, author, logicalTimePoint, pId); + public BaseRegisterCompetitorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, + AbstractLogEventAuthor author, Serializable pId, Competitor competitor) throws IllegalArgumentException { + super(createdAt, logicalTimePoint, author, pId); + checkCompetitor(competitor); + this.competitor = competitor; + } + + /** + * @throws IllegalArgumentException + * if {@code competitor} is null + */ + public BaseRegisterCompetitorEventImpl(TimePoint logicalTimePoint, AbstractLogEventAuthor author, + Competitor competitor) throws IllegalArgumentException { + this(now(), logicalTimePoint, author, randId(), competitor); + } + + private static void checkCompetitor(Competitor competitor) throws IllegalArgumentException { if (competitor == null) { throw new IllegalArgumentException("Competitor may not be null"); } - this.competitor = competitor; } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java index 413775ce470..0746e5e74da 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Boat.java @@ -1,5 +1,6 @@ package com.sap.sailing.domain.base; +import com.sap.sse.common.Color; import com.sap.sse.common.Named; import com.sap.sse.datamining.annotations.Dimension; @@ -8,4 +9,6 @@ public interface Boat extends Named { @Dimension(messageKey="SailID") String getSailID(); + + Color getColor(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/EventBase.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/EventBase.java index f642b939199..1a6a72c7650 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/EventBase.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/EventBase.java @@ -1,98 +1,98 @@ -package com.sap.sailing.domain.base; - -import java.net.URL; -import java.util.Map; - -import com.sap.sailing.domain.common.Renamable; -import com.sap.sse.common.Named; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.WithID; -import com.sap.sse.common.media.ImageSize; -import com.sap.sse.common.media.WithMedia; - -/** - * Base interface for an Event consisting of all static information, which might be shared - * by the server and an Android application. - */ -public interface EventBase extends Named, WithDescription, Renamable, WithID, WithMedia { - - void setDescription(String description); - - /** - * @return a non-null venue for this event - */ - Venue getVenue(); - - /** - * @return the start date of the event - */ - TimePoint getStartDate(); - - void setStartDate(TimePoint startDate); - - /** - * @return the end date of the event - */ - TimePoint getEndDate(); - - void setEndDate(TimePoint startDate); - - boolean isPublic(); - - void setPublic(boolean isPublic); - - /** - * @deprecated - * Returns a non-null live but unmodifiable collection of URLs pointing to image resources that can be - * used to represent the event, e.g., on a web page. - * - * @return a non-null value which may be empty - */ - Iterable getImageURLs(); - - /** - * @deprecated - * An event may have zero or more sponsors, each of which usually want to see their logo on the web page. - * - * @return the sponsors' logos; always non-null but possibly empty - */ - Iterable getSponsorImageURLs(); - - /** - * @deprecated - * An optional logo image; may return null. - */ - URL getLogoImageURL(); - - /** - * @deprecated - * Returns a non-null live but unmodifiable collection of URLs pointing to video resources that can be - * used to represent the event, e.g., on a web page. - * - * @return a non-null value which may be empty - */ - Iterable getVideoURLs(); - - /** - * @return the URL of the event's official web site, or null if such a site does not exist or its URL - * is not known - */ - URL getOfficialWebsiteURL(); - - void setOfficialWebsiteURL(URL officialWebsiteURL); - - /** - * @return the URL of an external web site containing sailor related information like protests, official results, etc. - * or null if such a site does not exist or its URL is not known. - */ - URL getSailorsInfoWebsiteURL(); - - void setSailorsInfoWebsiteURL(URL sailorsInfoWebsiteURL); - - Iterable getLeaderboardGroups(); - - /** - * Sets and converts all event images and videos from the old URL based format to the new richer format - * */ - boolean setMediaURLs(Iterable imageURLs, Iterable sponsorImageURLs, Iterable videoURLs, URL logoImageURL, Map imageSizes); -} +package com.sap.sailing.domain.base; + +import java.net.URL; +import java.util.Map; + +import com.sap.sailing.domain.common.Renamable; +import com.sap.sse.common.Named; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.WithID; +import com.sap.sse.common.media.ImageSize; +import com.sap.sse.shared.media.WithMedia; + +/** + * Base interface for an Event consisting of all static information, which might be shared + * by the server and an Android application. + */ +public interface EventBase extends Named, WithDescription, Renamable, WithID, WithMedia { + + void setDescription(String description); + + /** + * @return a non-null venue for this event + */ + Venue getVenue(); + + /** + * @return the start date of the event + */ + TimePoint getStartDate(); + + void setStartDate(TimePoint startDate); + + /** + * @return the end date of the event + */ + TimePoint getEndDate(); + + void setEndDate(TimePoint startDate); + + boolean isPublic(); + + void setPublic(boolean isPublic); + + /** + * @deprecated + * Returns a non-null live but unmodifiable collection of URLs pointing to image resources that can be + * used to represent the event, e.g., on a web page. + * + * @return a non-null value which may be empty + */ + Iterable getImageURLs(); + + /** + * @deprecated + * An event may have zero or more sponsors, each of which usually want to see their logo on the web page. + * + * @return the sponsors' logos; always non-null but possibly empty + */ + Iterable getSponsorImageURLs(); + + /** + * @deprecated + * An optional logo image; may return null. + */ + URL getLogoImageURL(); + + /** + * @deprecated + * Returns a non-null live but unmodifiable collection of URLs pointing to video resources that can be + * used to represent the event, e.g., on a web page. + * + * @return a non-null value which may be empty + */ + Iterable getVideoURLs(); + + /** + * @return the URL of the event's official web site, or null if such a site does not exist or its URL + * is not known + */ + URL getOfficialWebsiteURL(); + + void setOfficialWebsiteURL(URL officialWebsiteURL); + + /** + * @return the URL of an external web site containing sailor related information like protests, official results, etc. + * or null if such a site does not exist or its URL is not known. + */ + URL getSailorsInfoWebsiteURL(); + + void setSailorsInfoWebsiteURL(URL sailorsInfoWebsiteURL); + + Iterable getLeaderboardGroups(); + + /** + * Sets and converts all event images and videos from the old URL based format to the new richer format + * */ + boolean setMediaURLs(Iterable imageURLs, Iterable sponsorImageURLs, Iterable videoURLs, URL logoImageURL, Map imageSizes); +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardSearchResultBase.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardSearchResultBase.java index 1ab3365fc2e..176dd2a67d2 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardSearchResultBase.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/LeaderboardSearchResultBase.java @@ -34,5 +34,5 @@ public interface LeaderboardSearchResultBase extends Hit { * that is referenced by the leaderboard as its {@link Leaderboard#getDefaultCourseArea() default course area}, the * event is returned; null otherwise. */ - EventBase getEvent(); + Iterable getEvents(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java index 22385b0d39a..9a7f3a50b8a 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/BoatImpl.java @@ -7,6 +7,7 @@ import java.util.Set; import com.sap.sailing.domain.base.BoatChangeListener; import com.sap.sailing.domain.base.BoatClass; +import com.sap.sse.common.Color; import com.sap.sse.common.Util; import com.sap.sse.common.impl.NamedImpl; @@ -14,12 +15,18 @@ public class BoatImpl extends NamedImpl implements DynamicBoat { private static final long serialVersionUID = 3489730487528955788L; private final BoatClass boatClass; private String sailID; + private final Color color; private transient Set listeners; - + public BoatImpl(String name, BoatClass boatClass, String sailID) { + this(name, boatClass, sailID, null); + } + + public BoatImpl(String name, BoatClass boatClass, String sailID, Color color) { super(name); this.boatClass = boatClass; this.sailID = sailID; + this.color = color; this.listeners = new HashSet(); } @@ -38,6 +45,11 @@ public class BoatImpl extends NamedImpl implements DynamicBoat { return sailID; } + @Override + public Color getColor() { + return color; + } + @Override public void setSailId(String newSailId) { final String oldSailId = this.sailID; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/EventBaseImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/EventBaseImpl.java index 566fce6e2c9..98ddd1f7e3f 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/EventBaseImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/EventBaseImpl.java @@ -15,15 +15,15 @@ import com.sap.sailing.domain.base.Venue; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; import com.sap.sse.common.media.ImageSize; -import com.sap.sse.common.media.MediaDescriptor; import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.common.media.MediaUtils; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.MediaDescriptor; +import com.sap.sse.shared.media.MediaUtils; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; public abstract class EventBaseImpl implements EventBase { private static final long serialVersionUID = -5749964088848611074L; diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java index c3fbac12988..b3b0155e091 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/SharedDomainFactoryImpl.java @@ -5,9 +5,8 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.net.URI; -import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -105,13 +104,16 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { } } + /** + * Holds the canonicalized boat class names which are known to maybe start other than with an upwind leg. + * The boat class name used here is obtained by using {@link BoatClassMasterdata#unifyBoatClassName(String)}. + */ private final Set mayStartWithNoUpwindLeg; private final RaceLogResolver raceLogResolver; /** * Uses a transient competitor store - * @param raceLogResolver TODO */ public SharedDomainFactoryImpl(RaceLogResolver raceLogResolver) { this(new TransientCompetitorStoreImpl(), raceLogResolver); @@ -128,7 +130,8 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { boatClassCache = new HashMap(); this.competitorStore = competitorStore; waypointCache = new ConcurrentHashMap(); - mayStartWithNoUpwindLeg = new HashSet(Arrays.asList(new String[] { "extreme40", "ess", "ess40" })); + // FIXME ass also bug 3347: mapping to lower case should rather work through a common unification / canonicalization of boat class names + mayStartWithNoUpwindLeg = Collections.singleton(BoatClassMasterdata.unifyBoatClassName(BoatClassMasterdata.EXTREME_40.getDisplayName())); courseAreaCache = new HashMap(); configurationMatcherCache = new HashMap(); } @@ -282,26 +285,17 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { @Override public BoatClass getOrCreateBoatClass(String name, boolean typicallyStartsUpwind) { - final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassName(name); + final BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name); + final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name); + BoatClass result; synchronized (boatClassCache) { - BoatClass result = boatClassCache.get(name); + result = boatClassCache.get(unifiedBoatClassName); if (result == null) { - result = boatClassCache.get(unifiedBoatClassName); - } - if (result == null && unifiedBoatClassName != null) { - BoatClassMasterdata boatClassMasterdata = BoatClassMasterdata.resolveBoatClass(name); - if (boatClassMasterdata != null) { + if (unifiedBoatClassName != null && boatClassMasterdata != null) { result = new BoatClassImpl(boatClassMasterdata.getDisplayName(), boatClassMasterdata); - boatClassCache.put(name, result); - boatClassCache.put(unifiedBoatClassName, result); - boatClassCache.put(result.getName(), result); - for (String alternativeName : boatClassMasterdata.getAlternativeNames()) { - boatClassCache.put(alternativeName, result); - } + } else { + result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind); } - } - if (result == null) { - result = new BoatClassImpl(unifiedBoatClassName, typicallyStartsUpwind); boatClassCache.put(unifiedBoatClassName, result); } return result; @@ -309,8 +303,9 @@ public class SharedDomainFactoryImpl implements SharedDomainFactory { } @Override - public BoatClass getOrCreateBoatClass(String name) { - return getOrCreateBoatClass(name, name == null || /* typicallyStartsUpwind */!mayStartWithNoUpwindLeg.contains(name.toLowerCase())); + public BoatClass getOrCreateBoatClass(final String name) { + final String unifiedBoatClassName = BoatClassMasterdata.unifyBoatClassNameBasedOnExistingMasterdata(name); + return getOrCreateBoatClass(name, name == null || /* typicallyStartsUpwind */ !mayStartWithNoUpwindLeg.contains(unifiedBoatClassName)); } @Override diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java index 2636916f321..fad14860eb0 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/impl/TransientCompetitorStoreImpl.java @@ -18,6 +18,7 @@ import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorStore; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sse.common.Color; @@ -243,9 +244,10 @@ public class TransientCompetitorStoreImpl implements CompetitorStore, Serializab competitorDTO = new CompetitorDTOImpl(c.getName(), c.getColor(), c.getEmail(), countryCode == null ? "" : countryCode.getTwoLetterISOCode(), countryCode == null ? "" : countryCode.getThreeLetterIOCCode(), countryCode == null ? "" : countryCode.getName(), - c.getBoat().getSailID(), c.getId().toString(), + c.getId().toString(), c.getTeam().getImage() == null ? null : c.getTeam().getImage().toString(), c.getFlagImage() == null ? null : c.getFlagImage().toString(), + new BoatDTO(c.getBoat().getName(), c.getBoat().getSailID(), c.getBoat().getColor()), new BoatClassDTO(c.getBoat().getBoatClass() .getName(), c.getBoat().getBoatClass().getDisplayName(), c.getBoat().getBoatClass().getHullLength().getMeters()), c.getTimeOnTimeFactor(), c.getTimeOnDistanceAllowancePerNauticalMile()); diff --git a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java index 6227fb48c01..c0239414ed0 100755 --- a/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.swisstimingadapter/src/com/sap/sailing/domain/swisstimingadapter/impl/DomainFactoryImpl.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.swisstimingadapter.impl; import java.util.ArrayList; import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -196,7 +197,7 @@ public class DomainFactoryImpl implements DomainFactory { Iterable competitors = createCompetitorList(startList, race.getRaceID(), race.getBoatClass()); logger.info("Creating RaceDefinitionImpl for race "+race.getRaceID()); BoatClass boatClass = race.getBoatClass() != null ? race.getBoatClass() : getRaceTypeFromRaceID(race.getRaceID()).getBoatClass(); - RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitors, race.getRaceID()); + RaceDefinition result = new RaceDefinitionImpl(race.getRaceName(), domainCourse, boatClass, competitors, /* competitorsAndTheirBoats */ Collections.emptyMap(), race.getRaceID()); regatta.addRace(result); return result; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java index 505ef1b2f97..f630c65f58d 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/LeaderboardDTODiffingTest.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sailing.domain.common.dto.FleetDTO; @@ -232,8 +233,8 @@ public class LeaderboardDTODiffingTest { @Test public void testCompetitorListChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); newVersion.competitors.add(13, somebodyNew); // insert a competitor; this should mess up all others' indexes; check if this works CompetitorDTO wolfgang = getPreviousCompetitorByName("HUNGER +JESS"); @@ -253,8 +254,8 @@ public class LeaderboardDTODiffingTest { Util.addAll(newVersion.getSuppressedCompetitors(), newSuppressedCompetitors); newVersion.setSuppressedCompetitors(newSuppressedCompetitors); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); newVersion.setSuppressed(newVersion.competitors.get(13), true); // suppress an existing competitor; compaction should reduce this to a single number only newVersion.setSuppressed(somebodyNew, true); // check that mixed mode with existing and new competitors works as well @@ -276,8 +277,8 @@ public class LeaderboardDTODiffingTest { @Test public void testDisplayNameChange() { newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); newVersion.competitors.add(somebodyNew); newVersion.competitorDisplayNames = new HashMap(newVersion.competitorDisplayNames); @@ -306,8 +307,8 @@ public class LeaderboardDTODiffingTest { List newOrdering = new ArrayList(newVersion.getCompetitorsFromBestToWorst(r9)); newVersion.setCompetitorsFromBestToWorst(r9, newOrdering); newVersion.competitors = new ArrayList(newVersion.competitors); // clone competitor list so it's not identical to that of previous version - CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "GER 1234", "912p09871203987", - /* imageURL */ null, /* flagImageURL */ null, new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, + CompetitorDTO somebodyNew = new CompetitorDTOImpl("Someone New", Color.RED, "someone@nobody.de", "DE", "GER", "Germany", "912p09871203987", + /* imageURL */ null, /* flagImageURL */ null, new BoatDTO("LSC", "GER 1234"), new BoatClassDTO("505", 5.05), /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); newVersion.competitors.add(somebodyNew); newOrdering.add(somebodyNew); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java index a593a00f766..cd6ff4ce7ac 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/markpassing/impl/WaypointPositionAndDistanceCacheTest.java @@ -28,6 +28,7 @@ import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.common.impl.DegreeBearingImpl; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; +import com.sap.sailing.domain.common.impl.NauticalMileDistance; import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; import com.sap.sailing.domain.markpassingcalculation.impl.WaypointPositionAndDistanceCache; import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; @@ -127,6 +128,33 @@ public class WaypointPositionAndDistanceCacheTest { assertEquals(5, recalculations); // one for each waypoint, one for the distance; second request recalculates except start/finish position } + /** + * A white-box text for bug 3364: when multiple cache entries exist in the map, invalidating a cache entry can cause a + * ConcurrentModificationException. + */ + @Test + public void testInvalidateByNewMarkPositionWithMultipleMarkPositionsInCache() { + assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); + trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( + new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution.divide(10)))), + now.plus(timeRangeResolution.divide(10)))); // does not affect the cache interval + trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( + new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution.times(2)))), + now.plus(timeRangeResolution.times(2)))); + trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( + new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution.times(3)))), + now.plus(timeRangeResolution.times(3)))); + assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); + assertEquals(60+new NauticalMileDistance(20).scale(timeRangeResolution.divide(Duration.ONE_HOUR)).getNauticalMiles(), cache.getApproximateDistance(start, windwardWaypoint, now.plus(timeRangeResolution)).getNauticalMiles(), 0.01); + assertEquals(60+new NauticalMileDistance(20).scale(timeRangeResolution.times(2).divide(Duration.ONE_HOUR)).getNauticalMiles(), cache.getApproximateDistance(start, windwardWaypoint, now.plus(timeRangeResolution.times(2))).getNauticalMiles(), 0.01); + trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( + new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution.minus(1)))), + now.plus(timeRangeResolution.minus(1)))); // cause cache invalidation with several entries in the map + recalculations = 0; + assertEquals(60+new NauticalMileDistance(20).scale(timeRangeResolution.divide(Duration.ONE_HOUR)).getNauticalMiles(), cache.getApproximateDistance(start, windwardWaypoint, now.plus(timeRangeResolution)).getNauticalMiles(), 0.01); + assertEquals(2, recalculations); // distance calculation also requires position calculation, therefore 2, not 1 + } + @Test public void testNewMarkPositionAffectingEntryOppositeOrder() { assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); @@ -140,10 +168,13 @@ public class WaypointPositionAndDistanceCacheTest { @Test public void testNewMarkPositionNotAffectingEntry() { - assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution))), - now.plus(timeRangeResolution))); // does not affect the cache interval + now.plus(timeRangeResolution))); + assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); + trackedRace.getOrCreateTrack(windward).add(new GPSFixImpl(new DegreePosition(1, 0).translateGreatCircle( + new DegreeBearingImpl(0), new KnotSpeedImpl(20).travel(now, now.plus(timeRangeResolution.times(2)))), + now.plus(timeRangeResolution.times(2)))); // only affects back to now.plus(timeRangeResolution) but not all the way back to now assertEquals(60, cache.getApproximateDistance(start, windwardWaypoint, now).getNauticalMiles(), 0.01); assertEquals(60, cache.getApproximateDistance(windwardWaypoint, start, now).getNauticalMiles(), 0.01); assertEquals(3, recalculations); // one for the position of each waypoint, one for the distance; second / third request from cache diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java index 98180307380..c89a195de69 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java @@ -165,7 +165,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest { } public static URI getCourseDesignUpdateURI() throws URISyntaxException { - return new URI("http://tracms.traclive.dk/update_course"); + return new URI("http://" + TracTracConnectionConstants.HOST_NAME + "/update_course"); } public static String getTracTracUsername() { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java index 2d261296651..28a3e8018d4 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CompetitorProviderCacheInvalidationTest.java @@ -18,8 +18,9 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +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.events.RegattaLogRegisterCompetitorEvent; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRegisterCompetitorEventImpl; @@ -109,7 +110,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[0]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -125,7 +126,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard // we're now revoking a competitor registration on the race log and assert // that the competitor is gone from the list: final Competitor competitorToRevokeFromRaceLog = compLists[0].get(2); - raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking")); + raceLog.add(new RaceLogRevokeEventImpl(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking")); actualForRace = new HashSet<>(); // try another time; cache should of course yield an equal result (although // we're not asserting here that the result actually comes from the cache) Util.addAll(competitorProviderFlexibleLeaderboard.getAllCompetitors( @@ -149,7 +150,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), MillisecondsTimePoint.now(), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -167,11 +168,11 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard flexibleLeaderboard.addRaceColumn("R1", /* medalRace */ false); RegattaLog regattaLog = flexibleLeaderboard.getRegattaLog(); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), MillisecondsTimePoint.now(), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), UUID.randomUUID(), c)); } RaceLog raceLog = flexibleLeaderboard.getRacelog("R1", LeaderboardNameConstants.DEFAULT_FLEET_NAME); for (Competitor c : compLists[1]) { - raceLog.add(RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); } Set expected = new HashSet<>(compLists[0]); expected.addAll(compLists[1]); @@ -251,7 +252,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard public void testSimpleCompetitorListOnOneRaceLogInRegattaLeaderboard() { RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); for (Competitor c : compLists[0]) { - raceLog.add(RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); + raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), 1, c)); } Set expected = new HashSet<>(compLists[0]); Set actual = new HashSet<>(); @@ -269,7 +270,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final Map competitorOnRegattaLogRegistrationEvents = new HashMap<>(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), c); + final RegattaLogRegisterCompetitorEventImpl registerCompetitorEvent = new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c); regattaLog.add(registerCompetitorEvent); competitorOnRegattaLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -302,13 +303,13 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard final RegattaLog regattaLog = regattaLeaderboard.getRegatta().getRegattaLog(); final LogEventAuthorImpl author = new LogEventAuthorImpl("Me", 0); for (Competitor c : compLists[0]) { - regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, MillisecondsTimePoint.now(), UUID.randomUUID(), c)); + regattaLog.add(new RegattaLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), author, UUID.randomUUID(), c)); } final RaceLog raceLog = regattaLeaderboard.getRacelog("R1", "Yellow"); final int passId = 1; final Map competitorOnRaceLogRegistrationEvents = new HashMap<>(); for (Competitor c : compLists[passId]) { - final RaceLogRegisterCompetitorEvent registerCompetitorEvent = RaceLogEventFactory.INSTANCE.createRegisterCompetitorEvent(MillisecondsTimePoint.now(), author, passId, c); + final RaceLogRegisterCompetitorEvent registerCompetitorEvent = new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), author, passId, c); raceLog.add(registerCompetitorEvent); competitorOnRaceLogRegistrationEvents.put(c, registerCompetitorEvent); } @@ -335,7 +336,7 @@ public class CompetitorProviderCacheInvalidationTest extends AbstractLeaderboard // But now it gets interesting: we're revoking a competitor registration on the race log and assert // that the competitor is gone from the list: final Competitor competitorToRevokeFromRaceLog = compLists[passId].get(2); - raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking")); + raceLog.add(new RaceLogRevokeEventImpl(author, passId, competitorOnRaceLogRegistrationEvents.get(competitorToRevokeFromRaceLog), "Test revoking")); actualForRaceYellow = new HashSet<>(); // try another time; cache should of course yield an equal result (although // we're not asserting here that the result actually comes from the cache) Util.addAll(competitorProviderRegattaLeaderboard.getAllCompetitors( diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DomainFactoryImplTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DomainFactoryImplTest.java new file mode 100644 index 00000000000..a5684e370bf --- /dev/null +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/DomainFactoryImplTest.java @@ -0,0 +1,71 @@ +package com.sap.sailing.domain.test; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl; + +public class DomainFactoryImplTest { + private DomainFactoryImpl domainFactory; + + @Before + public void setUp() { + domainFactory = new DomainFactoryImpl(DomainFactory.INSTANCE); + } + + + @Test + public void testGetDominantBoatClass_TestNullCollection() { + Assert.assertEquals(null, domainFactory.getDominantBoatClass(null)); + } + + @Test + public void testGetDominantBoatClass_TestEmptyCollection() { + List emptyList = new ArrayList<>(); + Assert.assertEquals(null, domainFactory.getDominantBoatClass(emptyList)); + } + @Test + public void testGetDominantBoatClass_TestWithOneObject() { + List list = new ArrayList<>(); + list.add("LSR"); + Assert.assertEquals("Laser Int.", domainFactory.getDominantBoatClass(list).getDisplayName()); + } + + @Test + public void testGetDominantBoatClass_TestWithTheSameCount() { + List list = new ArrayList<>(); + list.add("LSR"); + list.add("18.Footer"); + String result = domainFactory.getDominantBoatClass(list).getDisplayName(); + if(!(result == "Laser Int." || result == "18Footer")) { + Assert.assertEquals("Laser Int.", result); + } + } + + @Test + public void testGetDominantBoatClass_TestWithMoreThanOneObject() { + List list = new ArrayList<>(); + list.add("LSR"); + list.add("18.Footer"); + list.add("LSR"); + String result = domainFactory.getDominantBoatClass(list).getDisplayName(); + Assert.assertEquals("Laser Int.", result); + } + + @Test + public void testGetDominantBoatClass_TestWithSynonymNames() { + List list = new ArrayList<>(); + list.add("LSR"); + list.add("18.Footer"); + list.add("18.Footer"); + list.add("Laser Int."); + list.add("Laser"); + String result = domainFactory.getDominantBoatClass(list).getDisplayName(); + Assert.assertEquals("Laser Int.", result); + } +} diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index 49a4594eb01..ace5830c7fe 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -1213,11 +1213,11 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); RaceLog raceLogForRace2 = leaderboardHighPoint10Or8AndLastBreaksTie.getRaceColumnByName("R2").getRaceLog(leaderboardHighPoint10Or8AndLastBreaksTie.getFleet(null)); - raceLogForRace2.add(new RaceLogAdditionalScoringInformationEventImpl(now, new LogEventAuthorImpl("Plopp", 1), later, "12345678", Collections.emptyList(), 0, AdditionalScoringInformationType.UNKNOWN)); + raceLogForRace2.add(new RaceLogAdditionalScoringInformationEventImpl(now, later, new LogEventAuthorImpl("Plopp", 1), "12345678", 0, AdditionalScoringInformationType.UNKNOWN)); assertEquals(new Double(20), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); - raceLogForRace2.add(new RaceLogAdditionalScoringInformationEventImpl(now, new LogEventAuthorImpl("Plopp", 1), later.plus(Duration.ONE_MINUTE), "123456789873773762", Collections.emptyList(), 0, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); + raceLogForRace2.add(new RaceLogAdditionalScoringInformationEventImpl(now, later.plus(Duration.ONE_MINUTE), new LogEventAuthorImpl("Plopp", 1), "123456789873773762", 0, AdditionalScoringInformationType.MAX_POINTS_DECREASE_MAX_SCORE)); assertEquals(new Double(18), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[0], later)); assertEquals(new Double(16), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[1], later)); assertEquals(new Double(2), leaderboardHighPoint10Or8AndLastBreaksTie.getTotalPoints(competitors[9], later)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java index 9e9f61a7c56..13784b461aa 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/RaceExecutionOrderProvdiderAttachDetachTest.java @@ -1,6 +1,8 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Collections; @@ -10,6 +12,7 @@ import java.util.UUID; import org.junit.Test; +import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Fleet; @@ -199,6 +202,17 @@ public class RaceExecutionOrderProvdiderAttachDetachTest extends TrackBasedTest assertFalse(trackedRace.hasRaceExecutionOrderProvidersAttached()); } + @Test + public void testThatTrackedRaceReceivesRaceLogWhenSeriesIsLinkedToRegatta() { + createTestSetupWithRegattaAndSeries(/* linkSeriesToRegatta */false); + raceColumnInSeries.setTrackedRace(fleet, trackedRace); + assertNull(raceColumnInSeries.getRaceLog(fleet)); + regatta.addSeries(series); + final RaceLog raceLog = raceColumnInSeries.getRaceLog(fleet); + assertNotNull(raceLog); + assertNotNull(trackedRace.getRaceLog(raceLog.getId())); + } + private void createTestSetupWithRegattaAndSeries(boolean linkSeriesToRegatta) { trackedRace = createTestTrackedRace(REGATTA, RACE, BOATCLASS, Collections. emptyList(), MillisecondsTimePoint.now()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java index 483115d7110..cebb4552807 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRank.java @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +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.Course; @@ -75,6 +76,11 @@ public class MockedTrackedRaceWithFixedRank extends MockedTrackedRace { return null; } } + + @Override + public Boat getBoatOfCompetitorById(Serializable competitorID) { + return null; + } } @Override diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java index 64c53934cb9..2eacc2264bd 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRaceWithFixedRankAndManyCompetitors.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.HashSet; import java.util.Set; +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.Course; @@ -50,6 +51,10 @@ public class MockedTrackedRaceWithFixedRankAndManyCompetitors extends MockedTrac public Serializable getId() { return null; } + @Override + public Boat getBoatOfCompetitorById(Serializable competitorID) { + return null; + } }; } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index b1a5b41f6eb..89d0244e00e 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -9,10 +9,13 @@ import java.net.URISyntaxException; import java.net.URL; import java.text.ParseException; import java.util.List; +import java.util.Map; import java.util.UUID; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +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.Course; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.Nationality; @@ -41,14 +44,15 @@ import com.sap.sailing.domain.tracking.impl.EmptyWindStore; import com.sap.sailing.domain.tractracadapter.impl.DomainFactoryImpl; import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver; import com.sap.sailing.domain.tractracadapter.impl.Simulator; -import com.tractrac.model.lib.api.data.IPosition; -import com.sap.sse.common.Duration; +import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.tractrac.model.lib.api.data.IPosition; import com.tractrac.model.lib.api.event.CreateModelException; import com.tractrac.model.lib.api.event.ICompetitor; import com.tractrac.model.lib.api.event.IEvent; import com.tractrac.model.lib.api.event.IRace; +import com.tractrac.model.lib.impl.event.Race; import com.tractrac.subscription.lib.api.IEventSubscriber; import com.tractrac.subscription.lib.api.IRaceSubscriber; import com.tractrac.subscription.lib.api.SubscriberInitializationException; @@ -200,7 +204,7 @@ public interface DomainFactory { * @param raceLogResolver TODO */ DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitors, BoatClass boatClass, + String raceName, Iterable competitors, BoatClass boatClass, Map competitorBoats, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI courseDesignUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver); @@ -255,6 +259,8 @@ public interface DomainFactory { */ RaceDefinition getAndWaitForRaceDefinition(UUID raceId, long timeoutInMilliseconds); + Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass); + Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race); RaceTrackingConnectivityParameters createTrackingConnectivityParameters(URL paramURL, URI liveURI, URI storedURI, @@ -281,7 +287,7 @@ public interface DomainFactory { MetadataParser getMetadataParser(); - BoatClass getDominantBoatClass(List competitorClassNames); + BoatClass getDominantBoatClass(Iterable competitorClassNames); List createSidelines(String raceMetadataString, Iterable allEventControlPoints); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java index 4b7c7ebb375..c5c233d060d 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/MetadataParser.java @@ -7,6 +7,8 @@ import com.sap.sailing.domain.common.MarkType; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.tractracadapter.impl.RaceCourseReceiver; import com.sap.sse.common.Named; +import com.sap.sse.common.Util; +import com.tractrac.model.lib.api.event.IRaceCompetitor; /** * TracTrac objects can be augmented by what TracTrac calls a "DataSheet." These optional data sheets can provide @@ -53,4 +55,10 @@ public interface MetadataParser { Map> parseSidelinesFromRaceMetadata(String raceMetadataString, Iterable controlPoints); + /** + * Parses the boat name, boad id and the boat color for a competitor (entry) of a race. + * @param competitor + * @return a Triple containing the boat name, boat id and boat color or null if no metadata is availalble + */ + Util.Triple parseCompetitorBoat(IRaceCompetitor competitor); } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 26ef68f3f8d..7df01e515ff 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -21,6 +21,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +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.CompetitorStore; @@ -79,6 +80,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.impl.RGBColor; import com.sap.sse.util.WeakIdentityHashMap; import com.tractrac.model.lib.api.data.IPosition; import com.tractrac.model.lib.api.event.CreateModelException; @@ -504,7 +506,7 @@ public class DomainFactoryImpl implements DomainFactory { @Override public DynamicTrackedRace getOrCreateRaceDefinitionAndTrackedRace(DynamicTrackedRegatta trackedRegatta, UUID raceId, - String raceName, Iterable competitors, BoatClass boatClass, Course course, + String raceName, Iterable competitors, BoatClass boatClass, Map competitorBoats, Course course, Iterable sidelines, WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, URI tracTracUpdateURI, UUID tracTracEventUuid, String tracTracUsername, String tracTracPassword, boolean ignoreTracTracMarkPassings, RaceLogResolver raceLogResolver) { @@ -512,7 +514,7 @@ public class DomainFactoryImpl implements DomainFactory { RaceDefinition raceDefinition = raceCache.get(raceId); if (raceDefinition == null) { logger.info("Creating RaceDefinitionImpl for race "+raceName); - raceDefinition = new RaceDefinitionImpl(raceName, course, boatClass, competitors, raceId); + raceDefinition = new RaceDefinitionImpl(raceName, course, boatClass, competitors, competitorBoats, raceId); } else { logger.info("Already found RaceDefinitionImpl for race "+raceName); } @@ -567,9 +569,25 @@ public class DomainFactoryImpl implements DomainFactory { /* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(), raceDefinitionSetToUpdate, useMarkPassingCalculator, raceLogResolver); } + + @Override + public Map getBoatsInfoForCompetitors(IRace race, BoatClass defaultBoatClass) { + final Map competitorBoatInfos = new HashMap<>(); + for (IRaceCompetitor rc : race.getRaceCompetitors()) { + Util.Triple competitorBoatInfo = getMetadataParser().parseCompetitorBoat(rc); + Competitor existingCompetitor = getOrCreateCompetitor(rc.getCompetitor()); + if (existingCompetitor != null && competitorBoatInfo != null) { + Boat boatOfCompetitor = new BoatImpl(competitorBoatInfo.getA(), defaultBoatClass, + competitorBoatInfo.getB(), new RGBColor(competitorBoatInfo.getC())); + competitorBoatInfos.put(existingCompetitor, boatOfCompetitor); + } + } + return competitorBoatInfos; + } + @Override - public com.sap.sse.common.Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race) { + public Util.Pair, BoatClass> getCompetitorsAndDominantBoatClass(IRace race) { List competitorClasses = new ArrayList(); final List competitors = new ArrayList(); for (IRaceCompetitor rc : race.getRaceCompetitors()) { @@ -579,7 +597,7 @@ public class DomainFactoryImpl implements DomainFactory { competitorClasses.add(rc.getCompetitor().getCompetitorClass()); } BoatClass dominantBoatClass = getDominantBoatClass(competitorClasses); - com.sap.sse.common.Util.Pair, BoatClass> competitorsAndDominantBoatClass = new com.sap.sse.common.Util.Pair, BoatClass>( + Util.Pair, BoatClass> competitorsAndDominantBoatClass = new com.sap.sse.common.Util.Pair, BoatClass>( competitors, dominantBoatClass); return competitorsAndDominantBoatClass; } @@ -594,24 +612,19 @@ public class DomainFactoryImpl implements DomainFactory { } @Override - public BoatClass getDominantBoatClass(List competitorClassNames) { - Map countsPerBoatClass = new HashMap(); - BoatClass dominantBoatClass = null; - int numberOfCompetitorsInDominantBoatClass = 0; - for (String competitorClassName : competitorClassNames) { - BoatClass boatClass = getOrCreateBoatClass(competitorClassName); - Integer boatClassCount = countsPerBoatClass.get(boatClass); - if (boatClassCount == null) { - boatClassCount = 0; - } - boatClassCount = boatClassCount + 1; - countsPerBoatClass.put(boatClass, boatClassCount); - if (boatClassCount > numberOfCompetitorsInDominantBoatClass) { - numberOfCompetitorsInDominantBoatClass = boatClassCount; - dominantBoatClass = boatClass; + public BoatClass getDominantBoatClass(Iterable competitorClassNames) { + if (competitorClassNames == null) { + return null; + + } else { + Collection boatClasses = new ArrayList<>(); + for (String competitorClassName : competitorClassNames) { + BoatClass boatClass = getOrCreateBoatClass(competitorClassName); + boatClasses.add(boatClass); } + + return Util.getDominantObject(boatClasses); } - return dominantBoatClass; } @Override diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MetadataParserImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MetadataParserImpl.java index 6972bbe22c6..d2b7bfcb95f 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MetadataParserImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/MetadataParserImpl.java @@ -19,6 +19,7 @@ import com.sap.sailing.domain.tractracadapter.MetadataParser; import com.sap.sailing.domain.tractracadapter.TracTracControlPoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.NamedImpl; +import com.tractrac.model.lib.api.event.IRaceCompetitor; /** * TracTrac objects can be augmented by what TracTrac calls a "DataSheet." These optional data sheets can provide @@ -204,5 +205,29 @@ public class MetadataParserImpl implements MetadataParser { } return result; } - + + @Override + public Util.Triple parseCompetitorBoat(IRaceCompetitor competitor) { + Util.Triple result = null; + String parsedBoatName = null; + String parsedBoatId = null; + String parsedColor = null; + String raceCompetitorMetadataString = competitor.getMetadata() != null ? competitor.getMetadata().getText() : null; + if (raceCompetitorMetadataString != null) { + Map competitorMetadata = parseMetadata(raceCompetitorMetadataString); + for (Entry entry : competitorMetadata.entrySet()) { + if (entry.getKey().startsWith("boatName")) { + parsedBoatName = entry.getValue(); + } else if (entry.getKey().startsWith("boatId")) { + parsedBoatId = entry.getValue(); + } else if (entry.getKey().startsWith("boatColor")) { + parsedColor = entry.getValue(); + } + } + if (parsedBoatName != null && parsedBoatId != null && parsedColor != null) { + result = new Util.Triple(parsedBoatName, parsedBoatId, parsedColor); + } + } + return result; + } } diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java index 9033ba85de2..5f8e6cbb304 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceCourseReceiver.java @@ -9,6 +9,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -156,9 +157,10 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue, BoatClass> competitorsAndDominantBoatClass = getDomainFactory().getCompetitorsAndDominantBoatClass(tractracRace); + Map competitorBoats = getDomainFactory().getBoatsInfoForCompetitors(tractracRace, competitorsAndDominantBoatClass.getB()); trackedRace = getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace( getTrackedRegatta(), tractracRace.getId(), tractracRace.getName(), competitorsAndDominantBoatClass.getA(), - competitorsAndDominantBoatClass.getB(), course, sidelines, windStore, delayToLiveInMillis, + competitorsAndDominantBoatClass.getB(), competitorBoats, course, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate, tracTracUpdateURI, getTracTracEvent().getId(), tracTracUsername, tracTracPassword, useInternalMarkPassingAlgorithm, raceLogResolver); needToUpdateRaceTimes = true; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/LeaderboardSearchResult.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/LeaderboardSearchResult.java index a49b710723b..8beb6d53e52 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/LeaderboardSearchResult.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/LeaderboardSearchResult.java @@ -36,7 +36,7 @@ public interface LeaderboardSearchResult extends LeaderboardSearchResultBase { * If there is a connection between an {@link Event} and the {@link #getLeaderboard() leaderboard}, e.g., because * the {@link Event} has a {@link Event#getLeaderboardGroups() leaderboard group} that is part of {@link #getLeaderboardGroups()} or * the event has a course area attached to its {@link Event#getVenue() venue} that is referenced by the leaderboard as - * its {@link Leaderboard#getDefaultCourseArea() default course area}, the event is returned; null otherwise. + * its {@link Leaderboard#getDefaultCourseArea() default course area}, the event is part of the resulting iterable. */ - Event getEvent(); + Iterable getEvents(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java index eda3492c879..b55928727f9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceDefinition.java @@ -25,4 +25,10 @@ public interface RaceDefinition extends Named, WithID { Iterable getCompetitors(); Competitor getCompetitorById(Serializable competitorID); + + /** + * Gets the boat used by the competitor for this race. + */ + Boat getBoatOfCompetitorById(Serializable competitorID); + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java index e03614bd77e..a6c40da780e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/AbstractRaceColumn.java @@ -1,249 +1,257 @@ -package com.sap.sailing.domain.base.impl; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.logging.Logger; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.racelog.RaceLogIdentifier; -import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.racelog.impl.RaceLogIdentifierImpl; -import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sse.common.Util; - -public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn { - private static final long serialVersionUID = -7801617988982540470L; - - private static final Logger logger = Logger.getLogger(AbstractRaceColumn.class.getName()); - - private TrackedRaces trackedRaces; - private Map raceIdentifiers; - - private Map raceLogs; - - private transient RaceLogStore raceLogStore; - private RegattaLikeIdentifier regattaLikeParent; - - public AbstractRaceColumn() { - this.trackedRaces = new TrackedRaces(); - this.raceIdentifiers = new HashMap(); - this.raceLogs = new HashMap(); - } - - @Override - public synchronized void setRaceLogInformation(RaceLogStore raceLogStore, RegattaLikeIdentifier regattaLikeParent) { - this.raceLogStore = raceLogStore; - this.regattaLikeParent = regattaLikeParent; - for (final Fleet fleet : getFleets()) { - reloadRaceLog(fleet); - } - } - - @Override - public RaceLog getRaceLog(Fleet fleet) { - synchronized (raceLogs) { - return raceLogs.get(fleet); - } - } - - @Override - public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) { - return new RaceLogIdentifierImpl(regattaLikeParent, getName(), fleet); - } - - @Override - public TrackedRace getTrackedRace(Fleet fleet) { - return trackedRaces.get(fleet); - } - - @Override - public void setTrackedRace(Fleet fleet, TrackedRace trackedRace) { - TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet); - if (trackedRace != previouslyLinkedRace) { - releaseTrackedRace(fleet); - synchronized (this) { - if (trackedRace != null) { - this.trackedRaces.put(fleet, trackedRace); - this.setRaceIdentifier(fleet, trackedRace.getRaceIdentifier()); - logger.info(String.format("Linked race column %s with tracked race %s.", this.getName(), - trackedRace.getRace() == null ? "null" : trackedRace.getRace().getName())); - } - } - if (trackedRace != null) { - trackedRace.attachRaceLog(getRaceLog(fleet)); - trackedRace.attachRaceExecutionProvider(getRaceExecutionOrderProvider()); - getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(this, fleet, trackedRace); - } - } - } - - @Override - public RaceIdentifier getRaceIdentifier(Fleet fleet) { - return raceIdentifiers.get(fleet); - } - - @Override - public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) { - if (raceIdentifier != null) { - this.raceIdentifiers.put(fleet, raceIdentifier); - } - } - - @Override - public synchronized void releaseTrackedRace(Fleet fleet) { - TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet); - this.trackedRaces.remove(fleet); - if (previouslyLinkedRace != null && regattaLikeParent != null) { - RaceLogIdentifier identifier = getRaceLogIdentifier(fleet); - previouslyLinkedRace.detachRaceLog(identifier.getIdentifier()); - previouslyLinkedRace.detachRaceExecutionOrderProvider(getRaceExecutionOrderProvider()); - getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(this, fleet, previouslyLinkedRace); - } - } - - @Override - public void removeRaceIdentifier(Fleet fleet) { - releaseTrackedRace(fleet); - this.raceIdentifiers.remove(fleet); - } - - @Override - public Fleet getFleetOfCompetitor(Competitor competitor) { - for (final Fleet fleet : getFleets()) { - if (Util.contains(getAllCompetitors(fleet), competitor)) { - return fleet; - } - } - return null; - } - - @Override - public Fleet getFleetByName(String fleetName) { - for (Fleet fleet : getFleets()) { - if (fleet.getName().equals(fleetName)) { - return fleet; - } - } - return null; - } - - @Override - public boolean hasTrackedRaces() { - return !trackedRaces.isEmpty(); - } - - @Override - public TrackedRace getTrackedRace(Competitor competitor) { - for (TrackedRace trackedRace : trackedRaces.values()) { - if (Util.contains(trackedRace.getRace().getCompetitors(), competitor)) { - return trackedRace; - } - } - return null; - } - - @Override - public String toString() { - return getName(); - } - - @Override - public void reloadRaceLog(Fleet fleet) { - synchronized(raceLogs) { - RaceLogIdentifier identifier = getRaceLogIdentifier(fleet); - RaceLog newOrLoadedRaceLog = raceLogStore.getRaceLog(identifier, /*ignoreCache*/ true); - RaceLog raceLogAvailable = raceLogs.get(fleet); - if (raceLogAvailable == null) { - RaceColumnRaceLogReplicator listener = new RaceColumnRaceLogReplicator(this, identifier); - // FIXME Wouldn't this skip any listener notifications that a merge below would trigger if the race log already existed? - // FIXME For example, how about the race log-provided score corrections that need application to the leaderboard and replication? - newOrLoadedRaceLog.addListener(listener); - raceLogs.put(fleet, newOrLoadedRaceLog); - } else { - // now add all race log events from newOrLoadedRaceLog that are not already in raceLogAvailable - raceLogAvailable.merge(newOrLoadedRaceLog); - } - } - } - - /** - * When deserializing, replication listeners are registered on all race logs. - */ - private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - ois.defaultReadObject(); - for (Entry entry : raceLogs.entrySet()) { - Fleet fleet = entry.getKey(); - RaceLog raceLog = entry.getValue(); - raceLog.addListener(new RaceColumnRaceLogReplicator(this, getRaceLogIdentifier(fleet))); - // now comes a little secrecy (see bug 2506) about how, after de-serialization, the connections - // between race column, race log, tracked race and the listener pumping stuff from the race log - // into the tracked race are re-established. The race log's listener structure is transient, and so - // is the tracked race's attachedRaceLogs field and the logListener field. The collections and the - // DynamicTrackedRaceLogListener are re-established after de-serialization in corresponding readObject(...) - // methods. However, the connections are not. That's what we need to do here, simply by invoking: - ois.registerValidation(() -> { - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - trackedRace.attachRaceLog(raceLog); - } - }, /* prio */ 0); - // because this will add the race log to the tracked race's attachedRaceLogs collection again, and - // the new DynamicTrackedRaceLogListener that the readObject(...) method had constructed for the - // tracked race will be added as a listener to the race log whose listeners collection otherwise would - // only hold the RaceColumnRaceLogReplicator object added above. - } - } - - @Override - public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { - trackedRaces.setMasterDataExportOngoingThreadFlag(flagValue); - } - - - @Override - public Iterable getAllCompetitors() { - Set result = new HashSet<>(); - for (Fleet fleet : getFleets()) { - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - Util.addAll(trackedRace.getRace().getCompetitors(), result); - } else { - // if no tracked race is found, use competitors from race log; this assumes that if a tracked - // race exists, its competitors set takes precedence over what's in the race log. Usually, - // the tracked race will have the same competitors as those in the race log, or more because - // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze(); - result.addAll(viaRaceLog); - } - } - return result; - } - - @Override - public Iterable getAllCompetitors(final Fleet fleet) { - final Iterable result; - TrackedRace trackedRace = getTrackedRace(fleet); - if (trackedRace != null) { - result = trackedRace.getRace().getCompetitors(); - } else { - // if no tracked race is found, use competitors from race log; this assumes that if a tracked - // race exists, its competitors set takes precedence over what's in the race log. Usually, - // the tracked race will have the same competitors as those in the race log, or more because - // those from the regatta log are added to the tracked race as well. - Set viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze(); - result = viaRaceLog; - } - return result; - } -} +package com.sap.sailing.domain.base.impl; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.logging.Logger; + +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; +import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.impl.RaceLogIdentifierImpl; +import com.sap.sailing.domain.regattalike.RegattaLikeIdentifier; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sse.common.Util; + +public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implements RaceColumn { + private static final long serialVersionUID = -7801617988982540470L; + + private static final Logger logger = Logger.getLogger(AbstractRaceColumn.class.getName()); + + private TrackedRaces trackedRaces; + private Map raceIdentifiers; + + private Map raceLogs; + + private transient RaceLogStore raceLogStore; + private RegattaLikeIdentifier regattaLikeParent; + + public AbstractRaceColumn() { + this.trackedRaces = new TrackedRaces(); + this.raceIdentifiers = new HashMap(); + this.raceLogs = new HashMap(); + } + + @Override + public synchronized void setRaceLogInformation(RaceLogStore raceLogStore, RegattaLikeIdentifier regattaLikeParent) { + this.raceLogStore = raceLogStore; + this.regattaLikeParent = regattaLikeParent; + for (final Fleet fleet : getFleets()) { + reloadRaceLog(fleet); + } + } + + @Override + public RaceLog getRaceLog(Fleet fleet) { + synchronized (raceLogs) { + return raceLogs.get(fleet); + } + } + + @Override + public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) { + return new RaceLogIdentifierImpl(regattaLikeParent, getName(), fleet); + } + + @Override + public TrackedRace getTrackedRace(Fleet fleet) { + return trackedRaces.get(fleet); + } + + @Override + public void setTrackedRace(Fleet fleet, TrackedRace trackedRace) { + TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet); + if (trackedRace != previouslyLinkedRace) { + releaseTrackedRace(fleet); + synchronized (this) { + if (trackedRace != null) { + this.trackedRaces.put(fleet, trackedRace); + this.setRaceIdentifier(fleet, trackedRace.getRaceIdentifier()); + logger.info(String.format("Linked race column %s with tracked race %s.", this.getName(), + trackedRace.getRace() == null ? "null" : trackedRace.getRace().getName())); + } + } + if (trackedRace != null) { + final RaceLog raceLog = getRaceLog(fleet); + if (raceLog != null) { + trackedRace.attachRaceLog(raceLog); + } + trackedRace.attachRaceExecutionProvider(getRaceExecutionOrderProvider()); + getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(this, fleet, trackedRace); + } + } + } + + @Override + public RaceIdentifier getRaceIdentifier(Fleet fleet) { + return raceIdentifiers.get(fleet); + } + + @Override + public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) { + if (raceIdentifier != null) { + this.raceIdentifiers.put(fleet, raceIdentifier); + } + } + + @Override + public synchronized void releaseTrackedRace(Fleet fleet) { + TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet); + this.trackedRaces.remove(fleet); + if (previouslyLinkedRace != null && regattaLikeParent != null) { + RaceLogIdentifier identifier = getRaceLogIdentifier(fleet); + previouslyLinkedRace.detachRaceLog(identifier.getIdentifier()); + previouslyLinkedRace.detachRaceExecutionOrderProvider(getRaceExecutionOrderProvider()); + getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(this, fleet, previouslyLinkedRace); + } + } + + @Override + public void removeRaceIdentifier(Fleet fleet) { + releaseTrackedRace(fleet); + this.raceIdentifiers.remove(fleet); + } + + @Override + public Fleet getFleetOfCompetitor(Competitor competitor) { + for (final Fleet fleet : getFleets()) { + if (Util.contains(getAllCompetitors(fleet), competitor)) { + return fleet; + } + } + return null; + } + + @Override + public Fleet getFleetByName(String fleetName) { + for (Fleet fleet : getFleets()) { + if (fleet.getName().equals(fleetName)) { + return fleet; + } + } + return null; + } + + @Override + public boolean hasTrackedRaces() { + return !trackedRaces.isEmpty(); + } + + @Override + public TrackedRace getTrackedRace(Competitor competitor) { + for (TrackedRace trackedRace : trackedRaces.values()) { + if (Util.contains(trackedRace.getRace().getCompetitors(), competitor)) { + return trackedRace; + } + } + return null; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public void reloadRaceLog(Fleet fleet) { + synchronized(raceLogs) { + RaceLogIdentifier identifier = getRaceLogIdentifier(fleet); + RaceLog newOrLoadedRaceLog = raceLogStore.getRaceLog(identifier, /*ignoreCache*/ true); + RaceLog raceLogAvailable = raceLogs.get(fleet); + if (raceLogAvailable == null) { + RaceColumnRaceLogReplicator listener = new RaceColumnRaceLogReplicator(this, identifier); + // FIXME Wouldn't this skip any listener notifications that a merge below would trigger if the race log already existed? + // FIXME For example, how about the race log-provided score corrections that need application to the leaderboard and replication? + newOrLoadedRaceLog.addListener(listener); + raceLogs.put(fleet, newOrLoadedRaceLog); + final TrackedRace trackedRace = getTrackedRace(fleet); + if (trackedRace != null) { + // need to attach race log + trackedRace.attachRaceLog(newOrLoadedRaceLog); + } + } else { + // now add all race log events from newOrLoadedRaceLog that are not already in raceLogAvailable + raceLogAvailable.merge(newOrLoadedRaceLog); + } + } + } + + /** + * When deserializing, replication listeners are registered on all race logs. + */ + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + for (Entry entry : raceLogs.entrySet()) { + Fleet fleet = entry.getKey(); + RaceLog raceLog = entry.getValue(); + raceLog.addListener(new RaceColumnRaceLogReplicator(this, getRaceLogIdentifier(fleet))); + // now comes a little secrecy (see bug 2506) about how, after de-serialization, the connections + // between race column, race log, tracked race and the listener pumping stuff from the race log + // into the tracked race are re-established. The race log's listener structure is transient, and so + // is the tracked race's attachedRaceLogs field and the logListener field. The collections and the + // DynamicTrackedRaceLogListener are re-established after de-serialization in corresponding readObject(...) + // methods. However, the connections are not. That's what we need to do here, simply by invoking: + ois.registerValidation(() -> { + TrackedRace trackedRace = getTrackedRace(fleet); + if (trackedRace != null) { + trackedRace.attachRaceLog(raceLog); + } + }, /* prio */ 0); + // because this will add the race log to the tracked race's attachedRaceLogs collection again, and + // the new DynamicTrackedRaceLogListener that the readObject(...) method had constructed for the + // tracked race will be added as a listener to the race log whose listeners collection otherwise would + // only hold the RaceColumnRaceLogReplicator object added above. + } + } + + @Override + public void setMasterDataExportOngoingThreadFlag(boolean flagValue) { + trackedRaces.setMasterDataExportOngoingThreadFlag(flagValue); + } + + + @Override + public Iterable getAllCompetitors() { + final Set result = new HashSet<>(); + for (Fleet fleet : getFleets()) { + TrackedRace trackedRace = getTrackedRace(fleet); + if (trackedRace != null) { + Util.addAll(trackedRace.getRace().getCompetitors(), result); + } else { + // if no tracked race is found, use competitors from race log; this assumes that if a tracked + // race exists, its competitors set takes precedence over what's in the race log. Usually, + // the tracked race will have the same competitors as those in the race log, or more because + // those from the regatta log are added to the tracked race as well. + Set viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze(); + result.addAll(viaRaceLog); + } + } + return result; + } + + @Override + public Iterable getAllCompetitors(final Fleet fleet) { + final Iterable result; + final TrackedRace trackedRace = getTrackedRace(fleet); + if (trackedRace != null) { + result = trackedRace.getRace().getCompetitors(); + } else { + // if no tracked race is found, use competitors from race log; this assumes that if a tracked + // race exists, its competitors set takes precedence over what's in the race log. Usually, + // the tracked race will have the same competitors as those in the race log, or more because + // those from the regatta log are added to the tracked race as well. + Set viaRaceLog = new RegisteredCompetitorsAnalyzer<>(getRaceLog(fleet)).analyze(); + result = viaRaceLog; + } + return result; + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index 51bf63b2070..a60d5e91926 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -49,6 +49,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsEightAndInterp import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsFive; import com.sap.sailing.domain.leaderboard.impl.HighPointWinnerGetsSix; import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.impl.LowPointForLeagueOverallLeaderboard; import com.sap.sailing.domain.leaderboard.impl.LowPointWinnerGetsZero; import com.sap.sailing.domain.leaderboard.impl.LowPointWithEliminationsAndRoundsWinnerGets07; import com.sap.sailing.domain.tracking.GPSFixTrack; @@ -116,6 +117,8 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl implements Domain return new HighPointFirstGets10Or8AndLastBreaksTie(); case LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07: return new LowPointWithEliminationsAndRoundsWinnerGets07(); + case LOW_POINT_LEAGUE_OVERALL: + return new LowPointForLeagueOverallLeaderboard(); } throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name()); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultBaseImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultBaseImpl.java index 216e51850b3..6644dc200d5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultBaseImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultBaseImpl.java @@ -19,17 +19,17 @@ public class LeaderboardSearchResultBaseImpl implements LeaderboardSearchResultB private final LeaderboardBase leaderboard; private final String regattaName; private final Iterable leaderboardGroups; - private final EventBase event; + private final Iterable events; private final String boatClassName; public LeaderboardSearchResultBaseImpl(LeaderboardBase leaderboard, String regattaName, - String boatClassName, Iterable leaderboardGroups, EventBase event) { + String boatClassName, Iterable leaderboardGroups, Iterable events) { super(); this.leaderboard = leaderboard; this.regattaName = regattaName; this.boatClassName = boatClassName; this.leaderboardGroups = leaderboardGroups; - this.event = event; + this.events = events; } @Override @@ -53,8 +53,8 @@ public class LeaderboardSearchResultBaseImpl implements LeaderboardSearchResultB } @Override - public EventBase getEvent() { - return event; + public Iterable getEvents() { + return events; } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultImpl.java index d619c8234f2..edb1557c2b9 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/LeaderboardSearchResultImpl.java @@ -14,17 +14,17 @@ import com.sap.sailing.domain.tracking.TrackedRace; public class LeaderboardSearchResultImpl implements LeaderboardSearchResult { private final Leaderboard leaderboard; - private final Event event; + private final Set events; private final Set leaderboardGroups; - public LeaderboardSearchResultImpl(Leaderboard leaderboard, Event event, Set leaderboardGroups) { + public LeaderboardSearchResultImpl(Leaderboard leaderboard, Set events, Set leaderboardGroups) { this.leaderboard = leaderboard; if (leaderboardGroups == null) { this.leaderboardGroups = Collections.emptySet(); } else { this.leaderboardGroups = leaderboardGroups; } - this.event = event; + this.events = events; } @Override @@ -49,8 +49,8 @@ public class LeaderboardSearchResultImpl implements LeaderboardSearchResult { } @Override - public Event getEvent() { - return event; + public Iterable getEvents() { + return events; } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java index 7b297db56cf..c62df996b41 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RaceDefinitionImpl.java @@ -2,10 +2,15 @@ package com.sap.sailing.domain.base.impl; import java.io.Serializable; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.logging.Logger; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Course; @@ -13,23 +18,37 @@ import com.sap.sailing.domain.base.RaceDefinition; import com.sap.sse.common.impl.NamedImpl; public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { + private static final Logger logger = Logger.getLogger(RaceDefinitionImpl.class.getName()); + private static final long serialVersionUID = -1900955198751393727L; private final Course course; private final LinkedHashMap competitorsById; private final Set competitors; + private final Map competitorBoats; private final BoatClass boatClass; private final Serializable id; - + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors) { - this(name, course, boatClass, competitors, /* use name as default ID */ name); + this(name, course, boatClass, competitors, Collections.emptyMap()); + } + + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, + Map competitorsAndTheirBoats) { + this(name, course, boatClass, competitors, competitorsAndTheirBoats, /* use name as default ID */ name); } public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, Serializable id) { + this(name, course, boatClass, competitors, /* per-race boats for competitors */ Collections.emptyMap(), id); + } + + public RaceDefinitionImpl(String name, Course course, BoatClass boatClass, Iterable competitors, + Map competitorsAndTheirBoats, Serializable id) { super(name); assert name != null; this.course = course; this.competitors = new HashSet<>(); this.competitorsById = new LinkedHashMap<>(); + this.competitorBoats = new HashMap<>(); for (Competitor competitor : competitors) { Competitor competitorWithEqualID = competitorsById.put(competitor.getId(), competitor); this.competitors.add(competitor); @@ -37,6 +56,15 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { throw new IllegalArgumentException("Two distinct competitors with equal ID "+competitor.getId()+" are not allowed within the single race "+name); } } + for (Entry competitorAndBoat : competitorsAndTheirBoats.entrySet()) { + Competitor competitor = competitorsById.get(competitorAndBoat.getKey().getId()); // only assign boat if competitor is part of race + if (competitor != null && competitorAndBoat.getValue() != null) { + competitorBoats.put(competitor.getId(), competitorAndBoat.getValue()); + } else { + logger.warning("Trying to set boat "+competitorAndBoat.getValue()+" for competitor "+competitorAndBoat.getKey()+ + " which is not part of race "+getName()+"'s set of competitors"); + } + } this.boatClass = boatClass; this.id = id; } @@ -66,4 +94,8 @@ public class RaceDefinitionImpl extends NamedImpl implements RaceDefinition { return boatClass; } + @Override + public Boat getBoatOfCompetitorById(Serializable competitorID) { + return competitorBoats.get(competitorID); + } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java index 9badb203b79..a24a15b96db 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/ScoringScheme.java @@ -71,11 +71,14 @@ public interface ScoringScheme extends Serializable { Integer numberOfCompetitorsInRace, NumberOfCompetitorsInLeaderboardFetcher numberOfCompetitorsInLeaderboardFetcher); /** + * @param o1 TODO * @param competitor1Scores scores of the first competitor, in the order of race columns in the leaderboard + * @param o2 TODO * @param competitor2Scores scores of the second competitor, in the order of race columns in the leaderboard + * @param timePoint TODO */ - int compareByBetterScore(List> competitor1Scores, - List> competitor2Scores, boolean nullScoresAreBetter); + int compareByBetterScore(Competitor o1, + List> competitor1Scores, Competitor o2, List> competitor2Scores, boolean nullScoresAreBetter, TimePoint timePoint); /** * In case two competitors scored in different numbers of races, this scoring scheme decides whether this diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java index 0b5871d5f8b..d53aa47d527 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractScoringSchemeImpl.java @@ -7,6 +7,7 @@ import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Set; import com.sap.sailing.domain.base.Competitor; @@ -17,6 +18,7 @@ import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; public abstract class AbstractScoringSchemeImpl implements ScoringScheme { private static final long serialVersionUID = 6830414905539642446L; @@ -122,7 +124,7 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme { * Assuming both competitors scored in the same number of races, compares the sorted scores. */ @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { final Comparator pureScoreComparator = getScoreComparator(nullScoresAreBetter); // needs to compare net points; therefore, divide the total points by the column factor for comparison: List o1NetScores = new ArrayList<>(); @@ -161,9 +163,16 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme { @Override public int compareByLastRace(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { int result = 0; - if (!o1Scores.isEmpty() && !o2Scores.isEmpty()) { - result = getScoreComparator(nullScoresAreBetter).compare(o1Scores.get(o1Scores.size()-1).getB(), - o2Scores.get(o2Scores.size()-1).getB()); + final Comparator pureScoreComparator = getScoreComparator(nullScoresAreBetter); + ListIterator> o1Iter = o1Scores.listIterator(o1Scores.size()); + ListIterator> o2Iter = o2Scores.listIterator(o2Scores.size()); + while (result == 0 && o1Iter.hasPrevious() && o2Iter.hasPrevious()) { + result = pureScoreComparator.compare(o1Iter.previous().getB(), o2Iter.previous().getB()); + } + if (o1Iter.hasPrevious() != o2Iter.hasPrevious()) { + // if, as may be allowed by some scoring scheme variants, competitors with different numbers of scored races are compared + // and are equal for all races of the competitor who scored fewer races, the competitor who scored more races is preferred + result = o1Iter.hasNext() ? -1 : 1; } return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 0293355a26c..de92f254836 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -655,7 +655,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race return getScoringScheme().isValidInTotalScore(this, raceColumn, competitor, timePoint) && (getScoreCorrection().isScoreCorrected(competitor, raceColumn, timePoint) || ((trackedRaceForCompetitorInColumn=raceColumn.getTrackedRace(competitor)) != null && - trackedRaceForCompetitorInColumn.hasStarted(timePoint))); + trackedRaceForCompetitorInColumn.hasStarted(timePoint) && + trackedRaceForCompetitorInColumn.getRank(competitor, timePoint) != 0)); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointExtremeSailingSeriesOverall.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointExtremeSailingSeriesOverall.java index badf4434478..ed98d6033bd 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointExtremeSailingSeriesOverall.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointExtremeSailingSeriesOverall.java @@ -51,7 +51,7 @@ public class HighPointExtremeSailingSeriesOverall extends HighPoint { * Implements rule 13.5 of the Extreme Sailing Series notice of race as of August 2012. */ @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { assert o1Scores.size() == o2Scores.size(); int o1Wins = getWins(o1Scores); int o2Wins = getWins(o2Scores); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10LastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10LastBreaksTie.java index 41dbe043fcf..dfeb99259e0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10LastBreaksTie.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10LastBreaksTie.java @@ -2,8 +2,10 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.List; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; public class HighPointFirstGets10LastBreaksTie extends HighPointFirstGetsFixedScore { @@ -19,7 +21,7 @@ public class HighPointFirstGets10LastBreaksTie extends HighPointFirstGetsFixedSc } @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { return 0; } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java index 0ddf9dc3a0c..0cd5de3afa8 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets10Or8AndLastBreaksTie.java @@ -43,7 +43,7 @@ public class HighPointFirstGets10Or8AndLastBreaksTie extends HighPointFirstGetsF } @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { int o1Wins = getWins(o1Scores); int o2Wins = getWins(o2Scores); int result = o2Wins - o1Wins; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java index db01a6a8748..9d4d86e0ac5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointFirstGets1LastBreaksTie.java @@ -7,6 +7,7 @@ import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.leaderboard.NumberOfCompetitorsInLeaderboardFetcher; +import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; public class HighPointFirstGets1LastBreaksTie extends HighPointFirstGetsFixedScore { @@ -28,7 +29,7 @@ public class HighPointFirstGets1LastBreaksTie extends HighPointFirstGetsFixedSco } @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { return 0; } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointLastBreaksTie.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointLastBreaksTie.java index 05ae9f463a4..899279c682f 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointLastBreaksTie.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/HighPointLastBreaksTie.java @@ -2,8 +2,10 @@ package com.sap.sailing.domain.leaderboard.impl; import java.util.List; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; /** @@ -18,7 +20,7 @@ public class HighPointLastBreaksTie extends HighPoint { private static final long serialVersionUID = -5338636946886101669L; @Override - public int compareByBetterScore(List> o1Scores, List> o2Scores, boolean nullScoresAreBetter) { + public int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { return 0; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java index 64d1990ff54..b65b6ad1046 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LeaderboardTotalRankComparator.java @@ -173,7 +173,7 @@ public class LeaderboardTotalRankComparator implements Comparator { if (result == 0) { result = compareByMedalRaceScore(o1MedalRaceScore, o2MedalRaceScore); if (result == 0) { - result = compareByBetterScore(Collections.unmodifiableList(o1Scores), Collections.unmodifiableList(o2Scores)); + result = compareByBetterScore(o1, Collections.unmodifiableList(o1Scores), o2, Collections.unmodifiableList(o2Scores), timePoint); if (result == 0) { // compare by last race: result = scoringScheme.compareByLastRace(o1Scores, o2Scores, nullScoresAreBetter); @@ -276,11 +276,11 @@ public class LeaderboardTotalRankComparator implements Comparator { /** * Assuming both competitors scored in the same number of races, and assuming they scored the same total score, * break the tie according to the {@link #scoringScheme scoring scheme} set for this comparator. - * - * @see ScoringScheme#compareByBetterScore(List, List, boolean) + * @see ScoringScheme#compareByBetterScore(Competitor, List, Competitor, List, boolean, TimePoint) */ - protected int compareByBetterScore(List> o1Scores, List> o2Scores) { - return scoringScheme.compareByBetterScore(o1Scores, o2Scores, nullScoresAreBetter); + protected int compareByBetterScore(Competitor o1, List> o1Scores, Competitor o2, + List> o2Scores, TimePoint timePoint) { + return scoringScheme.compareByBetterScore(o1, o1Scores, o2, o2Scores, nullScoresAreBetter, timePoint); } /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowPointForLeagueOverallLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowPointForLeagueOverallLeaderboard.java new file mode 100644 index 00000000000..282efc8d03c --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/LowPointForLeagueOverallLeaderboard.java @@ -0,0 +1,57 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + + + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.leaderboard.meta.MetaLeaderboardColumn; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; + + +/** + * To be used for national sailing leagues' overall (season) leaderboard. Ties are broken by comparing the point sums + * of the act leaderboards. When those are equal, too, the regatta rank during the last act is used to break the tie. + * + * @author Axel Uhl (D043530) + * + */ +public class LowPointForLeagueOverallLeaderboard extends LowPoint { + private static final long serialVersionUID = -2767385186133743330L; + + public LowPointForLeagueOverallLeaderboard() { + super(); + } + + @Override + public ScoringSchemeType getType() { + return ScoringSchemeType.LOW_POINT_LEAGUE_OVERALL; + } + + /** + * When this method is called, we can assume that the points sum for both competitors is equal. + * + */ + @Override + public int compareByBetterScore(Competitor o1, List> o1Scores, + Competitor o2, List> o2Scores, boolean nullScoresAreBetter, TimePoint timePoint) { + final Double o1ScoreSum = o1Scores.stream().collect(Collectors.summingDouble(rcAndScore->rcAndScore.getB())); + final Double o2ScoreSum = o2Scores.stream().collect(Collectors.summingDouble(rcAndScore->rcAndScore.getB())); + assert Math.abs(o1ScoreSum - o2ScoreSum) < 0.00001; + assert o1Scores.stream().allMatch(rcAndScore->rcAndScore.getA() instanceof MetaLeaderboardColumn); + assert o2Scores.stream().allMatch(rcAndScore->rcAndScore.getA() instanceof MetaLeaderboardColumn); + double totalPointsSumO1 = getTotalPoints(o1, o1Scores.stream().map(rcAndScore->rcAndScore.getA()), timePoint); + double totalPointsSumO2 = getTotalPoints(o2, o1Scores.stream().map(rcAndScore->rcAndScore.getA()), timePoint); + return getScoreComparator(nullScoresAreBetter).compare(totalPointsSumO1, totalPointsSumO2); + } + + private double getTotalPoints(Competitor competitor, Stream raceColumns, TimePoint timePoint) { + return raceColumns.collect(Collectors.summingDouble(rc->((MetaLeaderboardColumn) rc).getLeaderboard().getTotalPoints(competitor, timePoint))); + } +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index ea5f9fc74a9..491b73ff655 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -42,7 +42,7 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R return null; } - Leaderboard getLeaderboard() { + public Leaderboard getLeaderboard() { return leaderboard; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/WaypointPositionAndDistanceCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/WaypointPositionAndDistanceCache.java index 414ec6be360..cf4d3fad43b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/WaypointPositionAndDistanceCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/impl/WaypointPositionAndDistanceCache.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.markpassingcalculation.impl; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -194,13 +195,14 @@ public class WaypointPositionAndDistanceCache { if (map != null) { final SortedMap tailMap = map.tailMap(roundToResolution(affectedTimeRange.from())); synchronized (map) { - for (Entry e : tailMap.entrySet()) { + for (Iterator> i=tailMap.entrySet().iterator(); i.hasNext(); ) { + final Entry e = i.next(); final TimePoint timePoint = e.getKey(); if (timePoint.after(affectedTimeRange.to())) { break; } assert timePoint.equals(roundToResolution(timePoint)); - map.remove(timePoint); + i.remove(); synchronized (waypoints) { for (Waypoint otherWaypoint : waypoints) { ControlPoint otherControlPoint = otherWaypoint.getControlPoint(); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 225bda30bb9..290b6e31eb1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -877,5 +877,4 @@ public interface TrackedRace extends Serializable, IsManagedByCache getMarksFromRaceAndLogs() { return getMarks(); } - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java index e7f6e5be169..72e6933c475 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceChangeListener.java @@ -113,5 +113,4 @@ public abstract class AbstractRaceChangeListener implements RaceChangeListener { public void waypointRemoved(int zeroBasedIndex, Waypoint waypointThatGotRemoved) { defaultAction(); } - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceRankComparator.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceRankComparator.java index a3fc907c059..b300696e9b8 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceRankComparator.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/AbstractRaceRankComparator.java @@ -5,6 +5,7 @@ import java.util.Comparator; import java.util.List; import java.util.NavigableSet; import java.util.SortedSet; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; import com.sap.sailing.domain.base.Competitor; @@ -14,6 +15,7 @@ import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util.Pair; /** * Compares two competitors by their ranking in the overall race for a given time point. Competitors who haven't started @@ -43,6 +45,11 @@ public abstract class AbstractRaceRankComparator> implem private final TimePoint timePoint; private final DummyMarkPassingWithTimePointOnly markPassingWithTimePoint; private final boolean lessIsBetter; + private final ConcurrentHashMap lastMarkPassingBeforeTimePoint; + private final ConcurrentHashMap currentLeg; + + private final MarkPassing NULL_MARK_PASSING = new MarkPassingImpl(null, null, null); + private final TrackedLegOfCompetitor NULL_TRACKED_LEG_OF_COMPETITOR = new TrackedLegOfCompetitorImpl(null, null); /** * @param lessIsBetter @@ -55,6 +62,8 @@ public abstract class AbstractRaceRankComparator> implem this.timePoint = timePoint; this.markPassingWithTimePoint = new DummyMarkPassingWithTimePointOnly(timePoint); this.lessIsBetter = lessIsBetter; + this.lastMarkPassingBeforeTimePoint = new ConcurrentHashMap<>(); + this.currentLeg = new ConcurrentHashMap<>(); } protected TimePoint getTimePoint() { @@ -65,6 +74,38 @@ public abstract class AbstractRaceRankComparator> implem return trackedRace; } + private Pair getLastMarkPassingBeforeTimePointAndCurrentLeg(Competitor competitor) { + final TrackedLegOfCompetitor currentLegForCompetitor; + final MarkPassing lastMarkPassingBeforeTimePointForCompetitor; + if (lastMarkPassingBeforeTimePoint.containsKey(competitor)) { + final MarkPassing markPassingFromMap = lastMarkPassingBeforeTimePoint.get(competitor); + lastMarkPassingBeforeTimePointForCompetitor = markPassingFromMap == NULL_MARK_PASSING ? null : markPassingFromMap; + final TrackedLegOfCompetitor trackedLegOfCompetitorFromMap = currentLeg.get(competitor); + currentLegForCompetitor = trackedLegOfCompetitorFromMap == NULL_TRACKED_LEG_OF_COMPETITOR ? null : trackedLegOfCompetitorFromMap; + } else { + NavigableSet o1MarkPassings = trackedRace.getMarkPassings(competitor); + NavigableSet o1MarkPassingsBeforeTimePoint; + trackedRace.lockForRead(o1MarkPassings); + try { + o1MarkPassingsBeforeTimePoint = o1MarkPassings.headSet(markPassingWithTimePoint, /* inclusive */true); + final int o1MarkPassingsBeforeTimePointSize = o1MarkPassingsBeforeTimePoint.size(); + if (o1MarkPassingsBeforeTimePointSize > 0) { + lastMarkPassingBeforeTimePointForCompetitor = o1MarkPassingsBeforeTimePoint.last(); + } else { + lastMarkPassingBeforeTimePointForCompetitor = null; + } + currentLegForCompetitor = trackedRace.getCurrentLeg(competitor, timePoint); + // cache the results of analyzing the mark passings: + lastMarkPassingBeforeTimePoint.put(competitor, lastMarkPassingBeforeTimePointForCompetitor == null ? + NULL_MARK_PASSING : lastMarkPassingBeforeTimePointForCompetitor); + currentLeg.put(competitor, currentLegForCompetitor == null ? NULL_TRACKED_LEG_OF_COMPETITOR : currentLegForCompetitor); + } finally { + trackedRace.unlockAfterRead(o1MarkPassings); + } + } + return new Pair<>(lastMarkPassingBeforeTimePointForCompetitor, currentLegForCompetitor); + } + @Override public int compare(Competitor o1, Competitor o2) { int result; @@ -72,40 +113,14 @@ public abstract class AbstractRaceRankComparator> implem result = 0; } else { final Course course = trackedRace.getRace().getCourse(); - NavigableSet o1MarkPassings = trackedRace.getMarkPassings(o1); - NavigableSet o1MarkPassingsBeforeTimePoint; - MarkPassing o1LastMarkPassingBeforeTimePoint = null; - int o1MarkPassingsBeforeTimePointSize; - TrackedLegOfCompetitor o1Leg; - trackedRace.lockForRead(o1MarkPassings); - try { - // FIXME for the XMLExportTest.testExportingESSNice2014 the "inclusive" parameter doesn't seem to work properly; problem is caused by the MarkPassingByTimeComparator falling back to competitor ID if times are equal - o1MarkPassingsBeforeTimePoint = o1MarkPassings.headSet( - markPassingWithTimePoint, /* inclusive */true); - o1MarkPassingsBeforeTimePointSize = o1MarkPassingsBeforeTimePoint.size(); - if (o1MarkPassingsBeforeTimePointSize > 0) { - o1LastMarkPassingBeforeTimePoint = o1MarkPassingsBeforeTimePoint.last(); - } - o1Leg = trackedRace.getCurrentLeg(o1, timePoint); - } finally { - trackedRace.unlockAfterRead(o1MarkPassings); - } - NavigableSet o2MarkPassings = trackedRace.getMarkPassings(o2); - NavigableSet o2MarkPassingsBeforeTimePoint; - MarkPassing o2LastMarkPassingBeforeTimePoint = null; - int o2MarkPassingsBeforeTimePointSize; - TrackedLegOfCompetitor o2Leg; - trackedRace.lockForRead(o2MarkPassings); - try { - o2MarkPassingsBeforeTimePoint = o2MarkPassings.headSet(markPassingWithTimePoint, /* inclusive */true); - o2MarkPassingsBeforeTimePointSize = o2MarkPassingsBeforeTimePoint.size(); - if (o2MarkPassingsBeforeTimePointSize > 0) { - o2LastMarkPassingBeforeTimePoint = o2MarkPassingsBeforeTimePoint.last(); - } - o2Leg = trackedRace.getCurrentLeg(o2, timePoint); - } finally { - trackedRace.unlockAfterRead(o2MarkPassings); - } + final TrackedLegOfCompetitor o1Leg; + final MarkPassing o1LastMarkPassingBeforeTimePoint; + Pair lastMarkPassingBeforeTimePointAndCurrentLegForO1 = getLastMarkPassingBeforeTimePointAndCurrentLeg(o1); + o1LastMarkPassingBeforeTimePoint = lastMarkPassingBeforeTimePointAndCurrentLegForO1.getA(); + o1Leg = lastMarkPassingBeforeTimePointAndCurrentLegForO1.getB(); + Pair lastMarkPassingBeforeTimePointAndCurrentLegForO2 = getLastMarkPassingBeforeTimePointAndCurrentLeg(o2); + final MarkPassing o2LastMarkPassingBeforeTimePoint = lastMarkPassingBeforeTimePointAndCurrentLegForO2.getA(); + final TrackedLegOfCompetitor o2Leg = lastMarkPassingBeforeTimePointAndCurrentLegForO2.getB(); final List legs = course.getLegs(); result = o1LastMarkPassingBeforeTimePoint == null ? o2LastMarkPassingBeforeTimePoint == null ? 0 // both haven't started yet @@ -113,7 +128,7 @@ public abstract class AbstractRaceRankComparator> implem : o2LastMarkPassingBeforeTimePoint == null ? -1 // only o1 has started; o1 is better ("less") than o2 /* both have started; any difference */ : course.getIndexOfWaypoint(o2LastMarkPassingBeforeTimePoint.getWaypoint()) - /* in last waypoint passed? */ course.getIndexOfWaypoint(o1LastMarkPassingBeforeTimePoint.getWaypoint()); - if (result == 0 && o1MarkPassingsBeforeTimePointSize > 0) { + if (result == 0 && o1LastMarkPassingBeforeTimePoint != null) { assert o2LastMarkPassingBeforeTimePoint != null; // Competitors are on same leg and both have already started the first leg. // TrackedLegOfCompetitor comparison also correctly uses finish times for a leg diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java index 3867938fea5..f84eeb4889a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/DynamicTrackedRaceImpl.java @@ -678,7 +678,7 @@ DynamicTrackedRace, GPSTrackListener { final boolean result; if (takesWindFixWithTimePoint(wind.getTimePoint())) { result = getOrCreateWindTrack(windSource).add(wind); - updated(/* time point */null); // wind events shouldn't advance race time + updated(wind.getTimePoint()); triggerManeuverCacheRecalculationForAllCompetitors(); notifyListeners(wind, windSource); } else { @@ -826,5 +826,4 @@ DynamicTrackedRace, GPSTrackListener { public DynamicGPSFixTrack getTrack(Mark mark) { return (DynamicGPSFixTrack) super.getTrack(mark); } - } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java index f59c561b2e3..c522dafb9e5 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/GPSFixTrackImpl.java @@ -388,7 +388,7 @@ public class GPSFixTrackImpl extends TrackImpl } lockForRead(); try { - Util.Pair fixesForPositionEstimation = getFixesForPositionEstimation(fix.getTimePoint(), /* inclusive */ true); + Util.Pair fixesForPositionEstimation = getFixesForPositionEstimation(fix.getTimePoint(), /* inclusive */ false); final TimePoint start; if (fix.equals(fixesForPositionEstimation.getA())) { if (getLastFixBefore(fix.getTimePoint()) == null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java index 561ac2945b7..db9cbbe03cc 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedRaceImpl.java @@ -788,12 +788,21 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl public TimePoint getStartOfRace() { if (startTime == null) { for (RaceLog raceLog : attachedRaceLogs.values()) { + if (logger.isLoggable(Level.FINEST)) { + logger.finest("Analyzing race log "+raceLog+" for race "+this.getRace().getName()); + } startTime = new StartTimeFinder(raceLogResolver, raceLog).analyze().getStartTime(); if (startTime != null) { + if (logger.isLoggable(Level.FINEST)) { + logger.finest("Found start time "+startTime+" in race log "+raceLog+" for race "+this.getRace().getName()); + } break; } } if (startTime == null) { + if (logger.isLoggable(Level.FINEST)) { + logger.finest("No start time found in race logs for race "+getRace().getName()); + } startTime = getStartTimeReceived(); // If not null, check if the first mark passing for the start line is too much after the // startTimeReceived; if so, return an adjusted, later start time. @@ -812,8 +821,14 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl if (startTimeReceived2timeOfFirstMarkPassingFirstMark > MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS) { startTime = new MillisecondsTimePoint(timeOfFirstMarkPassing.asMillis() - MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS); + if (logger.isLoggable(Level.FINEST)) { + logger.finest("Using start mark passings for start time of race "+this.getRace().getName()+": "+startTime); + } } else { startTime = startTimeReceived; + if (logger.isLoggable(Level.FINEST)) { + logger.finest("Using start mark received for race "+this.getRace().getName()+": "+startTime); + } } } } else { @@ -821,6 +836,9 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl if (markPassingsForFirstWaypointInOrder != null) { startTime = calculateStartOfRaceFromMarkPassings(markPassingsForFirstWaypointInOrder, getRace().getCompetitors()); + if (startTime != null && logger.isLoggable(Level.FINEST)) { + logger.finest("Using start mark passings for start time of race "+this.getRace().getName()+": "+startTime); + } } } } @@ -945,32 +963,32 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public boolean isLive(TimePoint at) { - final Date startOfLivePeriod; - final Date endOfLivePeriod; + final TimePoint startOfLivePeriod; + final TimePoint endOfLivePeriod; if (!hasGPSData() || !hasWindData()) { startOfLivePeriod = null; endOfLivePeriod = null; } else { if (getStartOfRace() == null) { - startOfLivePeriod = getStartOfTracking().asDate(); + startOfLivePeriod = getStartOfTracking(); } else { - startOfLivePeriod = new Date(getStartOfRace().asMillis() - TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS); + startOfLivePeriod = getStartOfRace().minus(TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS); } if (getEndOfRace() == null) { if (getTimePointOfNewestEvent() != null) { - endOfLivePeriod = new Date(getTimePointOfNewestEvent().asMillis() - + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS); + endOfLivePeriod = getTimePointOfNewestEvent().plus( + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS); } else { endOfLivePeriod = null; } } else { - endOfLivePeriod = new Date(getEndOfRace().asMillis() + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS); + endOfLivePeriod = getEndOfRace().plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS); } } // if an empty timepoint is given then take the start of the race if (at == null) { - at = new MillisecondsTimePoint(startOfLivePeriod.getTime()+1); + at = startOfLivePeriod.plus(1); } // whenLastTrackedRaceWasLive is null if there is no tracked race for fleet, or the tracked race hasn't started yet at the server time @@ -978,8 +996,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl final boolean result = startOfLivePeriod != null && endOfLivePeriod != null && - startOfLivePeriod.getTime() <= at.asMillis() && - at.asMillis() <= endOfLivePeriod.getTime(); + !startOfLivePeriod.after(at) && + !at.after(endOfLivePeriod); return result; } @@ -1239,10 +1257,23 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public int getRank(Competitor competitor, TimePoint timePoint) { int result; - if (getMarkPassings(competitor).isEmpty()) { + final NavigableSet markPassings = getMarkPassings(competitor); + if (markPassings.isEmpty()) { result = 0; } else { - result = getCompetitorsFromBestToWorst(timePoint).indexOf(competitor) + 1; + final boolean hasMarkPassingAtOrBeforeTimePoint; + lockForRead(markPassings); + try { + hasMarkPassingAtOrBeforeTimePoint = markPassings.floor(new DummyMarkPassingWithTimePointOnly(timePoint)) == null; + } finally { + unlockAfterRead(markPassings); + } + if (hasMarkPassingAtOrBeforeTimePoint) { + // no mark passing at or before timePoint; competitor has not started / participated yet + result = 0; + } else { + result = getCompetitorsFromBestToWorst(timePoint).indexOf(competitor) + 1; + } } return result; } @@ -3176,8 +3207,8 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl if (log != null) { // Use the new log, that possibly contains device mappings, to load GPSFix tracks from the DB // When this tracked race is to be serialized, wait for the loading from stores to complete. - final TimePoint startOfTimeWindowToLoad = getStartOfTracking(); // TODO consider race log's startOfTracking event - final TimePoint endOfTimeWindowToLoad = getEndOfTracking(); // TODO consider race log's endOfTracking event + final TimePoint startOfTimeWindowToLoad = getStartOfTracking(); // TODO consider race log's startOfTracking event; note, however, that the log is attached only by the call to loadFixesForLog below + final TimePoint endOfTimeWindowToLoad = getEndOfTracking(); // TODO consider race log's endOfTracking event; note, however, that the log is attached only by the call to loadFixesForLog below loadFixesForLog(log, addLogToMap, startOfTimeWindowToLoad, endOfTimeWindowToLoad, waitForGPSFixesToLoad); } else { logger.severe("Got a request to attach log for an empty log!"); @@ -3288,6 +3319,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public void attachRaceLog(final RaceLog raceLog) { loadFixesForLog(raceLog, attachedRaceLogs, /* wait for fixes to load */ false); + try { + // The log is attached to the tracked race by a background thread; this method wants + // to guarantee that the log is at least really attached to the TrackedRace before returning: + waitForLoadingFromGPSFixStoreToFinishRunning(raceLog); + } catch (InterruptedException e) { + logger.log(Level.WARNING, "Interrupted while waiting for race log being attached", e); + } } @Override @@ -3333,6 +3371,13 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl @Override public void attachRegattaLog(RegattaLog regattaLog) { loadFixesForLog(regattaLog, attachedRegattaLogs, /* wait for fixes to load */ false); + try { + // The log is attached to the tracked race by a background thread; this method wants + // to guarantee that the log is at least really attached to the TrackedRace before returning: + waitForLoadingFromGPSFixStoreToFinishRunning(regattaLog); + } catch (InterruptedException e) { + logger.log(Level.WARNING, "Interrupted while waiting for race log being attached", e); + } } @Override diff --git a/java/com.sap.sailing.feature.p2build/raceanalysis.product b/java/com.sap.sailing.feature.p2build/raceanalysis.product index b1682e26616..1dead91f56d 100755 --- a/java/com.sap.sailing.feature.p2build/raceanalysis.product +++ b/java/com.sap.sailing.feature.p2build/raceanalysis.product @@ -50,6 +50,7 @@ + diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/home/shared/dispatch/CacheDispatchTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/home/shared/dispatch/CacheDispatchTest.java new file mode 100644 index 00000000000..880b5cf2a10 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/home/shared/dispatch/CacheDispatchTest.java @@ -0,0 +1,274 @@ +package com.sap.sailing.gwt.home.shared.dispatch; + +import java.net.URL; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.caching.CachingDispatch; +import com.sap.sailing.gwt.dispatch.client.caching.HasClientCacheTotalTimeToLive; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + +public class CacheDispatchTest { + + private CachingDispatch cd = new CachingDispatch(new DispatchMock(), + false, 200); + + @Test + public void testCacheCleanup() { + final ResultHolder holder = new ResultHolder(); + checkIfCached(holder, new SomeDefaultCacheAction(), 20); + checkIfCached(holder, new SomeDefaultCacheAction(), 20); + checkIfCached(holder, new SomeDefaultCacheAction(), 20); + Assert.assertEquals("One element in cache", 3, cd.ttlItemsInCache()); + wait(210); + cd.cleanupExpiredItems(); + Assert.assertEquals("No element in cache", 0, cd.ttlItemsInCache()); + } + + @Test + public void testNoCache() { + final ResultHolder holder = new ResultHolder(); + SomeNoCacheAction action = new SomeNoCacheAction(); + cd.execute(action, new SimpleCallback() { + @Override + public void onSuccess(SomeResult result) { + holder.value = result; + } + }); + wait(100); + cd.execute(action, new SimpleCallback() { + @Override + public void onSuccess(SomeResult result) { + Assert.assertNotSame("Not caching, should not be same", holder.value, result); + } + }); + } + + + + @Test + public void testDefaultCache() { + ResultHolder holder = new ResultHolder(); + SomeDefaultCacheAction action = new SomeDefaultCacheAction(); + checkIfCached(holder, action, 100); + checkIfExpired(holder, action, 110); + } + + @Test + public void testActionWithTTLLongerThanDefaultCache() { + ResultHolder holder = new ResultHolder(); + SomeDefaultProvidingTTLCacheAction action = new SomeDefaultProvidingTTLCacheAction(300); + checkIfCached(holder, action, 210); + checkIfExpired(holder, action, 100); + } + + @Test + public void testActionWithTTLShorterThanDefaultCache() { + ResultHolder holder = new ResultHolder(); + SomeDefaultProvidingTTLCacheAction action = new SomeDefaultProvidingTTLCacheAction(100); + checkIfCached(holder, action, 50); + checkIfExpired(holder, action, 60); + } + + @Test + public void testResultWithTTLShorterThanDefaultCache() { + ResultHolder holder = new ResultHolder(); + SomeResultWithTTLCacheAction action = new SomeResultWithTTLCacheAction(100); + checkIfCached(holder, action, 50); + checkIfExpired(holder, action, 60); + } + + @Test + public void testResultWithTTLLongerThanDefaultCache() { + ResultHolder holder = new ResultHolder(); + SomeResultWithTTLCacheAction action = new SomeResultWithTTLCacheAction(300); + checkIfCached(holder, action, 250); + checkIfExpired(holder, action, 60); + } + + @Test + public void testActionResultWithTTL() { + ResultHolder holder = new ResultHolder(); + SomeActionAndResultWithTTLCacheAction action = new SomeActionAndResultWithTTLCacheAction(50, 300); + checkIfCached(holder, action, 200); + checkIfExpired(holder, action, 110); + } + + private > void checkIfCached(final ResultHolder holder, + A action, int waitTime) { + cd.execute(action, new SimpleCallback() { + @Override + public void onSuccess(Result result) { + holder.value = result; + } + }); + wait(waitTime); + cd.execute(action, new SimpleCallback() { + @Override + public void onSuccess(Result result) { + Assert.assertSame("Should be the same", holder.value, result); + } + }); + } + + private > void checkIfExpired(final ResultHolder holder, + A action, int waitTime) { + wait(waitTime); + cd.execute(action, new SimpleCallback() { + @Override + public void onSuccess(Result result) { + Assert.assertNotSame("Should have expired, should not be same", holder.value, result); + } + }); + } + + private class SomeNoCacheAction implements Action { + @Override + public SomeResult execute(DispatchContextMock ctx) throws DispatchException { + return new SomeResult(); + } + } + + private class SomeDefaultCacheAction implements Action, IsClientCacheable { + private String instanceIdentifier = UUID.randomUUID().toString(); + + @Override + public SomeResult execute(DispatchContextMock ctx) throws DispatchException { + return new SomeResult(); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(instanceIdentifier); + } + } + + private class SomeDefaultProvidingTTLCacheAction extends SomeDefaultCacheAction implements IsClientCacheable, + HasClientCacheTotalTimeToLive { + private int ttl; + + public SomeDefaultProvidingTTLCacheAction(int ttl) { + this.ttl = ttl; + } + + @Override + public int cacheTotalTimeToLiveMillis() { + return ttl; + } + } + + private class SomeResultWithTTLCacheAction implements Action, + IsClientCacheable { + private String instanceIdentifier = UUID.randomUUID().toString(); + private int ttl; + + public SomeResultWithTTLCacheAction(int ttl) { + this.ttl = ttl; + } + + @Override + public SomeResultWithTTL execute(DispatchContextMock ctx) throws DispatchException { + return new SomeResultWithTTL(ttl); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(instanceIdentifier); + } + } + + private class SomeActionAndResultWithTTLCacheAction implements Action, + IsClientCacheable, + HasClientCacheTotalTimeToLive { + private String instanceIdentifier = UUID.randomUUID().toString(); + private int actionTTL; + private int resultTTL; + + public SomeActionAndResultWithTTLCacheAction(int actionTTL, int resultTTL) { + this.actionTTL = actionTTL; + this.resultTTL = resultTTL; + } + + @Override + public SomeResultWithTTL execute(DispatchContextMock ctx) throws DispatchException { + return new SomeResultWithTTL(resultTTL); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(instanceIdentifier); + } + + @Override + public int cacheTotalTimeToLiveMillis() { + return actionTTL; + } + } + + private class SomeResult implements Result { + } + + private class SomeResultWithTTL implements Result, HasClientCacheTotalTimeToLive { + private int ttl; + + public SomeResultWithTTL(int ttl) { + super(); + this.ttl = ttl; + } + + @Override + public int cacheTotalTimeToLiveMillis() { + return ttl; + } + } + + private class ResultHolder { + Result value; + } + + private class DispatchContextMock implements DispatchContext { + + @Override + public HttpServletRequest getRequest() { + return null; + } + + @Override + public URL getRequestBaseURL() throws DispatchException { + return null; + } + } + + private abstract class SimpleCallback implements AsyncCallback { + @Override + public void onFailure(Throwable caught) { + } + } + + private void wait(int millis) { + try { + Thread.sleep(millis); + } catch (Exception e) { + } + } + + private class DispatchMock implements DispatchAsync { + @Override + public > void execute(A action, + AsyncCallback callback) throws DispatchException { + action.execute(new DispatchContextMock()); + + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs b/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs index 0de4bdea8b9..d6863f1498a 100755 --- a/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs +++ b/java/com.sap.sailing.gwt.ui/.settings/org.eclipse.core.resources.prefs @@ -1,6 +1,7 @@ eclipse.preferences.version=1 encoding//src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties=UTF-8 +encoding//src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_ru.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_zh.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties=UTF-8 encoding//src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties=UTF-8 diff --git a/java/com.sap.sailing.gwt.ui/Calendar.html b/java/com.sap.sailing.gwt.ui/Calendar.html new file mode 100644 index 00000000000..c3142b49c19 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/Calendar.html @@ -0,0 +1,3 @@ + +Dummy file used to count calendar-based access to Solutions place + \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/Home.html b/java/com.sap.sailing.gwt.ui/Home.html index 5562e95e8e2..e4172f8e8a0 100644 --- a/java/com.sap.sailing.gwt.ui/Home.html +++ b/java/com.sap.sailing.gwt.ui/Home.html @@ -25,7 +25,71 @@ + @@ -35,6 +99,10 @@ Your web browser must have JavaScript enabled in order for this application to display correctly. - +

+

SAP Sailing Analytics

+

Loading, please wait...

+
+
diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index b7f5d9f3981..5eeb8e17321 100644 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -49,9 +49,10 @@ Require-Bundle: com.sap.sailing.domain, org.apache.shiro.core;bundle-version="1.2.2", com.sap.sse.gwt.theme, com.sap.sailing.news, - com.sap.sailing.polars.datamining.shared;bundle-version="1.0.0", + com.sap.sailing.polars.datamining.shared, com.sap.sailing.polars.datamining, - com.sap.sse.datamining.annotations;bundle-version="1.0.0" + com.sap.sse.datamining.annotations, + com.sap.sse.shared.android Bundle-Activator: com.sap.sailing.gwt.ui.server.Activator Bundle-ActivationPolicy: lazy Import-Package: javax.servlet;version="3.1.0", @@ -68,7 +69,10 @@ Bundle-ClassPath: WEB-INF/classes/, WEB-INF/lib/gwt-ajaxloader.jar, WEB-INF/lib/gwt-bootstrap-2.3.2.0.jar TrackLifecycle: true -Export-Package: com.sap.sailing.gwt.ui.actions, +Export-Package: com.google.gwt.user.client.rpc.core.com.sap.sailing.domain.common.confidence.impl, + com.google.gwt.user.client.rpc.core.com.sap.sailing.domain.common.impl, + com.google.gwt.user.client.rpc.core.com.sap.sailing.domain.common.tracking.impl, + com.sap.sailing.gwt.ui.actions, com.sap.sailing.gwt.ui.client, com.sap.sailing.gwt.ui.client.shared.charts, com.sap.sailing.gwt.ui.client.shared.racemap, diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch deleted file mode 100755 index 3ffcab00446..00000000000 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index 72e00c5b8b3..af074b8e973 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -73,7 +73,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/Simulator.css b/java/com.sap.sailing.gwt.ui/Simulator.css index e7e173f5e83..ada77cd9fdf 100644 --- a/java/com.sap.sailing.gwt.ui/Simulator.css +++ b/java/com.sap.sailing.gwt.ui/Simulator.css @@ -396,3 +396,716 @@ input.magnifier { -moz-border-radius: 5px; border: 1px solid #177980;} -o-border-radius: 5px; border: 1px solid #177980;} -ms-border-radius: 5px; border: 1px solid #177980;} + + + + + + + + + + + + + + + + + + + /** Add css rules here for your application. */ +/* + body #calendar:after + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; +*/ + + + * { + font-family: 'Open Sans', sans-serif; + font-size: 12px; +} + + +iframe { + display: block; + width: 100%; + height: 100%; + border: none; + overflow-y: auto; + overflow-x: hidden; +} + +.clear { + clear: both; + font-size: 1px; + height: 0px; + line-height: 0px; + margin: -1px 0 0; + width: 100%; +} + +.cover { + left: -1000px; + overflow: hidden; + position: absolute; + top: -1000px; +} + +body { + background: white; + font-family: 'Open Sans', Arial, Verdana, sans-serif; + line-height: 1; + font-size: 14px; + font-weight: 400; + margin: 0; + +} + +table td, select, button { + font-family: 'Open Sans', Arial, Verdana, sans-serif; + line-height: 1; + font-size: 14px; +} + +.contentOuterPanel { + background: #dddcdc; + margin: 0 12px 0 12px; + padding: 12px; +} + + + +/** Example rules used by the template application (remove for your app) */ +h1 { + font-size: 2em; + font-family: 'Open Sans', Arial, Verdana, sans-serif; + font-weight: 700; + color: #777777; + margin: 40px 0px 70px; + text-align: center; +} + +table { + border-collapse: separate; +} + +.CombinedWindPanelParentDiv { + padding-top: 34px; + padding-left: 10px; +} + +.TrueNorthIndicatorPanelParentDiv { + padding-top: 10px; + padding-left: 10px; +} + +.MapSimulationLegendParentDiv { + padding-bottom: 10px; + padding-right: 10px; + pointer-events: none; +} + +.MapSimulationLegend { + pointer-events: all; +} + +.RaceMap-HeaderPanel { + height: 60px; + width: 100%; + background-color: #333; + opacity: .5; +} + +.leaderboardLabel { + border-bottom: 2px solid #007dc0; + padding: 0 0 6px 0; + font-weight: 700; +} + +.refreshAndSettings { + background: #f2f2f2; + border-bottom: 2px solid #fff; + border-top: 2px solid #fff; + height: 30px; +} + +.refreshAndSettings table td { + padding: 0 10px 0 0; +} + +.refreshAndSettings table table td { + padding: 0 0 0 0; +} + +.race-name { + line-height: 1.0; +} + +.openColumn { + position: relative; + vertical-align: middle; +} + +img.openColumn { + display: block; + margin: 3px auto 3px auto !important; +} + +.breadcrumbPanel { + height: 30px; + margin: 0 12px 13px 12px; +} + +.mainPanel { + width: 100%; +} + +.raceBoardNavigation { + float: left; + margin: 9px 0 0 12px; + font-family: 'Open Sans', Arial, Verdana, sans-serif; + font-weight: 300; +} + +.raceBoardControls { + float: right; + margin: 9px 0 0 12px; + font-family: 'Open Sans', Arial, Verdana, sans-serif; + font-weight: 300; +} + +.raceBoardNavigation-navigationitem { + color: #dddcdc; + text-transform: uppercase; + font-weight: 500; + margin: 0 12px 0 0; + padding: 0 0 5px 0; +} + +.raceBoardNavigation-navigationitem:hover { + border-bottom: 4px solid #f0ab00; + color: #dddcdc; + text-decoration: none; +} + +.raceBoardNavigation-navigationitem:active { + border-bottom: 4px solid #f0ab00; + color: #dddcdc; + text-decoration: none; +} + +.competitorInfo-Canvas { + pointer-events: none; +} + +.gwt-DialogBox { + z-index: 20; +} + +.abstractChartPanel-importantMessageOfChart { + font-family: 'Open Sans', Arial, Verdana, sans-serif; + font-weight: 600; + font-size: 20px; + height: 70px; + margin: 0 auto; + padding: 49px 0 0 80px; + width: 300px; + color: #7c7c7c; + background: url(images/important-message.png) left center no-repeat; +} + +.breadcrumbPanel-NextArrow { + display: none; +} + +.errorLabel { + color: #FF0000; +} + +.raceBoardNavigation-settingsButtonPanel { + float: right; + margin: 9px 12px 0 0; +} + +.raceBoardNavigation-settingsButton { + background: url(images/settings_white.png), + url(images/btn-cta-orangeleft.png); + background-position: center, center 0; + background-repeat: no-repeat, repeat-x; + width: 27px; + height: 23px; + margin: 0 12px 0 1px; + -webkit-border-radius: 0px 3px 3px 0px; + -moz-border-radius: 0px 3px 3px 0px; + -o-border-radius: 0px 3px 3px 0px; + -ms-border-radius: 0px 3px 3px 0px; + border-radius: 0px 3px 3px 0px; +} + +.raceBoardNavigation-settingsButton:hover { + background-image: url(images/settings_white.png), + url(images/btn-cta-orangeleft.png); + background-position: center, center -30px; + background-repeat: no-repeat, repeat-x; + cursor: pointer; +} + +.raceBoardNavigation-filterButton:hover { + background-image: url(images/filter_white.png), + url(images/btn-cta-orangeleft.png); + background-position: center, center -30px; + background-repeat: no-repeat, repeat-x; + cursor: pointer; +} + +.raceBoardNavigation-innerElement { + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center + 0 transparent; + color: #FFFFFF; + cursor: pointer; + font-family: 'Open Sans', Verdana, Arial, sans-serif; + font-weight: 600; + font-size: 14px; + margin: 0 0 0 0; + padding: 2px 7px 2px 3px; + height: 18px; + display: inline-block; + text-decoration: none; + border-radius: 5px 0 0 5px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); +} + +.raceBoardNavigation-innerElement:active { + top: 1px; + position: relative; +} + +.raceBoardNavigation-innerElement:hover { + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center + -30px transparent; + cursor: pointer; +} + +.raceBoardNavigation-innerElement label { + cursor: pointer; +} + +.raceBoardNavigation-standaloneElement { + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center + 0 transparent; + color: #FFFFFF; + cursor: pointer; + font-family: 'Open Sans', Verdana, Arial, sans-serif; + font-weight: 600; + font-size: 14px; + margin: 0 0 0 0; + padding: 2px 7px 2px 3px; + height: 23px; + display: inline-block; + text-decoration: none; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + border-radius: 5px 5px 5px 5px; + +} + +.raceBoardNavigation-standaloneElement:active { + top: 1px; + position: relative; +} + +.raceBoardNavigation-standaloneElement:hover { + background: url("images/btn-cta-orangeleft.png") repeat-x scroll center + -30px transparent; + cursor: pointer; +} + +.raceBoardNavigation-standaloneElement label { + cursor: pointer; +} + +.timePanelButton { + float: left; + margin: 0 0 0 5px; +} + +.timePanelButton-SlowDown { + background-color: red !important; +} + +.timePanelButton-SpeedUp { + background-color: green !important; +} + +.playPauseButton { + padding: 0; + float: left; + width: 32px; + height: 28px; + background: url(images/viewicons/@1x/img/SAP_RV_Play_INACTIVE.png) + center no-repeat; + cursor: pointer; + border: 1px solid #cecece; + border-radius: 4px; + outline: 0; +} + +.playPauseButton:hover { + cursor: pointer; + background-color: #cecece; +} + +.playPauseButtonPause { + background: url(images/viewicons/@2x/img/SAP_RV_Pause_INACTIVE.png) 2px + 0 no-repeat; + outline: 0; + background-size: contain; +} + +.playPauseButtonPause:hover { + cursor: pointer; +} + +.backToLivePlayButton { + width: 42px; + height: 38px; + font-size: 8px; + white-space: normal; + border-radius: 4px; + border: none; + + margin-right: 23px; + margin-top: 5px; + margin-bottom: 5px; + z-index: 1; +} + +.backToLivePlayButton-Inactive { + color: #6dc021; + background-color: white; + font-weight: bold; +} + +.backToLivePlayButton-Active { + background-color: #6dc021; + color: white; + font-weight: normal; +} + +.backToLivePlayButton:hover { + border: 2px solid gray; +} + +.backToLivePlayButton:focus { + outline: 0 !important; +} + +.dockLayoutPanel div[style="position: absolute; overflow: hidden; left: 0px; right: 0px; bottom: 0px; height: 90px;"] + { + z-index: 10; +} + +.browserOptimizedMessage { + padding: 15px 0px; +} + +.trackingQuality-circle { + width: 8px; + height: 8px; + border-radius: 50%; + float: left; +} + +.circleYellow { + background: #fbba00; +} + +.circleGreen { + background: #8ab54e; +} + +.circleRed { + background: #f01010; +} + +.busyIndicator-Simple { + position: absolute; + top: 0.7em; + right: 7.4em; +} + +.busyIndicator-Circle { + +} + +.raceBoard-TitlePanel { + position: relative; + top: 10px; + z-index: 10; + color: #fff; + margin-left: auto; + margin-right: auto; +} + +.raceBoard-TitlePanel-RaceNameLabel { + font-size: 32px; + font-weight: bold; + padding: 7px; +} + +.raceBoard-Logo { + position: absolute; + top: 6px; + left: 10px; + z-index: 10; + cursor: pointer; +} + +.SideBySideComponentViewer-MainPanel { + top: 12px; +} + +.TimePanel-ShowExtended-Button { + width: 29px; + height: 28px; + float: left; + cursor: pointer; + border-radius: 4px; + border: 1px solid #ececec; +} + +.TimePanel-ShowExtended-Button-Open { + background: white url(images/arrows_bottom_black.png) center no-repeat; +} + +.TimePanel-ShowExtended-Button-Closed { + background: white url(images/arrows_top_black.png) center no-repeat; +} + +.TimePanel-ShowExtended-Button:hover { + background-color: #cecece; +} + +.TimePanel-ShowExtended-Button:focus { + outline: 0 !important; +} + +.RaceBoard-globalNavigation-Link { + display: inline; + margin-right: 3px; +} + +.RaceBoard-globalNavigation-Link a { + color: #fff; + cursor: pointer; +} + +.RaceBoard-globalNavigation-Link+.RaceBoard-globalNavigation-Link:before + { + content: ' \00bb\00a0'; +} + +.TimePanel-settingsButtonStyle { + position: absolute; + right: 0px; + z-index: 1; + border: none; +} + +.TimePanel-settingsButtonStyle:focus { + outline: 0 !important; +} + +.TimePanel-settingsButtonStyle:hover { + border: 1px solid gray; +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-multiCompetitorRaceChart + { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png), + url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-multiCompetitorRaceChart + { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png), + url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-windChart { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_INACTIVE.png), + url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-windChart { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_CompetitorCharts_GHOSTED.png), + url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 5% 50%, 95% 50% +} + +.gwt-SplitLayoutPanel-EastToggleButton-Open-leaderboard { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_Leaderboard_GHOSTED.png), + url(images/arrows_top_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-EastToggleButton-Closed-leaderboard { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_Leaderboard_INACTIVE.png), + url(images/arrows_bottom_black_small.png); + background-repeat: no-repeat, no-repeat; + background-position: 4% 50%, 96% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Closed-media, + .gwt-SplitLayoutPanel-NorthSouthToggleButton-Open-media { + background-color: white; + background-image: + url(images/viewicons/@1x/img/SAP_RV_AudioVideo_INACTIVE.png); + background-repeat: no-repeat, no-repeat; + background-position: 10% 50%, 90% 50% +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-mediaplaying { + background-image: + url(images/viewicons/@1x/img/SAP_RV_AudioVideo_GHOSTED.png); +} + +.gwt-SplitLayoutPanel-NorthSouthToggleButton-Small-media { + background-position: 5% 50%, 100% 50% !important; + margin-left: 0px !important; + padding: 2px 35px !important; +} + +@external gwt-ToggleButton-up, gwt-ToggleButton-down, gwt-ToggleButton-up-hovering, gwt-ToggleButton-down-hovering; +.gwt-ToggleButton-up, .gwt-ToggleButton-up-hovering { + background: url(images/unlock.png) center no-repeat; + margin-left: 5px; +} + +.gwt-ToggleButton-down, .gwt-ToggleButton-down-hovering { + background: url(images/lock.png) center no-repeat; + margin-left: 5px; +} + +.RegattaRaceInformation-Header { + font-family: 'Open Sans', Arial, Verdana, sans-serif; + position: relative; + left: 140px; + top: 11px; +} + +.RegattaRaceInformation-Header .RaceName-Label { + display: inline; + color: white; + margin-right: 10px; + font-size: 36px; +} + +.RegattaRaceInformation-Header .RaceSeriesAndFleet-Label { + display: inline; + color: white; + font-size: 15px; +} + +.RegattaAndRaceTime-Header { + position: absolute; + right: 10px; + top: 13px; + text-align: right; + color: white; +} + +.RegattaAndRaceTime-Header .RegattaName-Anchor { + font-size: 15px; + color: white; + text-decoration: none; + padding-left: 25px; + background-image: url(images/home.png); + background-repeat: no-repeat; + background-size: 17px; + background-position: 4px 1px; +} + +.RegattaAndRaceTime-Header .RegattaName-Anchor:hover { + text-decoration: underline; +} + +.RegattaAndRaceTime-Header .RaceTime-Label { + font-size: 15px; + margin-top: 5px; +} + +.VideoPopup-Close-Button { + border: none; +} + +.Media-Select-Button { + font-size: 15px; + font-size: 1rem; + display: inline-block; + font-weight: 400; + color: #111; + border: none; + padding: 0.5em 0.3em 0.5em 0.8em; + background-color: #fff; + -webkit-transition: background-color 0.2s; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -ms-transition: background-color 0.2s; + transition: background-color 0.2s; + width: 100%; + max-width: 25em; + text-align: left; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.Media-Select-Button:hover, .Media-Select-Button:focus { + background-color: #f0ab00; +} + +.Media-Select-Button-playing { + color: #999; +} + +.Media-Select-Button-playing:hover, .Media-Select-Button-playing:focus { + color: #fff; + background-color: #ccc; +} + +.Media-Select-Popup .dialogMiddleCenterInner { + padding: 0; +} + +.Media-Select-Popup .Caption { + padding: 4px 10px; +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/Simulator.html b/java/com.sap.sailing.gwt.ui/Simulator.html index 4af3bff6bf0..885b59b88fa 100644 --- a/java/com.sap.sailing.gwt.ui/Simulator.html +++ b/java/com.sap.sailing.gwt.ui/Simulator.html @@ -16,6 +16,7 @@ + diff --git a/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml b/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml index 2b0f287cf70..fd843218017 100755 --- a/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml +++ b/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml @@ -76,21 +76,12 @@ Dispatch Service DispatchService - com.sap.sailing.gwt.ui.server.dispatch.DispatchRPCImpl + com.sap.sailing.gwt.home.server.servlets.DispatchRPCServletImpl DispatchService /service/dispatch - - Home Service - HomeService - com.sap.sailing.gwt.server.HomeServiceImpl - - - HomeService - /service/home - Media Service diff --git a/java/com.sap.sailing.gwt.ui/build.properties b/java/com.sap.sailing.gwt.ui/build.properties index 9a0247eb1d6..cfe0cb51c33 100644 --- a/java/com.sap.sailing.gwt.ui/build.properties +++ b/java/com.sap.sailing.gwt.ui/build.properties @@ -50,5 +50,6 @@ bin.includes = META-INF/,\ SettingsDialog.css,\ EmbeddedMapAndWindChart.css,\ EmbeddedMapAndWindChart.html,\ - com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/ + com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart/,\ + Calendar.html output.. = WEB-INF/classes/ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-post-trimmed.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-post-trimmed.png new file mode 100644 index 00000000000..afd31c1255c Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/solutions-post-trimmed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-post.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-post.png index 181ffb806e1..3b0041761b4 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/home/solutions-post.png and b/java/com.sap.sailing.gwt.ui/images/home/solutions-post.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-in-sailing.jpg b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-in-sailing.jpg new file mode 100644 index 00000000000..21e0e622b58 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-in-sailing.jpg differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-sailing-race-manager.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-sailing-race-manager.png new file mode 100644 index 00000000000..04d33096e98 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-sailing-race-manager.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-trimmed.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-trimmed.png new file mode 100644 index 00000000000..d835a09e7ec Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap-trimmed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-sap.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap.png index b91eedd8ec4..ff24be6578b 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/home/solutions-sap.png and b/java/com.sap.sailing.gwt.ui/images/home/solutions-sap.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator-trimmed.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator-trimmed.png new file mode 100644 index 00000000000..522e7eeedd4 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator-trimmed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator.png index a1e9beb92f0..3b22e87b67d 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator.png and b/java/com.sap.sailing.gwt.ui/images/home/solutions-simulator.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/home/solutions-training.png b/java/com.sap.sailing.gwt.ui/images/home/solutions-training.png index 8ad053dacb7..f3369a8714a 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/home/solutions-training.png and b/java/com.sap.sailing.gwt.ui/images/home/solutions-training.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/filter.svg b/java/com.sap.sailing.gwt.ui/images/mobile/filter.svg new file mode 100644 index 00000000000..c02f4b9b5fc --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/images/mobile/filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/search-icon-yellow.svg b/java/com.sap.sailing.gwt.ui/images/mobile/search-icon-yellow.svg new file mode 100644 index 00000000000..6ef96c3805d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/images/mobile/search-icon-yellow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-post.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-post.png new file mode 100644 index 00000000000..181ffb806e1 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-post.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-race.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-race.png new file mode 100644 index 00000000000..04d33096e98 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-race.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-in-sailing.jpg b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-in-sailing.jpg new file mode 100644 index 00000000000..21e0e622b58 Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-in-sailing.jpg differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-trimmed.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-trimmed.png index d835a09e7ec..7ddb8892e5c 100644 Binary files a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-trimmed.png and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap-trimmed.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap.png new file mode 100644 index 00000000000..be54e426e8e Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-sap.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-simulator.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-simulator.png new file mode 100644 index 00000000000..9123f6fccaf Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-simulator.png differ diff --git a/java/com.sap.sailing.gwt.ui/images/mobile/solutions-training.png b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-training.png new file mode 100644 index 00000000000..f3369a8714a Binary files /dev/null and b/java/com.sap.sailing.gwt.ui/images/mobile/solutions-training.png differ diff --git a/java/com.sap.sailing.gwt.ui/pom.xml b/java/com.sap.sailing.gwt.ui/pom.xml index d51dd03da2b..47a3ef69008 100755 --- a/java/com.sap.sailing.gwt.ui/pom.xml +++ b/java/com.sap.sailing.gwt.ui/pom.xml @@ -1,227 +1,211 @@ - 4.0.0 - - root - com.sap.sailing - 1.0.0-SNAPSHOT - - com.sap.sailing.gwt.ui - eclipse-plugin + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + 4.0.0 + + root + com.sap.sailing + 1.0.0-SNAPSHOT + + com.sap.sailing.gwt.ui + eclipse-plugin - - - sonatype - http://oss.sonatype.org/content/repositories/snapshots - - true - - - false - - - + + + + com.google.gwt + gwt-user + ${gwt.version} + + + com.google.gwt + gwt-dev + ${gwt.version} + + + javax.validation + validation-api + 1.0.0.GA + + + javax.validation + validation-api + 1.0.0.GA + sources + + + + com.github.branflake2267 + gwt-maps-api + 3.9.0-build-17 + provided + + + org.moxieapps.gwt + org.moxieapps.gwt.highcharts + 1.6.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sailing.domain.common + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.common + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.gwt + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.gwt.theme + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.gwt.adminconsole + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sailing.datamining.shared + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.datamining.shared + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.datamining.annotations + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sailing.polars.datamining.shared + 1.0.0-SNAPSHOT + sources + + + com.github.gwtbootstrap + gwt-bootstrap + 2.3.2.0 + provided + + + com.sap.sailing + com.sap.sse.security.common + 1.0.0-SNAPSHOT + sources + + + com.sap.sailing + com.sap.sse.security.ui + 1.0.0-SNAPSHOT + sources + - - - - com.google.gwt - gwt-user - ${gwt.version} - - - com.google.gwt - gwt-dev - ${gwt.version} - - - javax.validation - validation-api - 1.0.0.GA - - - javax.validation - validation-api - 1.0.0.GA - sources - - - - com.github.branflake2267 - gwt-maps-api - 3.9.0-build-17 - provided - - - org.moxieapps.gwt - org.moxieapps.gwt.highcharts - 1.6.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sailing.domain.common - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.common - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.gwt - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.gwt.theme - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.gwt.adminconsole - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sailing.datamining.shared - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.datamining.shared - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.datamining.annotations - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sailing.polars.datamining.shared - 1.0.0-SNAPSHOT - sources - - - com.github.gwtbootstrap - gwt-bootstrap - 2.3.2.0 - provided - - - com.sap.sailing - com.sap.sse.security.common - 1.0.0-SNAPSHOT - sources - - - com.sap.sailing - com.sap.sse.security.ui - 1.0.0-SNAPSHOT - sources - - + - - - - org.codehaus.mojo - gwt-maven-plugin - ${gwt.version} - - - - - - - com.sap.sailing.gwt.home.Home - com.sap.sailing.gwt.AutoPlay - com.sap.sailing.gwt.ui.AdminConsole - com.sap.sailing.gwt.ui.Leaderboard - com.sap.sailing.gwt.ui.LeaderboardEditing - com.sap.sailing.gwt.ui.RaceBoard - com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart - com.sap.sailing.gwt.ui.Spectator - com.sap.sailing.gwt.ui.DataMining - com.sap.sailing.gwt.ui.VideoPopup - com.sap.sailing.gwt.ui.YoutubePopup - com.sap.sailing.gwt.ui.Simulator - com.sap.sailing.gwt.regattaoverview.RegattaOverview - - - ${basedir}/.generated - ${basedir} - ${basedir}/src/main/resources - - - - compile - - - - - - org.eclipse.tycho - tycho-source-plugin - ${tycho-version} - - - plugin-source - generate-sources - - plugin-source - - - - - - + + + + org.codehaus.mojo + gwt-maven-plugin + ${gwt.version} + + + + + + + com.sap.sailing.gwt.home.Home + com.sap.sailing.gwt.AutoPlay + com.sap.sailing.gwt.ui.AdminConsole + com.sap.sailing.gwt.ui.Leaderboard + com.sap.sailing.gwt.ui.LeaderboardEditing + com.sap.sailing.gwt.ui.RaceBoard + com.sap.sailing.gwt.ui.EmbeddedMapAndWindChart + com.sap.sailing.gwt.ui.Spectator + com.sap.sailing.gwt.ui.DataMining + com.sap.sailing.gwt.ui.VideoPopup + com.sap.sailing.gwt.ui.YoutubePopup + com.sap.sailing.gwt.ui.Simulator + com.sap.sailing.gwt.regattaoverview.RegattaOverview + + + ${basedir}/.generated + ${basedir} + ${basedir}/src/main/resources + + + + compile + + + + + + org.eclipse.tycho + tycho-source-plugin + ${tycho-version} + + + plugin-source + generate-sources + + plugin-source + + + + + + - - - debug.no-gwt-compile - - - - org.codehaus.mojo - gwt-maven-plugin - ${gwt.version} - - - - - - - - help - - - - - - - - + + + debug.no-gwt-compile + + + + org.codehaus.mojo + gwt-maven-plugin + ${gwt.version} + + + + + + + + help + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/AutoPlayEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/AutoPlayEntryPoint.java index d6b674c0376..ad1a8fc43ad 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/AutoPlayEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/AutoPlayEntryPoint.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.autoplay.client; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Document; import com.sap.sailing.gwt.autoplay.client.app.AutoPlayAppActivityMapper; import com.sap.sailing.gwt.autoplay.client.app.AutoPlayAppClientFactory; import com.sap.sailing.gwt.autoplay.client.app.AutoPlayAppHistoryMapper; @@ -8,7 +9,7 @@ import com.sap.sailing.gwt.common.client.SharedResources; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.mvp.AbstractMvpEntryPoint; -public class AutoPlayEntryPoint extends AbstractMvpEntryPoint { +public class AutoPlayEntryPoint extends AbstractMvpEntryPoint { @Override public void doOnModuleLoad() { @@ -19,6 +20,7 @@ public class AutoPlayEntryPoint extends AbstractMvpEntryPoint { SharedResources.INSTANCE.mediaCss().ensureInjected(); SharedResources.INSTANCE.mainCss().ensureInjected(); + Document.get().getBody().addClassName(SharedResources.INSTANCE.mainCss().desktop()); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AbstractApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AbstractApplicationClientFactory.java index 0206ea11105..f041d9ef79f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AbstractApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AbstractApplicationClientFactory.java @@ -6,8 +6,6 @@ import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.web.bindery.event.shared.EventBus; import com.sap.sailing.gwt.autoplay.client.place.start.StartPlace; -import com.sap.sailing.gwt.ui.client.HomeService; -import com.sap.sailing.gwt.ui.client.HomeServiceAsync; import com.sap.sailing.gwt.ui.client.MediaService; import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; @@ -16,9 +14,8 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.security.ui.client.SecureClientFactoryImpl; -public abstract class AbstractApplicationClientFactory extends SecureClientFactoryImpl implements AutoPlayAppClientFactory { +public abstract class AbstractApplicationClientFactory extends SecureClientFactoryImpl implements AutoPlayAppClientFactory { private final SailingServiceAsync sailingService; - private final HomeServiceAsync homeService; private final MediaServiceAsync mediaService; private final PlaceNavigator navigator; @@ -26,10 +23,8 @@ public abstract class AbstractApplicationClientFactory extends SecureClientFacto super(root, eventBus, placeController); this.navigator = navigator; sailingService = GWT.create(SailingService.class); - homeService = GWT.create(HomeService.class); mediaService = GWT.create(MediaService.class); EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.sailingServiceRemotePath); - EntryPointHelper.registerASyncService((ServiceDefTarget) homeService, RemoteServiceMappingConstants.homeServiceRemotePath); EntryPointHelper.registerASyncService((ServiceDefTarget) mediaService, RemoteServiceMappingConstants.mediaServiceRemotePath); } @@ -43,11 +38,6 @@ public abstract class AbstractApplicationClientFactory extends SecureClientFacto return sailingService; } - @Override - public HomeServiceAsync getHomeService() { - return homeService; - } - @Override public MediaServiceAsync getMediaService() { return mediaService; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/DesktopApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/DesktopApplicationClientFactory.java index 9afbe0f941d..385c239708c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/DesktopApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/DesktopApplicationClientFactory.java @@ -41,4 +41,5 @@ public class DesktopApplicationClientFactory extends AbstractApplicationClientFa public ErrorView createErrorView(String errorMessage, Throwable errorReason) { return null; } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java index bddc64aa4e8..5cfe4fe6697 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/place/player/AutoPlayController.java @@ -12,10 +12,13 @@ import com.google.gwt.dom.client.Style.FontWeight; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; @@ -37,6 +40,7 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel; import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; +import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -162,12 +166,13 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { } } - private RaceBoardPanel createRaceBoardPanel(String leaderboardName, RegattaAndRaceIdentifier raceToShow) { + private RaceBoardPanel createRaceBoardPanel(String leaderboardName, RegattaAndRaceIdentifier raceToShow, Map competitorsAndTheirBoats) { RaceSelectionModel raceSelectionModel = new RaceSelectionModel(); List singletonList = Collections.singletonList(raceToShow); raceSelectionModel.setSelection(singletonList); + RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, userService, asyncActionsExecutor, - raceboardTimer, raceSelectionModel, leaderboardName, null, /* event */null, raceboardViewConfig, + competitorsAndTheirBoats, raceboardTimer, raceSelectionModel, leaderboardName, null, /* event */null, raceboardViewConfig, errorReporter, StringMessages.INSTANCE, userAgent, raceTimesInfoProvider, /* showMapControls */false); return raceBoardPanel; } @@ -279,23 +284,35 @@ public class AutoPlayController implements RaceTimesInfoProviderListener { private void showRaceBoard() { if (activeTvView != AutoPlayModes.Raceboard) { - playerView.clear(); - RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace); - raceBoardPanel.setSize("100%", "100%"); - if (showWindChart) { - raceBoardPanel.setWindChartVisible(true); - } - FlowPanel timePanel = createTimePanel(raceBoardPanel); + sailingService.getRaceboardData(currentLiveRace.getRegattaName(), currentLiveRace.getRaceName(), + leaderboardName, null, null, new AsyncCallback() { + @Override + public void onSuccess(RaceboardDataDTO result) { + playerView.clear(); + RaceBoardPanel raceBoardPanel = createRaceBoardPanel(leaderboardName, currentLiveRace, result.getCompetitorAndTheirBoats()); + raceBoardPanel.setSize("100%", "100%"); + if (showWindChart) { + raceBoardPanel.setWindChartVisible(true); + } + FlowPanel timePanel = createTimePanel(raceBoardPanel); + + final Button toggleButton = raceBoardPanel.getTimePanel().getAdvancedToggleButton(); + toggleButton.setVisible(false); + playerView.getDockPanel().addSouth(timePanel, 67); + playerView.getDockPanel().add(raceBoardPanel); + activeTvView = AutoPlayModes.Raceboard; + leaderboardTimer.pause(); + raceboardTimer.setPlayMode(PlayModes.Live); + + isInitialScreen = false; + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error while loading data for raceboard: " + caught.getMessage()); + } + }); - final Button toggleButton = raceBoardPanel.getTimePanel().getAdvancedToggleButton(); - toggleButton.setVisible(false); - playerView.getDockPanel().addSouth(timePanel, 67); - playerView.getDockPanel().add(raceBoardPanel); - activeTvView = AutoPlayModes.Raceboard; - leaderboardTimer.pause(); - raceboardTimer.setPlayMode(PlayModes.Live); - - isInitialScreen = false; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/AbstractBasePlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/AbstractBasePlace.java index 2ce01ba4d7a..013cf9b0957 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/AbstractBasePlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/AbstractBasePlace.java @@ -46,14 +46,11 @@ public abstract class AbstractBasePlace extends Place { public AbstractBasePlace(String url) { if (url != null && !url.isEmpty()) { this.placeParametersAsToken = url; - List list = Arrays.asList(placeParametersAsToken.split("&")); - if (list == null || list.size() < 1) { logger.warning("Token empty, no-op"); return; } - for (String listItem : list) { List nvPair = Arrays.asList(listItem.split("=")); if (nvPair == null || nvPair.size() != 2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/DateUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/DateUtil.java index 758b10af4ec..2643ce45026 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/DateUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/DateUtil.java @@ -31,11 +31,11 @@ public class DateUtil { } public static boolean isSameDayOfMonth(Date date1, Date date2) { - return getMonth(date1) == getMonth(date2); + return isSameMonth(date1, date2) && getDayOfMonth(date1) == getDayOfMonth(date2); } public static boolean isSameMonth(Date date1, Date date2) { - return getMonth(date1) == getMonth(date2); + return isSameYear(date1, date2) && getMonth(date1) == getMonth(date2); } public static boolean isSameYear(Date date1, Date date2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/SharedResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/SharedResources.java index 96c0bec53cf..3430d1a0c71 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/SharedResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/SharedResources.java @@ -14,6 +14,8 @@ public interface SharedResources extends ClientBundle { MediaCss mediaCss(); public interface MainCss extends CssResource{ + String mobile(); + String desktop(); String wrapper(); String navbar(); String navbar_button(); @@ -65,6 +67,7 @@ public interface SharedResources extends ClientBundle { String slideto(); String slidetonav(); String slidetoactive(); + String fleetcorner(); } public interface MediaCss extends CssResource{ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/BreadcrumbPane.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/BreadcrumbPane.java index 6961adfc4f0..c8d5e228892 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/BreadcrumbPane.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/BreadcrumbPane.java @@ -77,4 +77,8 @@ public class BreadcrumbPane extends Widget { } }); } + + public void clear() { + breadcrumDiv.removeAllChildren(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.java index b9d96dc2a80..be2cd7fb6ed 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.java @@ -7,6 +7,8 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Style.Display; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.place.shared.Place; @@ -22,6 +24,7 @@ import com.google.gwt.user.client.ui.IsWidget; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView.State; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; /** * Defines whole layout for site, including the header with the breadcrumbs and tab bar, and the content. @@ -42,6 +45,7 @@ public class TabPanel extends Composite { @UiField TabBar tabBar; @UiField BreadcrumbPane breadcrumbs; + @UiField DivElement breadcrumbsContainer; @UiField FlowPanel tabExtension; private TabView currentTab; @@ -53,6 +57,10 @@ public class TabPanel extends Composite { this.presenter = presenter; this.historyMapper = historyMapper; initWidget(ourUiBinder.createAndBindUi(this)); + + if(ExperimentalFeatures.USE_NAVIGATION_PATH_DISPLAY_ON_DESKTOP) { + breadcrumbsContainer.getStyle().setDisplay(Display.NONE); + } } public TabView getCurrentTab() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.ui.xml index b32798c6160..2d9d1fe3279 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/controls/tabbar/TabPanel.ui.xml @@ -35,14 +35,10 @@ float: right; margin-left: 0.5em; } - .busy { - width: 32px; - margin: 2em auto 10em; - } -
+
@@ -58,8 +54,6 @@
- - + addStyleNames="{style.content}" /> \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceCategory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceCategory.java new file mode 100644 index 00000000000..819cd4fa9cc --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceCategory.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.common.client.formfactor; + +public enum DeviceCategory { + DESKTOP, + TABLET, + MOBILE +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceDetector.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceDetector.java new file mode 100644 index 00000000000..5569893e62b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/DeviceDetector.java @@ -0,0 +1,69 @@ +package com.sap.sailing.gwt.common.client.formfactor; + +import java.util.logging.Logger; + +import com.google.gwt.regexp.shared.RegExp; +import com.google.gwt.user.client.Window.Navigator; + +public class DeviceDetector { + private static Logger LOG = Logger.getLogger(DeviceDetector.class.getName()); + + private static final RegExp isMobileRegExp = RegExp.compile( + "Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile Safari", "i"); + private static final RegExp tabletBlacklistRegExp = RegExp.compile( + "iPad|" // Apple ;-) + + "Nexus 7|Nexus 10|Nexus 9|" // Google Tablets + + "PlayBook|" // Blackberry + + "KFAPWI|" // Kindle Fire HD + + "FZ-B|" // Panasonic ToughPad + + "SGP|" // Sony Xperia Tablets + + "GT-P|SM-T|SM-P|" // Galaxy Tab (https://en.wikipedia.org/wiki/Samsung_Galaxy ; http://forum.xda-developers.com/wiki/Samsung/Model_naming_scheme) + + "Tablet" // Firefox on Android + , "i"); + + private static DeviceCategory deviceCategory; + public static DeviceCategory getDeviceCategory() { + if(deviceCategory == null) { + deviceCategory = calculateDeviceCategory(); + } + return deviceCategory; + } + + private static DeviceCategory calculateDeviceCategory() { + boolean isMobile = isMobileRegExp.test(Navigator.getUserAgent()); + LOG.info("Navigator user agent matched mobile regex: " + isMobile); + if(!isMobile) { + return DeviceCategory.DESKTOP; + } + boolean isTablet = tabletBlacklistRegExp.test(Navigator.getUserAgent()); + LOG.info("Navigator user agent matched tablet regex: " + isTablet); + return isTablet ? DeviceCategory.TABLET : DeviceCategory.MOBILE; + } + + /** + * Uses regular expression and user agent to detect mobile device. + * + * @return + */ + public static boolean isMobile() { + return getDeviceCategory() == DeviceCategory.MOBILE; + } + + /** + * Uses regular expression and user agent to detect tablet device. + * + * @return + */ + public static boolean isTablet() { + return getDeviceCategory() == DeviceCategory.TABLET; + } + + /** + * Convinience method + * + * @return + */ + public static boolean isDesktop() { + return getDeviceCategory() == DeviceCategory.DESKTOP; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/MetaTagUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/MetaTagUtil.java new file mode 100644 index 00000000000..35590d255d6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/formfactor/MetaTagUtil.java @@ -0,0 +1,64 @@ +package com.sap.sailing.gwt.common.client.formfactor; + +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.HeadElement; +import com.google.gwt.dom.client.MetaElement; +import com.sap.sse.common.Util; + +/** + * Utility class to add meta tags to the {@link Document#getHead() document head}. + */ +public abstract class MetaTagUtil { + + private static final String TAG_NAME_VIEWPORT = "viewport"; + + private static final String CONTENT_SEPARATOR = ","; + private static final String CONTENT_PROPERTY_VALUE_SEPARATOR = "="; + + private static final String CONTENT_PROPERTY_WIDTH = "width"; + private static final String CONTENT_PROPERTY_INITIAL_SCALE = "initial-scale"; + private static final String CONTENT_PROPERTY_MAXIMUM_SCALE = "maximum-scale"; + + public static final String WIDTH_VALUE_DEVICE_WIDTH = "device-width"; + public static final String SCALE_VALUE_SMALL = "0.5"; + public static final String SCALE_VALUE_SMALLER = "0.75"; + public static final String SCALE_VALUE_NORMAL = "1"; + public static final String SCALE_VALUE_LARGE = "2"; + + /** + * Appends a {@code viewport} meta tag to the {@link HeadElement head} using {@code width=device-width}. + * + * @param initialScaleValue value to use for meta tag content property {@code initial-scale} + * @param maximumScaleValue value to use for meta tag content property {@code maximum-scale} + * + * @see MetaTagUtil#setViewport(String, String, String) + */ + public static void setViewportToDeviceWidth(String initialScaleValue, String maximumScaleValue) { + MetaTagUtil.setViewport(WIDTH_VALUE_DEVICE_WIDTH, initialScaleValue, maximumScaleValue); + } + + /** + * Appends a {@code viewport} meta tag to the {@link HeadElement head}. + * + * @param widthValue value to use for meta tag content property {@code width} + * @param initialScaleValue value to use for meta tag content property {@code initial-scale} + * @param maximumScaleValue value to use for meta tag content property {@code maximum-scale} + */ + public static void setViewport(String widthValue, String initialScaleValue, String maximumScaleValue) { + String width = content(CONTENT_PROPERTY_WIDTH, widthValue); + String initialScale = content(CONTENT_PROPERTY_INITIAL_SCALE, initialScaleValue); + String maximumScale = content(CONTENT_PROPERTY_MAXIMUM_SCALE, maximumScaleValue); + appendMetaElement(TAG_NAME_VIEWPORT, Util.join(CONTENT_SEPARATOR, width, initialScale, maximumScale)); + } + + private static String content(String property, String value) { + return property + CONTENT_PROPERTY_VALUE_SEPARATOR + value; + } + + private static void appendMetaElement(String name, String content) { + MetaElement metaElement = Document.get().createMetaElement(); + metaElement.setName(name); + metaElement.setContent(content); + Document.get().getHead().appendChild(metaElement); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java index a6bc99a7792..52ebec1c989 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.java @@ -17,6 +17,7 @@ public interface TextMessages extends Messages { String contact(); String sponsoring(); String solutions(); + String blog(); String german(); String english(); String fullEventSchedule(); @@ -179,21 +180,53 @@ public interface TextMessages extends Messages { String sharingTwitter(); String socialFooterShare(); String socialFooterTitle(); - String solutionsSAPNav(); + + + String solutionsSISHeadline(); String solutionsSAPHeadline(); + String solutionsRaceHeadline(); + String solutionsPostHeadline(); + String solutionsTrainingHeadline(); + String solutionsSimulatorHeadline(); + + String sapInSailing(); + String contentSapInSailing1(); + String contentSapInSailing2(); + String contentSapInSailing3(); + String contentSapInSailing4(); + String contentSapInSailing5(); + String contentSapInSailing6(); + String contentSapInSailing7(); + String contentSapInSailing8(); + String contentSapInSailing9(); + String contentSapInSailing10(); + String contentSapInSailing11(); + String contentSapInSailing12(); String solutionsSAPText1(); String solutionsSAPText2(); - String solutionsRaceNav(); - String solutionsRaceHeadline(); String solutionsRaceText(); - String solutionsPostNav(); - String solutionsPostHeadline(); String solutionsPostText(); - String solutionsTrainingNav(); - String solutionsTrainingHeadline(); String solutionsTrainingText(); - String solutionsSimulatorNav(); - String solutionsSimulatorHeadline(); String solutionsSimulatorText(); + String sapSailingAnalytics(); + String contentSapSailingAnalytics1(); + String contentSapSailingAnalytics2(); + + String sapSailingAnalyticsReadMore(); + String sapSailingRaceManager(); + String contentSapSailingRaceManager(); + + String sapSailingRaceManagerReadMore(); + + String postRaceAnalytics(); + String contentPostRaceAnalytics1(); + String contentPostRaceAnalytics2(); + String i18nDeSolutionsTrainingHeadline(); + String i18nDeSolutionsTrainingText(); + + String strategySimulator(); + String contentStrategySimulator(); + + String strategySimulatorReadMore(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties index 25d8e5e4dbf..deb9bb5855e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages.properties @@ -6,6 +6,7 @@ aboutUs=About us contact=Contact sponsoring=Sponsoring solutions=Solutions +blog=Blog german=Deutsch english=English fullEventSchedule=Full event schedule @@ -134,7 +135,7 @@ leaderboardQuickAccessLabel=Leaderboard Quick Access mainEventShowAll=Show All Events mainEventTitle=Latest Events from the Sailing World mainMediaSubtitle=Get lost in the latest and most beautiful impressions from your favorite sailing event. -mainMediaTitle=Sailing loves Photography +mainMediaTitle=Photographers love Sailing mainMediaVideosSubtitle=Immerse yourself in the world of sailing and check out our latest events for more videos. mainMediaVideosTitle=Recent Video Entries mainSponsorsReadMore=Read More @@ -168,19 +169,55 @@ sharingFacebook=Share on Facebook sharingTwitter=Tweet about it socialFooterShare=Share this on socialFooterTitle=Recommend SAP Sailing Analytics -solutionsSAPNav=SAP Sailing Analytics + +# SOLUTIONS + +solutionsSISHeadline=SAP in Sailing solutionsSAPHeadline=SAP Sailing Analytics +solutionsRaceHeadline=SAP Sailing Race Manager +solutionsPostHeadline=Post-Race Analytics +solutionsTrainingHeadline=Training Diary +solutionsSimulatorHeadline=Strategy Simulator + +sapInSailing=SAP in Sailing +contentSapInSailing1=Sailing provides the perfect platform for SAP to showcase solutions and help the sport run like never before. SAP’s involvement in the sport has transformed the sailing experience by providing tools, which: +contentSapInSailing2=Help sailors analyze performance and optimize strategy +contentSapInSailing3=Bring fans closer to the action +contentSapInSailing4=Provide the media with information and insights to deliver a greater informed commentary +contentSapInSailing5=SAP has a longstanding involvement with sailing and has established a portfolio spanning across teams and regattas, including: +contentSapInSailing6=Official Technology Partner of Travemünder Woche +contentSapInSailing7=Technical Partner of the European Sailing Leagues +contentSapInSailing8=Title sponsor of the SAP Extreme Sailing Team +contentSapInSailing9=Official Technical Partner of the Extreme Sailing Series +contentSapInSailing10=Premium Partner of Germany’s national sailing team, Audi Sailing Team Germany +contentSapInSailing11=Premium Partner of the world’s largest regatta, Kieler Woche (Kiel Week) +contentSapInSailing12=Title sponsor of the SAP 5O5 World Championships + solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing. solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere. -solutionsRaceNav=Race Committee App -solutionsRaceHeadline=Race Committee App solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter. -solutionsPostNav=Post-Race Analytics -solutionsPostHeadline=Post-Race Analytics solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.
SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas. -solutionsTrainingNav=Training Diary -solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel. -solutionsSimulatorNav=Strategy Simulator -solutionsSimulatorHeadline=Strategy Simulator solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions. + + +sapSailingAnalytics=SAP Sailing Analytics +contentSapSailingAnalytics1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing. +contentSapSailingAnalytics2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere. +sapSailingAnalyticsReadMore=Read More + +sapSailingRaceManager=SAP Sailing Race Manager +contentSapSailingRaceManager=The SAP Sailing Race Manager delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter. +sapSailingRaceManagerReadMore=Learn More + +postRaceAnalytics=Post-Race Analytics +contentPostRaceAnalytics1=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better. +contentPostRaceAnalytics2=SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas. + +i18nDeSolutionsTrainingHeadline=SAP Sail Better – STG Training Diary +i18nDeSolutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete’s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel. + +strategySimulator=Strategy Simulator +contentStrategySimulator=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions. + +strategySimulatorReadMore=Learn More diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties index 2e21328263a..65b4c391adf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_de.properties @@ -6,6 +6,7 @@ aboutUs=Über uns contact=Kontakt sponsoring=Sponsoring solutions=Lösungen +blog=Blog german=Deutsch english=English fullEventSchedule=Gesamter Veranstaltungsplan @@ -134,7 +135,7 @@ leaderboardQuickAccessLabel=Ergebnisliste Schnellzugang mainEventShowAll=Zeige alle Veranstaltungen mainEventTitle=Die letzten Veranstaltungen aus der Segelwelt mainMediaSubtitle=Hier gibt es die aktuellsten und schönsten Impressionen aus deiner beliebtesten Segelveranstaltung. -mainMediaTitle=Segeln liebt Fotografie +mainMediaTitle=Fotografen lieben Segeln mainMediaVideosSubtitle=Tauche ein in die Welt des Segelns und besuche auch die anderen Veranstaltungen für mehr Videos. mainMediaVideosTitle= Die Letzten Videoeinträge mainSponsorsReadMore=Lese mehr @@ -168,19 +169,55 @@ sharingFacebook=Auf Facebook teilen sharingTwitter=Twittern socialFooterShare=Teile es auf socialFooterTitle=Empfehle SAP Sailing Analytics -solutionsSAPNav=SAP Sailing Analytics + +# SOLUTIONS + +solutionsSISHeadline=SAP im Segelsport solutionsSAPHeadline=SAP Sailing Analytics -solutionsSAPText1=Bei Echtzeitanalysen rund um Rennplätze, Schnelligkeit, Manöver, Verhalten etc., SAP hilf dabei zu vereinfachen und den Mythos von der Komplexität des Segelns zu nehmen. -solutionsSAPText2=SAP Sailing Analytics ermöglicht Einsichten und Transparenz in die Welt des Segelns durch Nutzung der Cloud und In-Memory Technologien, Erheben von GPS und Windmessungen in echtzeit und den Inhalt auf verschiedenen Oberflächen von überall zu visualisieren. -solutionsRaceNav=Race Committee App -solutionsRaceHeadline=Race Committee App -solutionsRaceText=Die SAP Race Committee App bietet mehr Effizienz und Kontrolle für die Rennleiter durch Automatisieren und vereinfachen der manuellen Aufgaben und der Kommunikation während laufender Segelregatten. Die Race Committee App hilft Aufgaben zu vereinfachen und Segelveranstaltungen zu leiten, um das Segel Komitee besser Handeln zu lassen. -solutionsPostNav=Nachträgliche Rennen Analyse. -solutionsPostHeadline=Nachträgliche Rennen Analyse -solutionsPostText=Zugang zu gesammelten Daten bei Segelveranstaltungen geben Seglern die Möglichkeit die eigene Performance zu beurteilen und zu analysieren, um Strategien zu entwickeln und besser zu segeln.
SAP Business Analytics Lösungen stellen Seglern, Trainern, Fans und Medien Tools zu verfügung, um die historischen Daten über mehrere Regatten und Rennen anzusehen und zu analysieren. SAP HANA erlaubt es ihnen über Verhaltensmuster, Tendenzen und Segelprofilen in einem einfachen, schnellen und effizienten Weg zu erlernen, damit sie ihre Performance und Entwicklung der Strategien in zukünftigen Regatten zu optimieren. -solutionsTrainingNav=Training Tagebuch -solutionsTrainingHeadline=SAP Segelt Besser \u2013 STG Training Tagebuch -solutionsTrainingText=Das STG Trainingstagebuch unterstützt die tägliche Dokumentation und Analyse von der physischen Kondition und Trainingserfolge eines Athleten in Wassertraining, physischen Training, Boot Arbeiten, Theorie und andere Aufgaben wie Bildung oder Reisen. -solutionsSimulatorNav=Strategie Simulator -solutionsSimulatorHeadline=Strategie Simulator -solutionsSimulatorText=Die richtige Strategie zu wählen kann einen großen Vorteil während eines Rennens bringen. Der Strategie Simulator vereinfacht ausschlaggebend die besten Segelstrategien für verschiedene Windkonditionen und Wasserströmungen. Seit dem der Wind und die Strömung während der Simulation direkt geändert werden kann, kann die Strategie sogar für unsichere Wetterverhältnisse einfach bewertet werden. +solutionsRaceHeadline=SAP Sailing Race Manager +solutionsPostHeadline=Analysen nach den Rennen +solutionsTrainingHeadline=Trainingstagebuch +solutionsSimulatorHeadline=Strategie-Simulator + +sapInSailing=SAP im Segelsport +contentSapInSailing1=Der Segelsport bietet SAP eine perfekte Plattform, um seine Lösungen zu demonstrieren und dem Sport zu neuen Bestleistungen zu verhelfen. SAPs Unterstützung hat das Segelerlebnis vollkommen verwandelt. Tools von SAP: +contentSapInSailing2=helfen Seglern, ihre Leistung zu analysieren und ihre Strategie zu optimieren +contentSapInSailing3=bringen Fans näher an das Geschehen heran +contentSapInSailing4=stellen Informationen und Einblicke für die Medien bereit, um eine besser informierte Berichterstattung zu ermöglichen +contentSapInSailing5=SAP ist bereits seit vielen Jahren mit dem Segelsport verbunden und hat ein Portfolio zahlreicher Teams und Regatten aufgebaut, darunter: +contentSapInSailing6=Offizieller Technologiepartner der Travemünder Woche +contentSapInSailing7=Technischer Partner der Europäischen Segelligen +contentSapInSailing8=Titelsponsor des SAP Extreme Sailing Teams +contentSapInSailing9=Offizieller technischer Partner der Extreme Sailing Series +contentSapInSailing10=Premium-Partner der deutschen Segel-Nationalmannschaft Audi Sailing Team Germany +contentSapInSailing11=Premium-Partner der Kieler Woche, der größten Regatta der Welt +contentSapInSailing12=Titelsponsor der SAP 5O5 World Championships + +solutionsSAPText1=Durch die Bereitstellung von Echtzeit-Analysen zu Ranglisten, Geschwindigkeiten, Manövern, Kursen etc. trägt SAP dazu bei, die komplexe Welt des Segelns einfacher und verständlicher zu machen. +solutionsSAPText2=SAP Sailing Analytics nutzt Cloud- und In-Memory-Technologie, verarbeitet GPS- und Winddaten in Echtzeit und visualisiert Inhalte in verschiedenen Frontends, die von überall zugänglich sind, um transparente Einblicke in die Welt des Segelns zu liefern. +solutionsRaceText=Der SAP Sailing Race Manager bietet Rennveranstaltern mehr Effizienz und Kontrolle, indem er ihre manuellen Aufgaben sowie die Kommunikation während Regatten automatisiert und vereinfacht. Diese App unterstützt die Durchführung und Abwicklung von Segelrennen und hilft Rennleitungen dadurch, intelligenter zu arbeiten. +solutionsPostText=Daten von den Segelveranstaltungen bieten Seglern die Möglichkeit, ihre Leistungen zu analysieren und zu bewerten, damit sie ihre Strategien verfeinern und letztendlich besser segeln können.
Lösungen von SAP Business Analytics geben Seglern, Trainern, Fans und Medien die Mittel in die Hand, um historische Daten von vielen Regatten und Rennen abzurufen und zu analysieren. Mit SAP HANA sind Informationen über Leistungsmuster, Trends und Segler-Profile einfach, schnell und effizient abrufbar, so dass Segler ihre eigene Leistung optimieren und Erfolgsstrategien für zukünftige Regatten entwickeln können. +solutionsTrainingText=Das STG Trainingstagebuch unterstützt die tägliche Dokumentation und Analyse der Kondition und Trainingsaktivitäten eines Sportlers, sowohl in Bereichen wie Training auf dem Wasser, Körpertraining, Arbeit auf dem Boot, Mentaltraining und Theorie als auch bei anderen Aktivitäten wie Weiterbildung oder Reisen. +solutionsSimulatorText=Während eines Rennens hängt viel von der Wahl der richtigen Strategie ab. Der Strategy Simulator vereinfacht die Ermittlung der besten Segelstrategie für diverse Wind- und Strömungsbedingungen. Da Wind und Strömung sofort in der Simulation geändert werden können, lässt sich die Robustheit einer Strategie selbst für unsichere Wetterbedingungen problemlos bewerten. + + +sapSailingAnalytics=SAP Sailing Analytics +contentSapSailingAnalytics1=Durch die Bereitstellung von Echtzeit-Analysen zu Ranglisten, Geschwindigkeiten, Manövern, Kursen etc. trägt SAP dazu bei, die komplexe Welt des Segelns einfacher und verständlicher zu machen. +contentSapSailingAnalytics2=SAP Sailing Analytics nutzt Cloud- und In-Memory-Technologie, verarbeitet GPS- und Winddaten in Echtzeit und visualisiert Inhalte in verschiedenen Frontends, die von überall zugänglich sind, um transparente Einblicke in die Welt des Segelns zu liefern. +sapSailingAnalyticsReadMore=Mehr lesen + +sapSailingRaceManager=SAP Sailing Race Manager +contentSapSailingRaceManager=Der SAP Sailing Race Manager bietet Rennveranstaltern mehr Effizienz und Kontrolle, indem sie ihre manuellen Aufgaben und die Kommunikation während Regatten automatisiert und vereinfacht. Die Race Committee App unterstützt die Durchführung und Abwicklung von Segelrennen und hilft Rennleitungen dadurch, intelligenter zu arbeiten. +sapSailingRaceManagerReadMore=Mehr erfahren + +postRaceAnalytics=Analysen nach den Rennen +contentPostRaceAnalytics1=Daten von den Segelveranstaltungen bieten Seglern die Möglichkeit, ihre Leistungen zu analysieren und zu bewerten, um ihre Strategien zu verfeinern und letztendlich besser zu segeln. +contentPostRaceAnalytics2=Lösungen von SAP Business Analytics geben Seglern, Trainern, Fans und Medien die Mittel in die Hand, um historische Daten von vielen Regatten und Rennen abzurufen und zu analysieren. Mit SAP HANA sind Informationen über Leistungsmuster, Trends und Segler-Profile einfach, schnell und effizient abrufbar, so dass Segler ihre eigene Leistung optimieren und Erfolgsstrategien für zukünftige Regatten entwickeln können. + +i18nDeSolutionsTrainingHeadline=SAP Sail Better – STG Trainingstagebuch +i18nDeSolutionsTrainingText=Das STG Trainingstagebuch unterstützt die tägliche Dokumentation und Analyse der Kondition und Trainingsaktivitäten eines Sportlers, sowohl in Bereichen wie Training auf dem Wasser, Körpertraining, Arbeit auf dem Boot, Mentaltraining und Theorie als auch bei anderen Aktivitäten wie Weiterbildung oder Reisen. + +strategySimulator=Strategie-Simulator +contentStrategySimulator=Während eines Rennens hängt viel von der Wahl der richtigen Strategie ab. Der Strategie-Simulator vereinfacht die Ermittlung der besten Segelstrategie für diverse Wind- und Strömungsbedingungen. Da Wind und Strömung sofort in der Simulation geändert werden können, lässt sich die Robustheit einer Strategie selbst für unsichere Wetterbedingungen problemlos bewerten. + +strategySimulatorReadMore=Mehr erfahren diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_ru.properties new file mode 100644 index 00000000000..db6065ad70c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_ru.properties @@ -0,0 +1,223 @@ +chartSelectionHint=Hint: You can also use the leaderboard (on the LEADERBOARD tab) to select the competitors displayed in the chart. +chooseALanguage=Choose a language +events=Events +home=Home +aboutUs=About us +contact=Contact +sponsoring=Sponsoring +solutions=Решения +blog=Блог +german=Deutsch +english=English +fullEventSchedule=Full event schedule +officalEventWebsite=Official event website +leg=Leg +races=Races +moreInfo=More info +viewAnalysis=View analysis +overallLeaderboard=Overall leaderboard +pleaseEnterASearchTerm=Please enter a search term. +pleaseTryAgain=Please try again... +reloadPage=Reload page +errorMessageLoadingData=An error occured while loading the data for this page. +errorMessageNoSuchLeaderboard=Could not find a leaderboard with this name. +raceNotScheduled=Not scheduled. +regattaDetails=Regatta details +regatta=Regatta +competitorsAnalytics=Competitors Analytics +chooseChart=Choose chart type +series=Series +regattaLeaderboards=Regatta leaderboards +features=Features +releaseNotes=Release notes +whatsNew=What''s new +overview=Overview +sapSailing=SAP Sailing +search=Search +startSimulator=Start Simulator +countdownStartingInDays=Days +countdownDays=Days +countdownHours=Hrs +countdownMinutes=Min +countdownSeconds=Sec +countdownDay=Day +countdownHour=Hour +countdownMinute=Min +countdownSecond=Sec +live=Live +finished=Finished +watchNow=Watch now +lastUpdate=Last Update +leaderboard=Leaderboard +boxNewsUpdateMoreLink=Report news +boxNewsUpdateTitle=News Update +boxUpcomingRacesCountdownStarted1=Started +boxUpcomingRacesCountdownStarted2=hrs and +boxUpcomingRacesCountdownStarted3=minutes ago +boxUpcomingRacesCountdownStarting1=Starting in +boxUpcomingRacesCountdownStarting2=hrs and +boxUpcomingRacesCountdownStarting3=minutes +boxUpcomingRacesMoreLink=Event Schedule +boxUpcomingRacesTitle=Upcoming Races Today +boxWeather=Weather +boxWeatherUnit=KTS +defaultTitle=SAP Sailing Analytics +eventHeaderMedia=Media +eventHeaderOverview=Overview +eventHeaderRaces=Schedule +eventHeaderRegattas=Regattas +seriesHeaderOverview=About the Series +seriesHeaderUpcoming=Upcoming +seriesHeaderRecent=Recent Events +seriesHeaderLeaderboard=Leaderboard +seriesOverviewHeaderRecent=Latest Series Events +seriesOverviewReadMore=More +eventsOverviewRecentEvents=Events +eventsOverviewRecentCountries=Countries +eventsOverviewRecentSailors=Sailors +eventsOverviewRecentTrackedRaces=Tracked Races +eventResultsHeadline=Winners and Results +eventResultsBoatClassesDropDown=All Boat Classes +eventOverviewMoreEvents=More Events +eventOverviewRecentEvents=Recent Events +eventOverviewUpcomingDate=Date +eventOverviewUpcomingEvent=Event +eventOverviewUpcomingLocation=Location +eventOverviewUpcomingSchedule=Upcoming Schedule +eventOverviewUpcomingSeries=Series +eventOverviewUpcomingTeaser=More Events To Be Announced Soon! +eventQuickfinderTitle=Event Quick-Finder +eventRegattaHeaderLeaderboard=Leaderboard +eventRegattaHeaderRaceRaces=Races +eventRegattaListAllBoatClasses=All boat classes +eventRegattaLeaderboardCompetitor=Competitor +eventRegattaLeaderboardExtendLeaderboard=Extend Leaderboard +eventRegattaLeaderboardFinishedMessage=No more races +eventRegattaLeaderboardLastScoreUpdate=Last Score Update +eventRegattaLeaderboardName=Name +eventRegattaLeaderboardRegattaRank=Regatta Rank +eventRegattaLeaderboardTotalPoints=Total Points +eventRegattaRaceWatch=Watch live +eventRegattaRaceAnalyse=Analyze Race +eventRegattaRaceNotTracked=Not Tracked +eventRegattaRaceFinished=Finished at: +eventRegattaRaceStarted=Started at: +eventRegattaRaceScheduled=Scheduled for: +eventRegattaRaceRace=Race +eventRegattaRaceWind=Wind Strength: +eventRegattaRaceWinner=Winner +eventRegattaRaceLeader=Leader +eventRegattaRacesLegendGps=Tracking +eventRegattaRacesLegendWind=Wind Data +eventRegattaRacesLegendVideo=Video +eventRegattaRacesLegendAudio=Audio +eventSponsorsTitle=Event Sponsorships +footerJobs=Jobs +footerCopyright=\u00A9 2015 SAP Sailing Analytics +footerLanguage=SAP Sailing in +footerLegal=Legal Disclosure +footerPrivacy=Privacy +footerFeedback=Feedback +headerEvents=Events +headerHome=Home +headerLogo=Sailing Analytics +headerSearch=Search +headerSearchPlaceholder=Search +headerSolutions=Solutions +headerSponsoring=Sponsoring +latestRaceResultsHeadline=Latest Official Race Results +latestRaceResultsIsNew=New +latestRaceResultsIsUpdated=Updated +latestRaceResultsRaceCountLabel=Result after +latestRaceResultsRaceCountUnit=races +latestRaceResultsRefresh=refresh +leaderboardQuickAccessLabel=Leaderboard Quick Access +mainEventShowAll=Show All Events +mainEventTitle=Latest Events from the Sailing World +mainMediaSubtitle=Get lost in the latest and most beautiful impressions from your favorite sailing event. +mainMediaTitle=Sailing loves Photography +mainMediaVideosSubtitle=Immerse yourself in the world of sailing and check out our latest events for more videos. +mainMediaVideosTitle=Recent Video Entries +mainSponsorsReadMore=Read More +mediaTeaserPhotosTitle=Photos +mediaTeaserVideosTitle=Videos +regattaCompetitors=Competitors +regattaRaces=Races +regattaTracked=Tracked +regattaRegattaStarts=Regatta will start +regattaPts=Pts. +regattaCourse=Course +regattaArea=Area +regattaFinishedAt=Finished at +regattaScheduledAt=Scheduled at +regattaStartedAt=Started at +regattasResultsTitle=Winner and Results +searchResultHeaderButton=Search +searchResultHeaderLabel=Your Search +searchResultsFound=result(s) found for +searchResultHeaderPlaceholder=Type in your searchkey +searchResultMore=More +searchResultSearch=Search +searchResultSearchAgain=Search again +searchResultSortLabel=Sort by +searchResultSortNewest=Recent +searchResultSortOldest=Oldest +searchResultSortRelevance=Relevance +searchResultCount=About 2,450 results where found for 'Schnitzel' +sharingEmail=Send an email +sharingFacebook=Share on Facebook +sharingTwitter=Tweet about it +socialFooterShare=Share this on +socialFooterTitle=Recommend SAP Sailing Analytics + +# SOLUTIONS + +solutionsSISHeadline=Компания SAP и парусный спорт +solutionsSAPHeadline=Инструмент аналитики парусного спорта от компании SAP +solutionsRaceHeadline=Менеджер регат SAP +solutionsPostHeadline=Пост-регатная аналитика +solutionsTrainingHeadline=Дневник тренировок +solutionsSimulatorHeadline=Тренажер стратегий + +sapInSailing=Компания SAP и парусный спорт +contentSapInSailing1=Парусный спорт предоставляет отличную платформу для компании SAP, демонстрируя возможные решения и помогая этому виду спорта развиваться как никогда. Участие SAP в этом виде спорта изменило впечатления от занятий парусным спортом, предлагая средства, которые: +contentSapInSailing2=Помогают яхтсменам анализировать достижения и оптимизировать стратегию +contentSapInSailing3=Позволяют болельщикам быть ближе к действию +contentSapInSailing4=Обеспечивают СМИ информацией и аналитическими оценками для подачи более информативных комментариев +contentSapInSailing5=Компания SAP имеет давние связи с парусным спортом и ее серьезный портфолио включает сотрудничество с различными командами и регатами, например: +contentSapInSailing6=Официальный технологический партнер Travemьnder Woche +contentSapInSailing7=Технический партнер Европейских лиг парусного спорта +contentSapInSailing8=Генеральный спонсор экстремальной команды по парусному спорту +contentSapInSailing9=Официальный технический партнер экстремальной серии парусного спорта +contentSapInSailing10=Премиум-партнер национальной команды Германии по парусному спорту, Германская команда Audi по парусному спорту +contentSapInSailing11=Премиум-партнер крупнейшей регаты мира, Kieler Woche (Kiel Week) +contentSapInSailing12=Генеральный спонсор чемпионатов мира SAP 5O5 + +solutionsSAPText1=Предоставляя аналитические данные о рейтинге, скоростях, маневрах, координатах и т.п. регат в реальном времени, компания SAP помогает освещать сложный парусный спорт в более простой и доступной форме. +solutionsSAPText2=Инструмент аналитики парусного спорта от компании SAP предоставляет аналитическую информацию и транспарентность миру парусного спорта, используя Технологию облака и памяти, обрабатывая данные GPS и измерения ветра в реальном времени и визуализируя содержимое в различных внешних интерфейсах, доступных из любой точки мира. +solutionsRaceText=Приложение «Комитет регат» SAP предоставляет возможность организаторам регат действовать эффективнее и лучше управлять ситуацией путем автоматизаци и упрощения задач, которые они делают вручную, а также их общения во время проведения яхтенных регат. Приложение «Комитет регат» помогает улучшить проведение регат и управление ими, чтобы помочь комитетам регат работать с более полной отдачей. +solutionsPostText=Доступ к данным, собираемым во время мероприятий, связанных с парусным спортом, дает яхтсменам возможность оценить и проанализировать свои показатели, что поможет им разработать стратегии и улучшить свои показатели в парусном спорте.
Решения бизнес-аналитики от компании SAP предоставляют яхтсменам, тренерам, болельщикам и средствам массовой информации инструменты для просмотра и анализа архивных данных по многим регатам и гонкам. Платформа SAP HANA позволяет им узнать о типовых действиях, тенденциях и профилях яхтсменов просто, быстро и эффективно с целью оптимизации своих собственных достижений и разработки успешных стратегий для будущих регат. +solutionsTrainingText=Дневник тренировок STG поддерживает работу с ежедневной документацией и анализ физического состояния и тренировочных усилий спортсменов в таких областях как тренировки на воде, физические тренировки, практика хождения под парусом, психическая подготовка, теория, а также другие виды деятельности, такие как образование или путешествия. +solutionsSimulatorText=Выбор правильной стратегии может дать большое конкурентное преимущество во время гонки. Тренажер стратегий SAP упрощает определение лучшей стратегии хождения под парусом для различных ветровых режимов и водных течений. Поскольку ветер и течение в тренажере можно быстро изменять, надежность стратегии можно легко оценить даже в условиях изменчивой погоды. + + +sapSailingAnalytics=Инструмент аналитики парусного спорта от компании SAP +contentSapSailingAnalytics1=Предоставляя аналитические данные о рейтинге, скоростях, маневрах, координатах и т.п. регат в реальном времени, компания SAP помогает освещать сложный парусный спорт в более простой и доступной форме. +contentSapSailingAnalytics2=Инструмент аналитики парусного спорта от компании SAP предоставляет аналитическую информацию и транспарентность миру парусного спорта, используя Технологию облака и памяти, обрабатывая данные GPS и измерения ветра в реальном времени и визуализируя содержимое в различных внешних интерфейсах, доступных из любой точки мира. +sapSailingAnalyticsReadMore=Читать далее + +sapSailingRaceManager=Менеджер регат SAP +contentSapSailingRaceManager=Менеджер регат SAP предоставляет возможность организаторам регат действовать эффективнее и лучше управлять ситуацией путем автоматизаци и упрощения задач, которые они делают вручную, а также их общения во время проведения яхтенных регат. Приложение «Комитет регат» помогает улучшить проведение регат и управление ими, чтобы помочь комитетам регат работать с более полной отдачей. +sapSailingRaceManagerReadMore=Читать далее + +postRaceAnalytics=Пост-регатная аналитика +contentPostRaceAnalytics1=Доступ к данным собираемым во время мероприятий, связанных с парусным спортом, дает яхтсменам возможность оценить и проанализировать свои показатели, что поможет им разработать стратегии и улучшить свои показатели в парусном спорте. +contentPostRaceAnalytics2=Решения бизнес-аналитики от компании SAP предоставляют яхтсменам, тренерам, болельщикам и средствам массовой информации инструменты для просмотра и анализа архивных данных по многим регатам и гонкам. Платформа SAP HANA позволяет им узнать о типовых действиях, тенденциях и профилях яхтсменов просто, быстро и эффективно с целью оптимизации своих собственных достижений и разработки успешных стратегий для будущих регат. + +i18nDeSolutionsTrainingHeadline=Инструмент от SAP "Улучши свои показатели в парусном спорте"– Дневник тренировок STG +i18nDeSolutionsTrainingText=Дневник тренировок STG поддерживает работу с ежедневной документацией и анализ физического состояния и тренировочных усилий спортсменов в таких областях как тренировки на воде, физические тренировки, практика хождения под парусом, психическая подготовка, теория, а также другие виды деятельности, такие как образование или путешествия. + +strategySimulator=Тренажер стратегий +contentStrategySimulator=Выбор правильной стратегии может дать большое конкурентное преимущество во время гонки. Тренажер стратегий SAP упрощает определение лучшей стратегии хождения под парусом для различных ветровых режимов и водных течений. Поскольку ветер и течение в тренажере можно быстро изменять, надежность стратегии можно легко оценить даже в условиях изменчивой погоды. + +strategySimulatorReadMore=Читать далее diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_zh.properties index 60eae3c34e2..6db739191e6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/common/client/i18n/TextMessages_zh.properties @@ -4,6 +4,7 @@ aboutUs=关于我们 contact=联络 sponsoring=赞助商 solutions=解决方案 +blog=博客 events=比赛 german=德语 english=英语 @@ -167,18 +168,55 @@ sharingEmail=Send an email sharingFacebook=Share on Facebook sharingTwitter=Tweet about it socialFooterTitle=Recommend SAP Sailing Analytics -solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing. -solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere. -solutionsRaceNav=Race Committee App -solutionsRaceHeadline=Race Committee App -solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter. -solutionsPostNav=Post-Race Analytics -solutionsPostHeadline=Post-Race Analytics -solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.
SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas. -solutionsTrainingNav=Training Diary -solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary -solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel. -solutionsSimulatorNav=Strategy Simulator -solutionsSimulatorHeadline=Strategy Simulator -solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions. +# SOLUTIONS (解决方案) + +solutionsSISHeadline=SAP 航海应用 +solutionsSAPHeadline=SAP Sailing Analytics +solutionsRaceHeadline=SAP Sailing Race Manager +solutionsPostHeadline=赛后分析 +solutionsTrainingHeadline=Training Diary +solutionsSimulatorHeadline=Strategy Simulator + +sapInSailing=SAP 航海应用 +contentSapInSailing1=Sailing 为 SAP 提供了一个理想的平台来展示解决方案,并以前所未有的方式进行这项运动。SAP 参与这项运动,并通过提供工具来改变航海体验,这些工具: +contentSapInSailing2=帮助水手分析性能和优化策略 +contentSapInSailing3=让航海爱好者更近距离地感受这项运动 +contentSapInSailing4=向媒体提供信息和见解,从而发表更明智的评论 +contentSapInSailing5=SAP 长期参与航海运动,与多个团队和航海赛事建立了合作关系,包括: +contentSapInSailing6=Travemünder Woche 的官方技术合作伙伴 +contentSapInSailing7=欧洲帆船联赛的技术合作伙伴 +contentSapInSailing8=SAP 极限帆船队的冠名赞助商 +contentSapInSailing9=极限帆船系列赛的官方技术合作伙伴 +contentSapInSailing10=德国国家帆船队、德国奥迪帆船队的金牌合作伙伴 +contentSapInSailing11=全球最大规模帆船比赛 Kieler Woche (Kiel Week) 的金牌合作伙伴 +contentSapInSailing12=SAP 505 世界锦标赛冠名赞助商 + +solutionsSAPText1=通过对比赛排名、速度、策略、方位等进行实时分析,SAP 可以帮助简化和阐明航海运动的复杂性。 +solutionsSAPText2=SAP Sailing Analytics 利用云和内存技术、实时处理 GPS 和风力测量数据,以及在可以从任意位置访问的各个前端上对内容进行可视化,提供对航海世界的见解和了解。 +solutionsRaceText=SAP Race Committee 应用程序通过自动化和简化赛事组织者的手动任务并在举行帆船赛事期间实现沟通,为其提供了更高的效率和控制。Race Committee 应用程序有助于简化赛事的举行和管理,帮助赛事委员会更加智能地举办比赛。 +solutionsPostText=访问帆船比赛中收集的数据让水手和教练有机会评估和分析其表现,从而有助于制定策略并在帆船赛事中发挥更高水平。
SAP Business Analytics 解决方案为水手、教练、帆船爱好者和媒体提供了工具来浏览和评估多个季节和赛事的历史数据。 SAP HANA 平台能够以一种简单、快速、高效的方式让他们了解表现模式、趋势和水手资料,以优化其自身表现以及为今后的赛事制定成功策略。 +solutionsTrainingText=STG Training Diary 支持在水上训练、体能训练、帆船作业、心理、理论以及培训或旅行等其他活动方面对运动员的体能情况和训练进行日常记录和分析。 +solutionsSimulatorText=在帆船比赛中,选择正确的策略可以提供巨大的竞争优势。Strategy Simulator 简化了多种风力情况和水流下最佳航行策略的制定过程。由于风和水流在模拟中会随时改变,甚至可以针对不确定的天气条件来轻松评估策略的稳固性。 + + +sapSailingAnalytics=SAP Sailing Analytics +contentSapSailingAnalytics1=通过对比赛排名、速度、策略、方位等进行实时分析,SAP 可以帮助简化和阐明航海运动的复杂性。 +contentSapSailingAnalytics2=SAP Sailing Analytics 利用云和内存技术、实时处理 GPS 和风力测量数据,以及在可以从任意位置访问的各个前端上对内容进行可视化,提供对航海世界的见解和了解。 +sapSailingAnalyticsReadMore=阅读更多 + +sapSailingRaceManager=SAP Sailing Race Manager +contentSapSailingRaceManager=SAP Sailing Race Manager 通过自动化和简化赛事组织者的手动任务并在举行帆船赛事期间实现沟通,为其提供了更高的效率和控制。Race Committee 应用程序有助于简化赛事的举行和管理,帮助赛事委员会更加智能地举办比赛。 +sapSailingRaceManagerReadMore=了解更多 + +postRaceAnalytics=赛后分析 +contentPostRaceAnalytics1=访问帆船比赛中收集的数据让水手有机会评估和分析其表现,从而有助于制定策略并在帆船赛事中发挥更高水平。 +contentPostRaceAnalytics2=SAP Business Analytics 解决方案为水手、教练、帆船爱好者和媒体提供了工具来浏览和分析多个赛事的历史数据。 SAP HANA 平台能够以一种简单、快速、高效的方式让他们了解表现模式、趋势和水手资料,以优化其自身表现以及为今后的赛事制定成功策略。 + +i18nDeSolutionsTrainingHeadline=SAP Sail Better – STG Training Diary +i18nDeSolutionsTrainingText=STG Training Diary 支持在水上训练、体能训练、帆船作业、心理、理论以及培训或旅行等其他活动方面对运动员的体能情况和训练进行日常记录和分析。 + +strategySimulator=Strategy Simulator +contentStrategySimulator=在帆船比赛中,选择正确的策略可以提供巨大的竞争优势。Strategy Simulator 简化了多种风力情况和水流下最佳航行策略的制定过程。由于风和水流在模拟中会随时改变,甚至可以针对不确定的天气条件来轻松评估策略的稳固性。 + +strategySimulatorReadMore=了解更多 diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/Dispatch.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/Dispatch.gwt.xml new file mode 100755 index 00000000000..5b669fc59b8 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/Dispatch.gwt.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Action.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Action.java new file mode 100644 index 00000000000..741ad66db19 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Action.java @@ -0,0 +1,12 @@ +package com.sap.sailing.gwt.dispatch.client; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + +public interface Action extends IsSerializable { + + @GwtIncompatible + R execute(CTX ctx) throws DispatchException; + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/CollectionResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/CollectionResult.java similarity index 73% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/CollectionResult.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/CollectionResult.java index fa132a5a098..8986fd56edc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/CollectionResult.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/CollectionResult.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client; import java.util.Collection; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DTO.java new file mode 100644 index 00000000000..bbd7aa3bcea --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DTO.java @@ -0,0 +1,10 @@ +package com.sap.sailing.gwt.dispatch.client; + +import com.google.gwt.user.client.rpc.IsSerializable; + +/** + * Data transfer object marker interface used in generic transport results in dispatch action/ results + */ +public interface DTO extends IsSerializable { + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchAsync.java new file mode 100644 index 00000000000..0429ec1f339 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchAsync.java @@ -0,0 +1,9 @@ +package com.sap.sailing.gwt.dispatch.client; + +import com.google.gwt.user.client.rpc.AsyncCallback; + +public interface DispatchAsync { + + > void execute(A action, AsyncCallback callback); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchContext.java new file mode 100644 index 00000000000..8af814da120 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/DispatchContext.java @@ -0,0 +1,17 @@ +package com.sap.sailing.gwt.dispatch.client; + +import java.net.URL; + +import javax.servlet.http.HttpServletRequest; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + + +public interface DispatchContext { + @GwtIncompatible + HttpServletRequest getRequest(); + + @GwtIncompatible + URL getRequestBaseURL() throws DispatchException; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ListResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ListResult.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ListResult.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ListResult.java index 46e4561b5c0..f577ef4a49d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ListResult.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ListResult.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client; import java.util.ArrayList; import java.util.Collection; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Result.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Result.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Result.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Result.java index e24acd001b3..3f72b9719ba 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Result.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/Result.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWithTTL.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWithTTL.java new file mode 100644 index 00000000000..9c2c7280a52 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWithTTL.java @@ -0,0 +1,49 @@ +package com.sap.sailing.gwt.dispatch.client; + +import com.sap.sailing.gwt.dispatch.client.caching.HasClientCacheTotalTimeToLive; +import com.sap.sse.common.Duration; +import com.sap.sse.common.impl.MillisecondsDurationImpl; + +public class ResultWithTTL implements Result, HasClientCacheTotalTimeToLive { + + /** max millis the result might be loaded earlier so we do batches **/ + public static final Duration MAX_TIME_TO_LOAD_EARLIER = Duration.ONE_SECOND.times(5); + + /** Time to live*/ + private Duration ttl; + private T dto; + @SuppressWarnings("unused") + private ResultWithTTL() { + } + + public ResultWithTTL(long ttl, T dto) { + this(new MillisecondsDurationImpl(ttl), dto); + } + + public ResultWithTTL(Duration ttl, T dto) { + this.ttl = ttl; + this.dto = dto; + } + + public T getDto() { + return dto; + } + + public Duration getTtl() { + return ttl; + } + + public long getTtlMillis() { + return ttl.asMillis(); + } + + /** + * Reduce the total time to live value for cache by the time needed so the refresh manager can batch calls. Result + * will not be negative. + */ + @Override + public int cacheTotalTimeToLiveMillis() { + return (int) Math.max(0, getTtlMillis() - MAX_TIME_TO_LOAD_EARLIER.asMillis()); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWrapper.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWrapper.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWrapper.java index e1e3b0c6aa7..9a18ae2e3de 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/ResultWrapper.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client; import java.util.Date; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/SortedSetResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/SortedSetResult.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/SortedSetResult.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/SortedSetResult.java index 7fb41164a53..a31a84a138e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/SortedSetResult.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/SortedSetResult.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client; import java.util.Collection; import java.util.Set; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/StringsResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/StringsResult.java new file mode 100644 index 00000000000..be4dc37a9ee --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/StringsResult.java @@ -0,0 +1,32 @@ +package com.sap.sailing.gwt.dispatch.client; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class StringsResult implements DTO, Result { + + private ArrayList values = new ArrayList<>(); + + public StringsResult() { + } + + public StringsResult(Collection values) { + this.values.addAll(values); + } + + public void addValue(String value) { + if (value != null) { + this.values.add(value); + } + } + + public List getValues() { + return values; + } + + public boolean isEmpty() { + return this.values.isEmpty(); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/AutomaticBatchingDispatch.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/AutomaticBatchingDispatch.java similarity index 73% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/AutomaticBatchingDispatch.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/AutomaticBatchingDispatch.java index 63e35fb7e7d..59a28fa0249 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/AutomaticBatchingDispatch.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/AutomaticBatchingDispatch.java @@ -1,22 +1,22 @@ -package com.sap.sailing.gwt.home.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.batching; import java.util.logging.Logger; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.BatchResult; -import com.sap.sailing.gwt.ui.shared.dispatch.NonBatchableAction; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; -public class AutomaticBatchingDispatch implements DispatchAsync { +public class AutomaticBatchingDispatch implements DispatchAsync { private static final Logger LOG = Logger.getLogger(AutomaticBatchingDispatch.class.getName()); - private final DispatchAsync executionContext; + private final DispatchAsync executionContext; - private DispatchCallStack currentCallstack; + private DispatchCallStack currentCallstack; /** * Creates a batching dispatch service using the given dispatch implementation. @@ -27,7 +27,7 @@ public class AutomaticBatchingDispatch implements DispatchAsync { * the underlying service implementation to use * */ - public AutomaticBatchingDispatch(DispatchAsync service) { + public AutomaticBatchingDispatch(DispatchAsync service) { this.executionContext = service; } @@ -36,13 +36,13 @@ public class AutomaticBatchingDispatch implements DispatchAsync { * loop. */ @Override - public > void execute(A action, AsyncCallback callback) { + public > void execute(A action, AsyncCallback callback) { if(action instanceof NonBatchableAction) { executionContext.execute(action, callback); return; } if (this.currentCallstack == null) { - this.currentCallstack = new DispatchCallStack(); + this.currentCallstack = new DispatchCallStack(); this.triggerExecution(); } this.currentCallstack.addCall(action, callback); @@ -55,11 +55,12 @@ public class AutomaticBatchingDispatch implements DispatchAsync { */ private void triggerExecution() { Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override public void execute() { LOG.fine("executing batch callstack "); - final DispatchCallStack callStackInExecution = AutomaticBatchingDispatch.this.currentCallstack; + final DispatchCallStack callStackInExecution = AutomaticBatchingDispatch.this.currentCallstack; AutomaticBatchingDispatch.this.currentCallstack = null; AutomaticBatchingDispatch.this.executionContext.execute(callStackInExecution.getBatchAction(), new AsyncCallback() { @@ -77,6 +78,6 @@ public class AutomaticBatchingDispatch implements DispatchAsync { }); } }); - }; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchAction.java similarity index 74% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchAction.java index b988f219d4f..38b5c09515f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchAction.java @@ -1,36 +1,41 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.batching; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; -public class BatchAction implements Action { +public class BatchAction implements Action { private static final Logger logger = Logger.getLogger(BatchAction.class.getName()); - private Action[] actions; + private Action[] actions; @SuppressWarnings("unused") private BatchAction() { } - public BatchAction(Action... actions) { + @SafeVarargs + public BatchAction(Action... actions) { this.actions = actions; } - public Action[] getActions() { + public Action[] getActions() { return actions; } @Override @GwtIncompatible - public BatchResult execute(DispatchContext ctx) throws DispatchException { + public BatchResult execute(CTX ctx) throws DispatchException { final int nrOfActions = getActions().length; final ArrayList results = new ArrayList(nrOfActions); final ArrayList exceptions = new ArrayList(nrOfActions); - for (Action a : getActions()) { + for (Action a : getActions()) { Result result = null; long start = System.currentTimeMillis(); try { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchResult.java similarity index 88% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchResult.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchResult.java index 34536f916c5..ea08227f7b3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/BatchResult.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/BatchResult.java @@ -1,9 +1,12 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.batching; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + public class BatchResult implements Result { private LinkedList results = new LinkedList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCall.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCall.java similarity index 54% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCall.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCall.java index 7ce8d381a2d..a6a67a43238 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCall.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCall.java @@ -1,14 +1,15 @@ -package com.sap.sailing.gwt.home.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.batching; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; /** * The convenience class wrapping an synchronous call. * */ -public final class DispatchCall, R extends Result> { +public final class DispatchCall, R extends Result, CTX extends DispatchContext> { private final A action; @@ -19,7 +20,7 @@ public final class DispatchCall, R extends Result> { this.callback = callback; } - public Action getAction() { + public Action getAction() { return action; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCallStack.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCallStack.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCallStack.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCallStack.java index e4db7cad040..2bec8747ffb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchCallStack.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/DispatchCallStack.java @@ -1,12 +1,11 @@ -package com.sap.sailing.gwt.home.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.batching; import java.util.LinkedList; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.BatchAction; -import com.sap.sailing.gwt.ui.shared.dispatch.BatchResult; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; /** * Convenience class used to aggregate {@link Call} instances. @@ -14,27 +13,27 @@ import com.sap.sailing.gwt.ui.shared.dispatch.Result; * The class and all methods are private, its use is internal only. * */ -public final class DispatchCallStack { +public final class DispatchCallStack { /** * The list containg all queued actions. */ - private final LinkedList> actionQueue = new LinkedList>(); + private final LinkedList> actionQueue = new LinkedList>(); /** * The batch action holding the all the actions build in the queue. This instance variable is used to lazy * initialize and cache the created batch action. */ - private BatchAction batchAction; + private BatchAction batchAction; /** * Add a call to the queue. Can only be called as long as the batch action has not been accessed/ initialized. * * @param call */ - public , R extends Result> void addCall(A action, AsyncCallback callback) { + public , R extends Result> void addCall(A action, AsyncCallback callback) { assert (this.batchAction == null); - this.actionQueue.add(new DispatchCall(action, callback)); + this.actionQueue.add(new DispatchCall(action, callback)); } /** @@ -42,13 +41,14 @@ public final class DispatchCallStack { * * @return */ - public BatchAction getBatchAction() { + public BatchAction getBatchAction() { if (this.batchAction == null) { - Action[] actions = new Action[this.actionQueue.size()]; + @SuppressWarnings("unchecked") + Action[] actions = new Action[this.actionQueue.size()]; for (int loop = 0; loop < actions.length; loop++) { actions[loop] = this.actionQueue.get(loop).getAction(); } - this.batchAction = new BatchAction(actions); + this.batchAction = new BatchAction(actions); } return this.batchAction; } @@ -60,7 +60,7 @@ public final class DispatchCallStack { */ public void fail(Throwable caught) { assert (caught != null); - for (DispatchCall call : this.actionQueue) { + for (DispatchCall call : this.actionQueue) { call.getCallback().onFailure(caught); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/NonBatchableAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/NonBatchableAction.java new file mode 100644 index 00000000000..41cde73e1b6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/batching/NonBatchableAction.java @@ -0,0 +1,5 @@ +package com.sap.sailing.gwt.dispatch.client.batching; + +public interface NonBatchableAction { + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/CachingDispatch.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/CachingDispatch.java new file mode 100644 index 00000000000..225678da9b4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/CachingDispatch.java @@ -0,0 +1,186 @@ +package com.sap.sailing.gwt.dispatch.client.caching; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.logging.Logger; + +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sse.common.Duration; + +/** + * Delegating dispatch implementation that caches results if actions implement IsClientCache interface. + * + * @author pgtaboada + */ +public final class CachingDispatch implements DispatchAsync { + + private static final Logger LOG = Logger.getLogger(CachingDispatch.class.getName()); + + private final CacheCleanupTask invalidationTask; + private final HashMap resultsCache = new HashMap<>(); + private final DispatchAsync dispatch; + private final int defaultTimeToLive; + + public CachingDispatch(DispatchAsync service) { + this(service, true, (int) Duration.ONE_MINUTE.times(3).asMillis()); + } + + public CachingDispatch(DispatchAsync service, boolean enableCleanup, int defaultTimeToLive) { + this.dispatch = service; + this.defaultTimeToLive = defaultTimeToLive; + if (enableCleanup) { + invalidationTask = new CacheCleanupTask(); + } else { + invalidationTask = null; + } + } + + @SuppressWarnings("unchecked") + @Override + public > void execute(A action, AsyncCallback callback) { + if (action instanceof IsClientCacheable) { + final IsClientCacheable clientCacheableAction = (IsClientCacheable) action; + final ResultHolder cachedResult = resultsCache.get(key(clientCacheableAction)); + if (cachedResult != null && cachedResult.isValid()) { + LOG.fine("Cache hit for " + action.getClass().getName()); + callback.onSuccess((R) cachedResult.getPayload()); + } else { + LOG.fine("Cache miss for " + action.getClass().getName()); + executeAndCache(action, callback); + } + } else { + LOG.fine("Action is not cacheable: " + action.getClass().getName()); + dispatch.execute(action, callback); + } + }; + + /** + * Perform dispatch call with intercepting callback. + * + * @param action + * @param callback + */ + private > void executeAndCache(final A action, + final AsyncCallback callback) { + dispatch.execute(action, new InterceptingCallback<>(action, callback)); + } + + /** + * Intercepting callback that stores the result into cache. + * + * @author pgtaboada + * + * @param + * @param + */ + private class InterceptingCallback> implements AsyncCallback { + private final A action; + private final AsyncCallback callback; + + public InterceptingCallback(A action, AsyncCallback callback) { + this.action = action; + this.callback = callback; + } + + @Override + public void onSuccess(R result) { + if (action instanceof IsClientCacheable) { + final IsClientCacheable clientCacheableAction = (IsClientCacheable) action; + final String instanceKey = key(clientCacheableAction); + int cacheTotalTimeToLiveMillis = defaultTimeToLive; + if (result instanceof HasClientCacheTotalTimeToLive) { + cacheTotalTimeToLiveMillis = ((HasClientCacheTotalTimeToLive) result).cacheTotalTimeToLiveMillis(); + } else if (action instanceof HasClientCacheTotalTimeToLive) { + cacheTotalTimeToLiveMillis = ((HasClientCacheTotalTimeToLive) action).cacheTotalTimeToLiveMillis(); + } + resultsCache.put(instanceKey, new ResultHolder(System.currentTimeMillis() + + cacheTotalTimeToLiveMillis, result)); + LOG.finest("Added " + instanceKey + " to cache, ttl: " + cacheTotalTimeToLiveMillis + "ms"); + if (invalidationTask != null && !invalidationTask.isRunning()) { + LOG.finest("Schedule cache cleanup"); + invalidationTask.schedule((int) Duration.ONE_MINUTE.times(5).asMillis()); + } + } + callback.onSuccess(result); + } + + @Override + public void onFailure(Throwable caught) { + callback.onFailure(caught); + } + } + + /** + * Generate instance key for given action. + * + * @param action + * @return + */ + private String key(IsClientCacheable action) { + StringBuilder key = new StringBuilder(action.getClass().getName()).append("_"); + action.cacheInstanceKey(key); + return key.toString(); + } + + /** + * Holder class used to store results in cache. + * + * @author pgtaboada + * + */ + private static class ResultHolder { + final Result payload; + final long invalidationTimestamp; + + public ResultHolder(long invalidationTimestamp, Result payload) { + this.invalidationTimestamp = invalidationTimestamp; + this.payload = payload; + } + + public boolean isValid() { + return System.currentTimeMillis() < invalidationTimestamp; + } + + public Result getPayload() { + return payload; + } + } + + public void cleanupExpiredItems() { + final ArrayList keys = new ArrayList(resultsCache.keySet()); + LOG.finest("Start cache cleanup"); + for (String key : keys) { + if (!resultsCache.get(key).isValid()) { + resultsCache.remove(key); + } + } + } + + public int ttlItemsInCache() { + return resultsCache.size(); + } + + /** + * Removes due elements from resultscache. + * + * @author pgtaboada + * + */ + private class CacheCleanupTask extends Timer { + @Override + public void run() { + try { + cleanupExpiredItems(); + } finally { + if (!resultsCache.isEmpty()) { + invalidationTask.schedule((int) Duration.ONE_MINUTE.times(5).asMillis()); + } + } + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/HasClientCacheTotalTimeToLive.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/HasClientCacheTotalTimeToLive.java new file mode 100644 index 00000000000..e2804f7f2a7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/HasClientCacheTotalTimeToLive.java @@ -0,0 +1,17 @@ +package com.sap.sailing.gwt.dispatch.client.caching; + +/** + * Interface used by actions and results to override default cache time to live. + * + * @author pgtaboada + * + */ +public interface HasClientCacheTotalTimeToLive { + + /** + * How long should the result be stored in the client side cache + * + * @return + */ + int cacheTotalTimeToLiveMillis(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/IsClientCacheable.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/IsClientCacheable.java new file mode 100644 index 00000000000..75b2de6eb1e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/caching/IsClientCacheable.java @@ -0,0 +1,17 @@ +package com.sap.sailing.gwt.dispatch.client.caching; + +/** + * Cache interface used by the caching dispatch to identify which command can be cached on client side. + * + * @author pgtaboada + * + */ +public interface IsClientCacheable { + + /** + * The instance specific key used to identify instance specific results in the cache. + * + * @return + */ + void cacheInstanceKey(StringBuilder key); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchException.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/DispatchException.java similarity index 86% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchException.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/DispatchException.java index 4605a0e087a..495281133ef 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchException.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/DispatchException.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.exceptions; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ServerDispatchException.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/ServerDispatchException.java similarity index 64% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ServerDispatchException.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/ServerDispatchException.java index ebb282e0f36..0661775bc66 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ServerDispatchException.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/exceptions/ServerDispatchException.java @@ -1,4 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.exceptions; + +import java.util.UUID; public class ServerDispatchException extends DispatchException { @@ -14,6 +16,11 @@ public class ServerDispatchException extends DispatchException { this.uuid = uuid; } + public ServerDispatchException(Throwable cause) { + super(cause.getMessage()); + this.uuid = UUID.randomUUID().toString(); + } + public String getUuid() { return uuid; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystem.java new file mode 100644 index 00000000000..384158a59da --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystem.java @@ -0,0 +1,10 @@ +package com.sap.sailing.gwt.dispatch.client.impl; + +import java.util.Date; + +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; + +public interface DispatchSystem extends DispatchAsync { + Date getCurrentServerTime(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystemImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystemImpl.java similarity index 50% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystemImpl.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystemImpl.java index fd862a02eb1..5bb331f988f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystemImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/impl/DispatchSystemImpl.java @@ -1,20 +1,26 @@ -package com.sap.sailing.gwt.home.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.impl; import java.util.Date; import com.google.gwt.core.shared.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.dispatch.ServerDispatchException; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.batching.AutomaticBatchingDispatch; +import com.sap.sailing.gwt.dispatch.client.caching.CachingDispatch; +import com.sap.sailing.gwt.dispatch.client.exceptions.ServerDispatchException; +import com.sap.sailing.gwt.dispatch.client.rpcimpl.SimpleDispatch; -public class DispatchSystemImpl implements DispatchSystem { +public class DispatchSystemImpl implements DispatchSystem { - private final SimpleDispatch simpleDispatch = new SimpleDispatch(null); - private final DispatchAsync dispatch = new AutomaticBatchingDispatch(simpleDispatch); + private final SimpleDispatch simpleDispatch = new SimpleDispatch(null); + private final DispatchAsync dispatch = new CachingDispatch(new AutomaticBatchingDispatch( + simpleDispatch)); @Override - public > void execute(final A action, final AsyncCallback callback) { + public > void execute(final A action, final AsyncCallback callback) { // TODO: client side execution time logging AsyncCallback wrappedCallback = new AsyncCallback() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPC.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPC.java new file mode 100644 index 00000000000..600d7fa6c2a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPC.java @@ -0,0 +1,15 @@ +package com.sap.sailing.gwt.dispatch.client.rpcimpl; + +import com.google.gwt.user.client.rpc.RemoteService; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.ResultWrapper; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + +public interface DispatchRPC extends RemoteService { + + > ResultWrapper execute( + RequestWrapper action) throws DispatchException; + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPCAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPCAsync.java new file mode 100644 index 00000000000..d46898f07ab --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/DispatchRPCAsync.java @@ -0,0 +1,15 @@ +package com.sap.sailing.gwt.dispatch.client.rpcimpl; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.ResultWrapper; + +public interface DispatchRPCAsync { + + > void execute( + RequestWrapper action, + AsyncCallback> callback); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/RequestWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/RequestWrapper.java similarity index 72% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/RequestWrapper.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/RequestWrapper.java index 0a7be0417ff..c8f00f5e517 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/RequestWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/RequestWrapper.java @@ -1,10 +1,14 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.rpcimpl; import java.util.Date; import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; -public class RequestWrapper> implements IsSerializable { +public class RequestWrapper, CTX extends DispatchContext> implements + IsSerializable { private Date currentClientTime = new Date(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/SimpleDispatch.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/SimpleDispatch.java similarity index 64% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/SimpleDispatch.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/SimpleDispatch.java index ee0c3966243..63b564c4e04 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/SimpleDispatch.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/dispatch/client/rpcimpl/SimpleDispatch.java @@ -1,21 +1,20 @@ -package com.sap.sailing.gwt.home.shared.dispatch; +package com.sap.sailing.gwt.dispatch.client.rpcimpl; import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.DispatchAsync; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.ResultWrapper; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.client.SailingClientFactory; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.RequestWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.rpc.DispatchRPC; -import com.sap.sailing.gwt.ui.shared.dispatch.rpc.DispatchRPCAsync; -public class SimpleDispatch implements DispatchAsync { +public class SimpleDispatch implements DispatchAsync { - private static final DispatchRPCAsync dispatchRPC = GWT.create(DispatchRPC.class); + private final DispatchRPCAsync dispatchRPC = GWT.create(DispatchRPC.class); private long clientServerOffset = 0; @@ -24,8 +23,9 @@ public class SimpleDispatch implements DispatchAsync { } @Override - public > void execute(A action, final AsyncCallback callback) { - RequestWrapper requestWrapper = new RequestWrapper(action, LocaleInfo.getCurrentLocale().getLocaleName()); + public > void execute(A action, final AsyncCallback callback) { + RequestWrapper requestWrapper = new RequestWrapper(action, LocaleInfo.getCurrentLocale() + .getLocaleName()); final long clientTimeOnRequestStart = System.currentTimeMillis(); dispatchRPC.execute(requestWrapper, new AsyncCallback>() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Desktop.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Desktop.gwt.xml deleted file mode 100755 index af4f3299332..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Desktop.gwt.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Home.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Home.gwt.xml old mode 100755 new mode 100644 index 80617ebe945..4110f0aa78a --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Home.gwt.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Home.gwt.xml @@ -1,10 +1,49 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Mobile.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Mobile.gwt.xml deleted file mode 100755 index a3a886909bd..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/Mobile.gwt.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/legacy/SeriesClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/legacy/SeriesClientFactory.java index d12160232d2..a91cc821b7d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/legacy/SeriesClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/client/place/event/legacy/SeriesClientFactory.java @@ -1,8 +1,9 @@ package com.sap.sailing.gwt.home.client.place.event.legacy; +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; import com.sap.sailing.gwt.ui.client.SailingClientFactory; -public interface SeriesClientFactory extends SailingClientFactory { +public interface SeriesClientFactory extends SailingClientFactory, ClientFactoryWithDispatch { // SeriesAnalyticsView createSeriesAnalyticsView(EventDTO event, String leaderboardName, SeriesNavigationTabs // navigationTab, Timer timerForClientServerOffset); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingAction.java new file mode 100644 index 00000000000..75f5b8cd6db --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingAction.java @@ -0,0 +1,13 @@ +package com.sap.sailing.gwt.home.communication; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; + +public interface SailingAction extends Action { + + @GwtIncompatible + R execute(SailingDispatchContext ctx) throws DispatchException; + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchContext.java similarity index 51% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContext.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchContext.java index 365a4849e0c..7baa29b4339 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchContext.java @@ -1,25 +1,28 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.home.communication; import java.util.Date; import java.util.Locale; -import javax.servlet.http.HttpServletRequest; - +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.DispatchContext; import com.sap.sailing.news.EventNewsService; import com.sap.sailing.server.RacingEventService; -public interface DispatchContext { - +public interface SailingDispatchContext extends DispatchContext { + @GwtIncompatible RacingEventService getRacingEventService(); - + + @GwtIncompatible EventNewsService getEventNewsService(); + @GwtIncompatible String getClientLocaleName(); + @GwtIncompatible Locale getClientLocale(); + @GwtIncompatible Date getCurrentClientTime(); - HttpServletRequest getRequest(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystem.java new file mode 100644 index 00000000000..9a5a12125a8 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystem.java @@ -0,0 +1,8 @@ +package com.sap.sailing.gwt.home.communication; + +import com.sap.sailing.gwt.dispatch.client.impl.DispatchSystem; + +public interface SailingDispatchSystem extends DispatchSystem { + + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystemImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystemImpl.java new file mode 100644 index 00000000000..f6a83a87e13 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/SailingDispatchSystemImpl.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.communication; + +import com.sap.sailing.gwt.dispatch.client.impl.DispatchSystemImpl; + +public class SailingDispatchSystemImpl extends DispatchSystemImpl implements + SailingDispatchSystem { +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventLinkAndMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventLinkAndMetadataDTO.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventLinkAndMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventLinkAndMetadataDTO.java index eb043ea5390..78ac7dd0325 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventLinkAndMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventLinkAndMetadataDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; +import com.sap.sailing.gwt.home.communication.start.StageEventType; public class EventLinkAndMetadataDTO extends EventMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventMetadataDTO.java similarity index 94% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventMetadataDTO.java index ed5ce2780a5..4947444b622 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventMetadataDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; import java.util.Date; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; public class EventMetadataDTO extends EventReferenceDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventReferenceDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventReferenceDTO.java similarity index 89% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventReferenceDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventReferenceDTO.java index ada6194da68..d504d8d50e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventReferenceDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventReferenceDTO.java @@ -1,10 +1,10 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class EventReferenceDTO implements DTO { private UUID id; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventSeriesReferenceDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventSeriesReferenceDTO.java similarity index 81% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventSeriesReferenceDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventSeriesReferenceDTO.java index c870505b7a1..1ed04317461 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventSeriesReferenceDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventSeriesReferenceDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; import java.util.UUID; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class EventSeriesReferenceDTO implements DTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventState.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventState.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventState.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventState.java index 37bec17d659..6b312467c00 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/EventState.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/EventState.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; public enum EventState { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetCompetitionFormatRacesAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetCompetitionFormatRacesAction.java similarity index 50% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetCompetitionFormatRacesAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetCompetitionFormatRacesAction.java index 50b6884155e..f43e21ec259 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetCompetitionFormatRacesAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetCompetitionFormatRacesAction.java @@ -1,16 +1,20 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.RaceCompetitionFormatDataCalculator; import com.sap.sse.common.Duration; -public class GetCompetitionFormatRacesAction implements Action>> { +public class GetCompetitionFormatRacesAction implements + SailingAction>>, IsClientCacheable { private UUID eventId; private String regattaId; @@ -25,11 +29,15 @@ public class GetCompetitionFormatRacesAction implements Action> execute(DispatchContext context) throws DispatchException { + public ResultWithTTL> execute(SailingDispatchContext context) throws DispatchException { RaceCompetitionFormatDataCalculator competitionFormatDataCalculator = new RaceCompetitionFormatDataCalculator(); EventActionUtil.forRacesOfRegatta(context, eventId, regattaId, competitionFormatDataCalculator); Duration timeToLive = EventActionUtil.getEventStateDependentTTL(context, eventId, Duration.ONE_MINUTE); return new ResultWithTTL<>(timeToLive, new ListResult<>(competitionFormatDataCalculator.getResult())); } + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId).append("_").append(regattaId); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventListViewAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventListViewAction.java new file mode 100644 index 00000000000..541b21d05f3 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventListViewAction.java @@ -0,0 +1,24 @@ +package com.sap.sailing.gwt.home.communication.event; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; +import com.sap.sailing.gwt.server.EventListDataCalculator; +import com.sap.sailing.gwt.server.HomeServiceUtil; + +public class GetEventListViewAction implements SailingAction, IsClientCacheable { + @Override + @GwtIncompatible + public EventListViewDTO execute(SailingDispatchContext context) { + EventListDataCalculator eventListDataCalculator = new EventListDataCalculator(context.getRacingEventService()); + HomeServiceUtil.forAllPublicEvents(context.getRacingEventService(), context.getRequest(), + eventListDataCalculator); + return eventListDataCalculator.getResult(); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventViewAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventViewAction.java similarity index 82% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventViewAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventViewAction.java index e6535204a4b..dcc1bd659a2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventViewAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetEventViewAction.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.ArrayList; import java.util.Collections; @@ -12,18 +12,20 @@ import java.util.logging.Logger; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.LeaderboardContext; +import com.sap.sailing.gwt.home.server.EventActionUtil.LeaderboardCallback; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.LeaderboardCallback; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sse.common.media.ImageDescriptor; import com.sap.sse.common.media.MediaTagConstants; +import com.sap.sse.shared.media.ImageDescriptor; -public class GetEventViewAction implements Action { +public class GetEventViewAction implements SailingAction, IsClientCacheable { private static final Logger logger = Logger.getLogger(GetEventViewAction.class.getName()); private UUID eventId; @@ -37,7 +39,7 @@ public class GetEventViewAction implements Action { } @GwtIncompatible - public EventViewDTO execute(DispatchContext context) { + public EventViewDTO execute(SailingDispatchContext context) { final Event event = context.getRacingEventService().getEvent(eventId); if (event == null) { throw new RuntimeException("Event not found"); @@ -112,7 +114,11 @@ public class GetEventViewAction implements Action { localizedURL += "en"; dto.setSailorsInfoWebsiteURL(localizedURL); } - return dto; } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetFinishedRacesAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetFinishedRacesAction.java similarity index 52% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetFinishedRacesAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetFinishedRacesAction.java index 1423431f9ed..23b6726517a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetFinishedRacesAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetFinishedRacesAction.java @@ -1,15 +1,19 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.RaceListDataCalculator; import com.sap.sse.common.Duration; -public class GetFinishedRacesAction implements Action>> { +public class GetFinishedRacesAction implements SailingAction>>, + IsClientCacheable { private UUID eventId; private String regattaId; @@ -25,11 +29,16 @@ public class GetFinishedRacesAction implements Action> execute(DispatchContext context) { + public ResultWithTTL> execute(SailingDispatchContext context) { RaceListDataCalculator raceListDataCalculator = new RaceListDataCalculator(); EventActionUtil.forRacesOfRegatta(context, eventId, regattaId, raceListDataCalculator); return new ResultWithTTL<>(EventActionUtil.getEventStateDependentTTL(context, eventId, Duration.ONE_MINUTE.times(5)), new SortedSetResult<>(raceListDataCalculator.getResult())); } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId).append("_").append(regattaId); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetLiveRacesForEventAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetLiveRacesForEventAction.java similarity index 52% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetLiveRacesForEventAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetLiveRacesForEventAction.java index c198ec41807..b8a35cfabe1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetLiveRacesForEventAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetLiveRacesForEventAction.java @@ -1,16 +1,20 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.CalculationWithEvent; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.LiveRaceCalculator; +import com.sap.sailing.gwt.home.server.EventActionUtil.CalculationWithEvent; -public class GetLiveRacesForEventAction implements Action>> { +public class GetLiveRacesForEventAction implements SailingAction>>, + IsClientCacheable { private UUID eventId; @SuppressWarnings("unused") @@ -23,7 +27,7 @@ public class GetLiveRacesForEventAction implements Action> execute(final DispatchContext context) { + public ResultWithTTL> execute(final SailingDispatchContext context) { return EventActionUtil.withLiveRaceOrDefaultSchedule(context, eventId, new CalculationWithEvent>() { @Override public ResultWithTTL> calculateWithEvent(Event event) { @@ -33,4 +37,9 @@ public class GetLiveRacesForEventAction implements Action>> { +public class GetLiveRacesForRegattaAction implements SailingAction>>, + IsClientCacheable { private UUID eventId; private String regattaName; @@ -25,7 +29,7 @@ public class GetLiveRacesForRegattaAction implements Action> execute(final DispatchContext context) { + public ResultWithTTL> execute(final SailingDispatchContext context) { return EventActionUtil.withLiveRaceOrDefaultSchedule(context, eventId, new CalculationWithEvent>() { @Override public ResultWithTTL> calculateWithEvent(Event event) { @@ -35,4 +39,9 @@ public class GetLiveRacesForRegattaAction implements Action>> { +public class GetRegattaListViewAction implements SailingAction>>, + IsClientCacheable { private UUID eventId; @SuppressWarnings("unused") @@ -26,7 +30,7 @@ public class GetRegattaListViewAction implements Action> execute(final DispatchContext context) { + public ResultWithTTL> execute(final SailingDispatchContext context) { final List result = new LinkedList<>(); EventActionUtil.forLeaderboardsOfEvent(context, eventId, new LeaderboardCallback() { @Override @@ -37,4 +41,9 @@ public class GetRegattaListViewAction implements Action(EventActionUtil.getEventStateDependentTTL(context, eventId, Duration.ONE_MINUTE.times(3)), new SortedSetResult<>(result)); } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaStatisticsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaStatisticsAction.java new file mode 100644 index 00000000000..efbc5ba8af5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaStatisticsAction.java @@ -0,0 +1,40 @@ +package com.sap.sailing.gwt.home.communication.event; + +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.statistics.EventStatisticsDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.StatisticsCalculator; + +public class GetRegattaStatisticsAction implements SailingAction>, IsClientCacheable { + + private UUID eventId; + private String regattaId; + + protected GetRegattaStatisticsAction() { + } + + public GetRegattaStatisticsAction(UUID eventId, String regattaId) { + this.eventId = eventId; + this.regattaId = regattaId; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) throws DispatchException { + StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); + statisticsCalculator.doForLeaderboard(EventActionUtil.getLeaderboardContext(context, eventId, regattaId)); + return statisticsCalculator.getResult(); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId).append("_").append(regattaId); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaWithProgressAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaWithProgressAction.java new file mode 100644 index 00000000000..210ff2ed9b2 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattaWithProgressAction.java @@ -0,0 +1,39 @@ +package com.sap.sailing.gwt.home.communication.event; + +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sse.common.Duration; + +public class GetRegattaWithProgressAction implements SailingAction>, IsClientCacheable { + + private UUID eventId; + private String regattaId; + + @SuppressWarnings("unused") + private GetRegattaWithProgressAction() { + } + + public GetRegattaWithProgressAction(UUID eventId, String regattaId) { + this.eventId = eventId; + this.regattaId = regattaId; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) { + return new ResultWithTTL<>(EventActionUtil.getEventStateDependentTTL(context, eventId, Duration.ONE_MINUTE.times(5)), + EventActionUtil.getLeaderboardContext(context, eventId, regattaId).getRegattaWithProgress()); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId).append("_").append(regattaId); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattasAndLiveRacesForEventAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattasAndLiveRacesForEventAction.java similarity index 72% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattasAndLiveRacesForEventAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattasAndLiveRacesForEventAction.java index 4f7546e69af..e6c9cf92821 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattasAndLiveRacesForEventAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/GetRegattasAndLiveRacesForEventAction.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.HashMap; import java.util.Map; @@ -9,17 +9,21 @@ import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.LeaderboardContext; +import com.sap.sailing.gwt.home.server.RaceContext; +import com.sap.sailing.gwt.home.server.EventActionUtil.LeaderboardCallback; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.LeaderboardCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; import com.sap.sse.common.Duration; -public class GetRegattasAndLiveRacesForEventAction implements Action> { +public class GetRegattasAndLiveRacesForEventAction implements SailingAction>, + IsClientCacheable { private UUID eventId; @SuppressWarnings("unused") @@ -32,7 +36,7 @@ public class GetRegattasAndLiveRacesForEventAction implements Action execute(DispatchContext context) { + public ResultWithTTL execute(SailingDispatchContext context) { Event event = context.getRacingEventService().getEvent(eventId); final Map regattas = mapRegattas(context, event); final TreeMap> regattasWithRaces = new TreeMap<>(); @@ -65,7 +69,7 @@ public class GetRegattasAndLiveRacesForEventAction implements Action mapRegattas(DispatchContext context, Event event) { + private Map mapRegattas(SailingDispatchContext context, Event event) { final Map result = new HashMap<>(); EventActionUtil.forLeaderboardsOfEvent(context, event, new LeaderboardCallback() { @Override @@ -87,4 +91,9 @@ public class GetRegattasAndLiveRacesForEventAction implements Action>, IsClientCacheable { + + private UUID seriesId; + + protected GetSeriesStatisticsAction() { + } + + public GetSeriesStatisticsAction(UUID seriesId) { + this.seriesId = seriesId; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) throws DispatchException { + StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); + EventActionUtil.forLeaderboardsOfEvent(context, seriesId, statisticsCalculator); + return statisticsCalculator.getResult(); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(seriesId); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/HasLogo.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/HasLogo.java similarity index 71% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/HasLogo.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/HasLogo.java index a380e77dcaa..e78dc8b7906 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/HasLogo.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/HasLogo.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; import com.sap.sse.gwt.client.media.ImageDTO; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/LabelType.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LabelType.java similarity index 97% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/LabelType.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LabelType.java index b8e56ee8e5a..fa384b7c7a4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/general/LabelType.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LabelType.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.general; +package com.sap.sailing.gwt.home.communication.event; import com.sap.sailing.gwt.ui.client.StringMessages; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LiveRaceDTO.java similarity index 71% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LiveRaceDTO.java index cbd67cbf9b1..af5a7e2ea86 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/LiveRaceDTO.java @@ -1,10 +1,10 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO; -import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.RaceProgressDTO; -import com.sap.sailing.gwt.ui.shared.race.wind.SimpleWindDTO; +import com.sap.sailing.gwt.home.communication.race.FlagStateDTO; +import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.RaceProgressDTO; +import com.sap.sailing.gwt.home.communication.race.wind.SimpleWindDTO; public class LiveRaceDTO extends RaceMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatFleetDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatFleetDTO.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatFleetDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatFleetDTO.java index ffb3abb8776..214d9051508 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatFleetDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatFleetDTO.java @@ -1,11 +1,11 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.Collection; import java.util.TreeSet; import com.google.gwt.user.client.rpc.IsSerializable; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; public class RaceCompetitionFormatFleetDTO implements IsSerializable { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatSeriesDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatSeriesDTO.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatSeriesDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatSeriesDTO.java index 15745aba8f2..84cf893b08a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatSeriesDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceCompetitionFormatSeriesDTO.java @@ -1,9 +1,9 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.ArrayList; import java.util.Collection; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class RaceCompetitionFormatSeriesDTO implements DTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListRaceDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceListRaceDTO.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListRaceDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceListRaceDTO.java index 8efd14b90a5..235a6139a43 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListRaceDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RaceListRaceDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.wind.WindStatisticsDTO; +import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.wind.WindStatisticsDTO; import com.sap.sse.common.Duration; public class RaceListRaceDTO extends RaceMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattasAndLiveRacesDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RegattasAndLiveRacesDTO.java similarity index 86% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattasAndLiveRacesDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RegattasAndLiveRacesDTO.java index 335a2d61cc8..c443a48695f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattasAndLiveRacesDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/RegattasAndLiveRacesDTO.java @@ -1,12 +1,12 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; public class RegattasAndLiveRacesDTO implements DTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/SimpleCompetitorDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java similarity index 90% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/SimpleCompetitorDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java index 22026fac877..1a05fa966cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/SimpleCompetitorDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/SimpleCompetitorDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event; import java.io.Serializable; @@ -9,7 +9,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.NamedDTO; import com.sap.sse.common.CountryCode; -public class SimpleCompetitorDTO extends NamedDTO implements Serializable { +public class SimpleCompetitorDTO extends NamedDTO implements Serializable, Comparable { private static final long serialVersionUID = -5743976446085202047L; @@ -94,4 +94,10 @@ public class SimpleCompetitorDTO extends NamedDTO implements Serializable { return true; } + @Override + public int compareTo(SimpleCompetitorDTO obj) { + int compareSailIds = this.sailID.compareTo(obj.sailID); + return compareSailIds == 0 ? this.getName().compareTo(obj.getName()): compareSailIds; + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRaceTickerStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRaceTickerStageDTO.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRaceTickerStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRaceTickerStageDTO.java index efd978e3741..338f68e9c92 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRaceTickerStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRaceTickerStageDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import java.util.Date; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRegattaTickerStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRegattaTickerStageDTO.java similarity index 90% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRegattaTickerStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRegattaTickerStageDTO.java index 3da08e6d81c..6c069cb8eda 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewRegattaTickerStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewRegattaTickerStageDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import java.util.Date; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageContentDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageContentDTO.java similarity index 65% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageContentDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageContentDTO.java index 4dcfa332cd3..f4a3344be4d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageContentDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageContentDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageDTO.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageDTO.java index 6500765e5f2..45f8ae04d36 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewStageDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class EventOverviewStageDTO implements DTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewTickerStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewTickerStageDTO.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewTickerStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewTickerStageDTO.java index fd01bd6a511..771615b835b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewTickerStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewTickerStageDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import java.util.Date; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewVideoStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewVideoStageDTO.java similarity index 90% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewVideoStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewVideoStageDTO.java index 5e9ab1d99f2..a6f7086920a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventOverviewVideoStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/EventOverviewVideoStageDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import com.sap.sse.gwt.client.media.VideoDTO; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewStageAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/GetEventOverviewStageAction.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewStageAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/GetEventOverviewStageAction.java index 3caa25a42e0..7c0aa231ef6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewStageAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/eventoverview/GetEventOverviewStageAction.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.eventoverview; import static com.sap.sailing.gwt.server.HomeServiceUtil.findEventThumbnailImageUrlAsString; import static com.sap.sailing.gwt.server.HomeServiceUtil.getStageImageURLAsString; @@ -9,20 +9,20 @@ import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventState; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewVideoStageDTO.Type; -import com.sap.sailing.gwt.ui.shared.general.EventState; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.common.media.VideoDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; -public class GetEventOverviewStageAction implements Action> { +public class GetEventOverviewStageAction implements SailingAction>, IsClientCacheable { private UUID eventId; private boolean useTeaserImage; @@ -38,7 +38,7 @@ public class GetEventOverviewStageAction implements Action execute(DispatchContext context) { + public ResultWithTTL execute(SailingDispatchContext context) { TimePoint now = MillisecondsTimePoint.now(); Event event = context.getRacingEventService().getEvent(eventId); EventState state = HomeServiceUtil.calculateEventState(event); @@ -56,12 +56,13 @@ public class GetEventOverviewStageAction implements Action videoTags = Collections.singletonList(MediaTagConstants.FEATURED); VideoDescriptor featuredVideo = HomeServiceUtil.getStageVideo(event, context.getClientLocale(), videoTags , false); if (featuredVideo != null) { - return new EventOverviewVideoStageDTO(Type.MEDIA, HomeServiceUtil.toVideoDTO(featuredVideo)); + return new EventOverviewVideoStageDTO(EventOverviewVideoStageDTO.Type.MEDIA, + HomeServiceUtil.toVideoDTO(featuredVideo)); } // P2: Featured image if available @@ -130,4 +131,9 @@ public class GetEventOverviewStageAction implements Action items = new ArrayList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniLeaderbordAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniLeaderbordAction.java new file mode 100644 index 00000000000..40cd8687b76 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniLeaderbordAction.java @@ -0,0 +1,45 @@ +package com.sap.sailing.gwt.home.communication.event.minileaderboard; + +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; + +public class GetMiniLeaderbordAction implements SailingAction>, IsClientCacheable { + private UUID eventId; + private String leaderboardName; + private int limit = 0; + + @SuppressWarnings("unused") + private GetMiniLeaderbordAction() { + } + + public GetMiniLeaderbordAction(UUID eventId, String leaderboardName) { + this(eventId, leaderboardName, 0); + } + + public GetMiniLeaderbordAction(UUID eventId, String leaderboardName, int limit) { + this.eventId = eventId; + this.leaderboardName = leaderboardName; + this.limit = limit; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) { + return EventActionUtil.getLeaderboardContext(context, eventId, leaderboardName).calculateMiniLeaderboard(context.getRacingEventService(), limit); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId); + key.append("_"); + key.append(leaderboardName); + key.append("_"); + key.append(limit); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniOverallLeaderbordAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniOverallLeaderbordAction.java new file mode 100644 index 00000000000..17a28f9828f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/GetMiniOverallLeaderbordAction.java @@ -0,0 +1,39 @@ +package com.sap.sailing.gwt.home.communication.event.minileaderboard; + +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; + +public class GetMiniOverallLeaderbordAction implements SailingAction>, IsClientCacheable { + private UUID seriesId; + private int limit = 0; + + @SuppressWarnings("unused") + private GetMiniOverallLeaderbordAction() { + } + + public GetMiniOverallLeaderbordAction(UUID eventId) { + this(eventId, 0); + } + + public GetMiniOverallLeaderbordAction(UUID seriesId, int limit) { + this.seriesId = seriesId; + this.limit = limit; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) { + return EventActionUtil.getOverallLeaderboardContext(context, seriesId).calculateMiniLeaderboard(context.getRacingEventService(), limit); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(seriesId).append("_").append(limit); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/MiniLeaderboardItemDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/MiniLeaderboardItemDTO.java similarity index 80% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/MiniLeaderboardItemDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/MiniLeaderboardItemDTO.java index 0f1b8bdf44a..c0bfbb5664a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/MiniLeaderboardItemDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/minileaderboard/MiniLeaderboardItemDTO.java @@ -1,6 +1,7 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.minileaderboard; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; public class MiniLeaderboardItemDTO implements DTO { private SimpleCompetitorDTO competitor; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/AbstractRaceNewsEntryDTO.java similarity index 64% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/AbstractRaceNewsEntryDTO.java index e906303b10e..229dcf30e6d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/news/AbstractRaceNewsEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/AbstractRaceNewsEntryDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.news; +package com.sap.sailing.gwt.home.communication.event.news; import java.util.Date; @@ -8,6 +8,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; public abstract class AbstractRaceNewsEntryDTO extends NewsEntryDTO { private String leaderboardName; + private String leaderboardGroupName; private RegattaAndRaceIdentifier regattaAndRaceIdentfier; private String boatClass; @@ -15,9 +16,11 @@ public abstract class AbstractRaceNewsEntryDTO extends NewsEntryDTO { } @GwtIncompatible - public AbstractRaceNewsEntryDTO(String leaderboardName, RegattaAndRaceIdentifier regattaAndRaceIdentifier, String raceTitle, String boatClass, Date timestamp) { + public AbstractRaceNewsEntryDTO(String leaderboardName, String leaderboardGroupName, + RegattaAndRaceIdentifier regattaAndRaceIdentifier, String raceTitle, String boatClass, Date timestamp) { super(raceTitle, timestamp, null); this.leaderboardName = leaderboardName; + this.leaderboardGroupName = leaderboardGroupName; this.boatClass = boatClass; } @@ -29,6 +32,10 @@ public abstract class AbstractRaceNewsEntryDTO extends NewsEntryDTO { public String getLeaderboardName() { return leaderboardName; } + + public String getLeaderboardGroupName() { + return leaderboardGroupName; + } public RegattaAndRaceIdentifier getRegattaAndRaceIdentfier() { return regattaAndRaceIdentfier; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/GetEventOverviewNewsAction.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/GetEventOverviewNewsAction.java index bfa00c2d8c6..be705aa2a57 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventOverviewNewsAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/event/news/GetEventOverviewNewsAction.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.communication.event.news; import java.util.ArrayList; import java.util.List; @@ -6,20 +6,19 @@ import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.CalculationWithEvent; -import com.sap.sailing.gwt.ui.shared.dispatch.news.InfoNewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.news.LeaderboardNewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.EventActionUtil; +import com.sap.sailing.gwt.home.server.EventActionUtil.CalculationWithEvent; import com.sap.sailing.news.EventNewsItem; import com.sap.sailing.news.impl.InfoEventNewsItem; import com.sap.sailing.news.impl.LeaderboardUpdateNewsItem; import com.sap.sse.common.Duration; -public class GetEventOverviewNewsAction implements Action>> { +public class GetEventOverviewNewsAction implements SailingAction>>, IsClientCacheable { private UUID eventId; /** * This is number of items to deliver @@ -41,7 +40,7 @@ public class GetEventOverviewNewsAction implements Action> execute(final DispatchContext context) { + public ResultWithTTL> execute(final SailingDispatchContext context) { return EventActionUtil.withLiveRaceOrDefaultSchedule(context, eventId, new CalculationWithEvent>() { @Override public ResultWithTTL> calculateWithEvent(Event event) { @@ -51,7 +50,7 @@ public class GetEventOverviewNewsAction implements Action getNews(DispatchContext dispatchContext, Event event) { + private List getNews(SailingDispatchContext dispatchContext, Event event) { List newsItems = dispatchContext.getEventNewsService().getNews(event); if(this.limit > 0 && newsItems.size() > limit) { @@ -68,4 +67,9 @@ public class GetEventOverviewNewsAction implements Action>, IsClientCacheable { + + private UUID eventId; + + protected GetEventStatisticsAction() { + } + + public GetEventStatisticsAction(UUID eventId) { + this.eventId = eventId; + } + + @Override + @GwtIncompatible + public ResultWithTTL execute(SailingDispatchContext context) throws DispatchException { + StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); + EventActionUtil.forLeaderboardsOfEvent(context, eventId, statisticsCalculator); + return statisticsCalculator.getResult(); + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventDTO.java similarity index 72% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventDTO.java index b2e566af76a..d145c69df95 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.eventlist; +package com.sap.sailing.gwt.home.communication.eventlist; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; public class EventListEventDTO extends EventLinkAndMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventSeriesDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventSeriesDTO.java similarity index 77% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventSeriesDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventSeriesDTO.java index 7143370b8ef..3d27644a0c2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListEventSeriesDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListEventSeriesDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.eventlist; +package com.sap.sailing.gwt.home.communication.eventlist; import java.util.UUID; -import com.sap.sailing.gwt.ui.shared.general.EventSeriesReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.EventSeriesReferenceDTO; public class EventListEventSeriesDTO extends EventSeriesReferenceDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListViewDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListViewDTO.java similarity index 85% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListViewDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListViewDTO.java index c42a176d773..bac40a3d17e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListViewDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListViewDTO.java @@ -1,11 +1,12 @@ -package com.sap.sailing.gwt.ui.shared.eventlist; +package com.sap.sailing.gwt.home.communication.eventlist; import java.util.ArrayList; -import com.google.gwt.user.client.rpc.IsSerializable; -import com.sap.sailing.gwt.ui.shared.general.EventState; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.home.communication.event.EventState; -public class EventListViewDTO implements IsSerializable { +public class EventListViewDTO implements DTO, Result { private ArrayList upcomingEvents = new ArrayList<>(); private ArrayList recentEvents = new ArrayList<>(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListYearDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListYearDTO.java similarity index 96% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListYearDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListYearDTO.java index 31539135813..3fb3ede72e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventlist/EventListYearDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventlist/EventListYearDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.eventlist; +package com.sap.sailing.gwt.home.communication.eventlist; import java.util.ArrayList; import java.util.List; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/EventViewDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/EventViewDTO.java similarity index 90% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/EventViewDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/EventViewDTO.java index cd49f3867d6..9c87ec409ce 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/EventViewDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/EventViewDTO.java @@ -1,14 +1,14 @@ -package com.sap.sailing.gwt.ui.shared.eventview; +package com.sap.sailing.gwt.home.communication.eventview; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.TreeSet; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sailing.gwt.ui.shared.general.HasLogo; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.HasLogo; import com.sap.sse.gwt.client.media.ImageDTO; public class EventViewDTO extends EventMetadataDTO implements Result, HasLogo { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/HasRegattaMetadata.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/HasRegattaMetadata.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/HasRegattaMetadata.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/HasRegattaMetadata.java index 33087059c62..7a2c2688216 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/HasRegattaMetadata.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/HasRegattaMetadata.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.eventview; +package com.sap.sailing.gwt.home.communication.eventview; import java.util.Date; -import com.sap.sailing.gwt.ui.shared.general.LabelType; +import com.sap.sailing.gwt.home.communication.event.LabelType; public interface HasRegattaMetadata { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaMetadataDTO.java similarity index 97% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaMetadataDTO.java index 27a4aa39a10..b4831dddf85 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaMetadataDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.eventview; +package com.sap.sailing.gwt.home.communication.eventview; import java.util.Date; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaReferenceDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaReferenceDTO.java similarity index 89% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaReferenceDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaReferenceDTO.java index 89e6b2d1581..8a673046e7b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaReferenceDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaReferenceDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.eventview; +package com.sap.sailing.gwt.home.communication.eventview; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class RegattaReferenceDTO implements DTO, Comparable { private String id; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaViewDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaViewDTO.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaViewDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaViewDTO.java index 44e25cead63..92686e24410 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/eventview/RegattaViewDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/eventview/RegattaViewDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.eventview; +package com.sap.sailing.gwt.home.communication.eventview; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/fakeseries/EventSeriesViewDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/EventSeriesViewDTO.java similarity index 85% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/fakeseries/EventSeriesViewDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/EventSeriesViewDTO.java index fb3082ed45d..0e7e1ea4a0e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/fakeseries/EventSeriesViewDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/EventSeriesViewDTO.java @@ -1,16 +1,16 @@ -package com.sap.sailing.gwt.ui.shared.fakeseries; +package com.sap.sailing.gwt.home.communication.fakeseries; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import com.google.gwt.user.client.rpc.IsSerializable; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.HasLogo; -import com.sap.sailing.gwt.ui.shared.general.LabelType; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.HasLogo; +import com.sap.sailing.gwt.home.communication.event.LabelType; import com.sap.sse.gwt.client.media.ImageDTO; -public class EventSeriesViewDTO implements IsSerializable, HasLogo { +public class EventSeriesViewDTO implements Result, HasLogo { private UUID id; private String displayName; private ArrayList events = new ArrayList<>(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/GetEventSeriesViewAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/GetEventSeriesViewAction.java new file mode 100644 index 00000000000..08d5eb8091b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/fakeseries/GetEventSeriesViewAction.java @@ -0,0 +1,102 @@ +package com.sap.sailing.gwt.home.communication.fakeseries; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO.EventSeriesState; +import com.sap.sailing.gwt.server.HomeServiceUtil; +import com.sap.sse.common.media.MediaTagConstants; +import com.sap.sse.shared.media.ImageDescriptor; + +public class GetEventSeriesViewAction implements SailingAction, IsClientCacheable { + + private UUID id; + + @SuppressWarnings("unused") + private GetEventSeriesViewAction() { + } + + public GetEventSeriesViewAction(UUID id) { + super(); + this.id = id; + } + + @Override + @GwtIncompatible + public EventSeriesViewDTO execute(SailingDispatchContext ctx) throws DispatchException { + Event o = ctx.getRacingEventService().getEvent(id); + if (o == null) { + throw new RuntimeException("Series not found"); + } + + EventSeriesViewDTO dto = new EventSeriesViewDTO(); + dto.setId(id); + ImageDescriptor logoImage = o.findImageWithTag(MediaTagConstants.LOGO); + dto.setLogoImage(logoImage != null ? HomeServiceUtil.convertToImageDTO(logoImage) : null); + // TODO implement correctly. We currently do not show media for series. + dto.setHasMedia(false); + + boolean oneEventStarted = false; + boolean oneEventLive = false; + boolean allFinished = true; + if (HomeServiceUtil.isFakeSeries(o)) { + LeaderboardGroup overallLeaderboardGroup = o.getLeaderboardGroups().iterator().next(); + dto.setDisplayName(overallLeaderboardGroup.getDisplayName() != null ? overallLeaderboardGroup.getDisplayName() : overallLeaderboardGroup.getName()); + + if (overallLeaderboardGroup.getOverallLeaderboard() != null) { + dto.setLeaderboardId(overallLeaderboardGroup.getOverallLeaderboard().getName()); + } + + List fakeSeriesEvents = new ArrayList(); + for (Event event : ctx.getRacingEventService().getAllEvents()) { + for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + if (overallLeaderboardGroup.equals(leaderboardGroup)) { + fakeSeriesEvents.add(event); + } + } + } + Collections.sort(fakeSeriesEvents, new Comparator() { + public int compare(Event e1, Event e2) { + return e1.getStartDate().compareTo(e2.getEndDate()); + } + }); + for(Event eventInSeries: fakeSeriesEvents) { + EventMetadataDTO eventOfSeries = HomeServiceUtil.convertToMetadataDTO(eventInSeries, ctx.getRacingEventService()); + dto.addEvent(eventOfSeries); + + oneEventStarted |= eventOfSeries.isStarted(); + oneEventLive |= (eventOfSeries.isStarted() && !eventOfSeries.isFinished()); + allFinished &= eventOfSeries.isFinished(); + } + } + if(oneEventLive) { + dto.setState(EventSeriesState.RUNNING); + } else if(!oneEventStarted) { + dto.setState(EventSeriesState.UPCOMING); + } else if(allFinished) { + dto.setState(EventSeriesState.FINISHED); + } else { + dto.setState(EventSeriesState.IN_PROGRESS); + } + + dto.setHasAnalytics(oneEventStarted); + return dto; + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(id); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/GetMediaForEventAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/GetMediaForEventAction.java new file mode 100644 index 00000000000..57eca9404b1 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/GetMediaForEventAction.java @@ -0,0 +1,63 @@ +package com.sap.sailing.gwt.home.communication.media; + +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.server.HomeServiceUtil; +import com.sap.sailing.gwt.ui.shared.media.MediaConstants; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +public class GetMediaForEventAction implements SailingAction, IsClientCacheable { + + private UUID eventId; + + @SuppressWarnings("unused") + private GetMediaForEventAction() { + } + + public GetMediaForEventAction(UUID eventId) { + this.eventId = eventId; + } + + @Override + @GwtIncompatible + public MediaDTO execute(SailingDispatchContext ctx) throws DispatchException { + Event event = ctx.getRacingEventService().getEvent(eventId); + EventReferenceDTO eventRef = new EventReferenceDTO(event); + + String eventName = event.getName(); + MediaDTO media = new MediaDTO(); + for(ImageDescriptor image : HomeServiceUtil.getPhotoGalleryImages(event)) { + SailingImageDTO imageDTO = new SailingImageDTO(eventRef, image.getURL().toString(), image.getCreatedAtDate().asDate()); + imageDTO.setSizeInPx(image.getWidthInPx(), image.getHeightInPx()); + imageDTO.setTitle(image.getTitle() != null ? image.getTitle(): eventName); + imageDTO.setSubtitle(image.getSubtitle()); + imageDTO.setTags(image.getTags()); + imageDTO.setCopyright(image.getCopyright()); + imageDTO.setLocale(image.getLocale() != null ? image.getLocale().toString() : null); + media.addPhoto(imageDTO); + } + for(VideoDescriptor video : event.getVideos()) { + MimeType type = video.getMimeType(); + if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { + SailingVideoDTO videoDTO = HomeServiceUtil.toSailingVideoDTO(eventRef, video); + media.addVideo(videoDTO); + } + } + return media; + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(eventId); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/MediaDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/MediaDTO.java similarity index 73% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/MediaDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/MediaDTO.java index e429d42626c..f22e9a42e6b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/MediaDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/MediaDTO.java @@ -1,11 +1,11 @@ -package com.sap.sailing.gwt.ui.shared.media; +package com.sap.sailing.gwt.home.communication.media; -import java.io.Serializable; import java.util.Collection; import java.util.TreeSet; -public class MediaDTO implements Serializable { - private static final long serialVersionUID = 4932700214423641309L; +import com.sap.sailing.gwt.dispatch.client.Result; + +public class MediaDTO implements Result { private TreeSet photos = new TreeSet<>(); private TreeSet videos = new TreeSet<>(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingImageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingImageDTO.java similarity index 90% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingImageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingImageDTO.java index 8073004d049..a565403ac5a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingImageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingImageDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.media; +package com.sap.sailing.gwt.home.communication.media; import java.util.Date; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; import com.sap.sse.gwt.client.media.AbstractMediaDTO; import com.sap.sse.gwt.client.media.ImageDTO; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingVideoDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingVideoDTO.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingVideoDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingVideoDTO.java index fede6eea00b..490f07fd631 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/media/SailingVideoDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/media/SailingVideoDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.media; +package com.sap.sailing.gwt.home.communication.media; import java.util.Date; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; import com.sap.sse.common.media.MimeType; import com.sap.sse.gwt.client.media.AbstractMediaDTO; import com.sap.sse.gwt.client.media.VideoDTO; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FlagStateDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FlagStateDTO.java similarity index 95% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FlagStateDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FlagStateDTO.java index 35943e2a4f2..986633d7934 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FlagStateDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FlagStateDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race; +package com.sap.sailing.gwt.home.communication.race; import com.google.gwt.user.client.rpc.IsSerializable; import com.sap.sailing.domain.common.racelog.Flags; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FleetMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FleetMetadataDTO.java similarity index 96% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FleetMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FleetMetadataDTO.java index 9a57394a1c1..aedef17ac7a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/FleetMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/FleetMetadataDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race; +package com.sap.sailing.gwt.home.communication.race; import com.google.gwt.user.client.rpc.IsSerializable; import com.sap.sailing.domain.common.LeaderboardNameConstants; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceMetadataDTO.java similarity index 95% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceMetadataDTO.java index d45305e74d7..300a561f061 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceMetadataDTO.java @@ -1,7 +1,7 @@ -package com.sap.sailing.gwt.ui.shared.race; +package com.sap.sailing.gwt.home.communication.race; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.gwt.ui.shared.race.wind.AbstractWindDTO; +import com.sap.sailing.gwt.home.communication.race.wind.AbstractWindDTO; import com.sap.sse.common.Util; public abstract class RaceMetadataDTO extends SimpleRaceMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceProgressDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceProgressDTO.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceProgressDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceProgressDTO.java index 618b3241276..8a6aac93efb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/RaceProgressDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/RaceProgressDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race; +package com.sap.sailing.gwt.home.communication.race; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/SimpleRaceMetadataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/SimpleRaceMetadataDTO.java similarity index 82% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/SimpleRaceMetadataDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/SimpleRaceMetadataDTO.java index af463559990..3ec6a9ee546 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/SimpleRaceMetadataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/SimpleRaceMetadataDTO.java @@ -1,10 +1,13 @@ -package com.sap.sailing.gwt.ui.shared.race; +package com.sap.sailing.gwt.home.communication.race; +import java.util.Collection; import java.util.Date; +import java.util.HashSet; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; import com.sap.sse.common.Util; import com.sap.sse.common.util.NaturalComparator; @@ -57,12 +60,15 @@ public class SimpleRaceMetadataDTO implements DTO, Comparable competitors = new HashSet<>(); + protected SimpleRaceMetadataDTO() { } @@ -84,6 +90,14 @@ public class SimpleRaceMetadataDTO implements DTO, Comparable competitors) { + this.competitors.addAll(competitors); + } + + public Collection getCompetitors() { + return competitors; + } + @Override public int compareTo(SimpleRaceMetadataDTO o) { final int compareByRaceName = new NaturalComparator().compare(getRaceName(), o.getRaceName()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/AbstractWindDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/AbstractWindDTO.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/AbstractWindDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/AbstractWindDTO.java index e372809709d..b7eae5b32e0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/AbstractWindDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/AbstractWindDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race.wind; +package com.sap.sailing.gwt.home.communication.race.wind; import com.google.gwt.user.client.rpc.IsSerializable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/SimpleWindDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/SimpleWindDTO.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/SimpleWindDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/SimpleWindDTO.java index c5435c8b3be..df1750a6b48 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/SimpleWindDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/SimpleWindDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race.wind; +package com.sap.sailing.gwt.home.communication.race.wind; public class SimpleWindDTO extends AbstractWindDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/WindStatisticsDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/WindStatisticsDTO.java similarity index 93% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/WindStatisticsDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/WindStatisticsDTO.java index ab5ff2d2614..23f45b6e444 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/race/wind/WindStatisticsDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/race/wind/WindStatisticsDTO.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.race.wind; +package com.sap.sailing.gwt.home.communication.race.wind; public class WindStatisticsDTO extends AbstractWindDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressDTO.java similarity index 79% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressDTO.java index 5c7885fba0b..3ad98235224 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressDTO.java @@ -1,9 +1,9 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.regatta; +package com.sap.sailing.gwt.home.communication.regatta; import java.util.ArrayList; import java.util.List; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class RegattaProgressDTO implements DTO { private ArrayList series = new ArrayList<>(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressFleetDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressFleetDTO.java similarity index 88% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressFleetDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressFleetDTO.java index 17e3457278c..41db81e445c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressFleetDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressFleetDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.regatta; +package com.sap.sailing.gwt.home.communication.regatta; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public class RegattaProgressFleetDTO implements DTO { private int raceCount; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressSeriesDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressSeriesDTO.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressSeriesDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressSeriesDTO.java index 5423a372393..8fa8155e78c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaProgressSeriesDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaProgressSeriesDTO.java @@ -1,10 +1,10 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.regatta; +package com.sap.sailing.gwt.home.communication.regatta; import java.util.Map; import java.util.TreeMap; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; public class RegattaProgressSeriesDTO implements DTO { private String name; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaWithProgressDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaWithProgressDTO.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaWithProgressDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaWithProgressDTO.java index 4e8f221f8ac..5fdcbe5d5df 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/regatta/RegattaWithProgressDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/regatta/RegattaWithProgressDTO.java @@ -1,7 +1,7 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.regatta; +package com.sap.sailing.gwt.home.communication.regatta; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaReferenceDTO; public class RegattaWithProgressDTO extends RegattaMetadataDTO { private RegattaProgressDTO progress; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchResultsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchResultsAction.java new file mode 100644 index 00000000000..5b218d6a4e0 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchResultsAction.java @@ -0,0 +1,68 @@ +package com.sap.sailing.gwt.home.communication.search; + +import java.net.URL; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.LeaderboardSearchResultBase; +import com.sap.sailing.domain.base.RemoteSailingServerReference; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.dispatch.client.batching.NonBatchableAction; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.server.RacingEventService; +import com.sap.sse.common.Util; +import com.sap.sse.common.search.KeywordQuery; +import com.sap.sse.common.search.Result; + +/** + * Use this action once for each result of {@link GetSearchServerNamesAction} and once for the main server. + * + * @see {@link #GetSearchResultsAction(String)} to search on the server to which this request is sent + * @see #GetSearchResultsAction(String, String) use a name as retrieved by {@link GetSearchServerNamesAction} which + * corresponds to a name of a {@link RemoteSailingServerReference}, to search a remote server. + */ +public class GetSearchResultsAction implements SailingAction>, NonBatchableAction { + + private String searchText; + private String remoteServerName; + + @SuppressWarnings("unused") + private GetSearchResultsAction() { + } + + public GetSearchResultsAction(String searchText) { + this(searchText, null); + } + + public GetSearchResultsAction(String searchText, String remoteServerName) { + this.searchText = searchText; + this.remoteServerName = remoteServerName; + } + + @Override + @GwtIncompatible + public ListResult execute(SailingDispatchContext ctx) throws DispatchException { + KeywordQuery searchQuery = new KeywordQuery(searchText.split("[ \t]+")); + RacingEventService service = ctx.getRacingEventService(); + if (remoteServerName == null) { + return getListResult(service.search(searchQuery), ctx.getRequestBaseURL(), false); + } + RemoteSailingServerReference remoteServer = service.getRemoteServerReferenceByName(remoteServerName); + return getListResult(service.searchRemotely(remoteServerName, searchQuery), remoteServer.getURL(), true); + } + + @GwtIncompatible + private ListResult getListResult(Result result, + URL baseUrl, boolean isOnRemoteServer) { + ListResult resultList = new ListResult<>(); + for (T hit : result.getHits()) { + // TODO: for now filter all results where we no event is defined + if (hit.getEvents() != null && !Util.isEmpty(hit.getEvents())) { + resultList.addValue(new SearchResultDTO(hit, baseUrl, isOnRemoteServer)); + } + } + return resultList; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchServerNamesAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchServerNamesAction.java new file mode 100644 index 00000000000..d2e0ffd1d4b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/GetSearchServerNamesAction.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.home.communication.search; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.RemoteSailingServerReference; +import com.sap.sailing.gwt.dispatch.client.StringsResult; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; + +/** + * A client should search a server in a two-step process. First, the client should ask the server which other servers + * are available for searching additional content. Then, in a second step, the client should fire the queries by + * parallel asynchronous action executions to the one server, passing the name of the remote server reference to search, + * or null in order to search the server to which the query is executed. This allows a client to + * asynchronously receive the results from various servers, not requiring the client to block until all results from all + * servers have been received. The key reason for this two-step process is that the GWT RPC does not support streaming + * of results. + * + * This action load the list of server reference names, corresponding with {@link RemoteSailingServerReference#getName()}, + * to be used as parameter in {@link GetSearchResultsAction}. This list does not contain the null + * value used to represent the search on the main server to which the query is sent. + * + * @see GetSearchResultsAction#GetSearchResultsAction(String, String) + */ +public class GetSearchServerNamesAction implements SailingAction { + + @Override + @GwtIncompatible + public StringsResult execute(SailingDispatchContext ctx) throws DispatchException { + StringsResult result = new StringsResult(); + for (RemoteSailingServerReference remoteServerRef : ctx.getRacingEventService().getLiveRemoteServerReferences()) { + result.addValue(remoteServerRef.getName()); + } + return result; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultDTO.java new file mode 100644 index 00000000000..b1f56acac9c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultDTO.java @@ -0,0 +1,56 @@ +package com.sap.sailing.gwt.home.communication.search; + +import java.net.URL; +import java.util.Set; +import java.util.TreeSet; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.LeaderboardSearchResultBase; +import com.sap.sailing.gwt.dispatch.client.DTO; + +public class SearchResultDTO implements DTO { + + private String displayName; + private String leaderboardName; + private String baseUrl; + private boolean isOnRemoteServer; + private TreeSet events = new TreeSet<>(); + + @SuppressWarnings("unused") + private SearchResultDTO() { + } + + @GwtIncompatible + public SearchResultDTO(LeaderboardSearchResultBase hit, URL baseUrl, boolean isOnRemoteServer) { + this.leaderboardName = hit.getLeaderboard().getName(); + this.displayName = hit.getLeaderboard().getDisplayName() != null ? hit.getLeaderboard().getDisplayName() : + (hit.getRegattaName() != null ? hit.getRegattaName() : leaderboardName); + this.baseUrl = baseUrl.toString(); + this.isOnRemoteServer = isOnRemoteServer; + for (EventBase event : hit.getEvents()) { + events.add(new SearchResultEventInfoDTO(event)); + } + } + + public String getDisplayName() { + return displayName; + } + + public String getLeaderboardName() { + return leaderboardName; + } + + public String getBaseUrl() { + return baseUrl; + } + + public boolean isOnRemoteServer() { + return isOnRemoteServer; + } + + public Set getEvents() { + return events; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultEventInfoDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultEventInfoDTO.java new file mode 100644 index 00000000000..6e9160e2c64 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/search/SearchResultEventInfoDTO.java @@ -0,0 +1,57 @@ +package com.sap.sailing.gwt.home.communication.search; + +import java.util.Date; +import java.util.UUID; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sse.common.util.NaturalComparator; + +public class SearchResultEventInfoDTO implements DTO, Comparable { + + private UUID id; + private String name; + private String venueName; + private Date startDate; + private Date endDate; + + @SuppressWarnings("unused") + private SearchResultEventInfoDTO() { + } + + @GwtIncompatible + public SearchResultEventInfoDTO(EventBase event) { + this.id = (UUID) event.getId(); + this.name = event.getName(); + this.venueName = event.getVenue() != null ? event.getVenue().getName() : null; + this.startDate = event.getStartDate() != null ? event.getStartDate().asDate() : null; + this.endDate = event.getEndDate() != null ? event.getEndDate().asDate() : null; + } + + public UUID getId() { + return id; + } + + public String getName() { + return name; + } + + public String getVenueName() { + return venueName; + } + + public Date getStartDate() { + return startDate; + } + + public Date getEndDate() { + return endDate; + } + + @Override + public int compareTo(SearchResultEventInfoDTO other) { + return new NaturalComparator().compare(this.name, other.name); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/EventQuickfinderDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventQuickfinderDTO.java similarity index 86% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/EventQuickfinderDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventQuickfinderDTO.java index 803ffe1bd87..0ed305f0960 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/EventQuickfinderDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventQuickfinderDTO.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.start; +package com.sap.sailing.gwt.home.communication.start; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; import com.sap.sse.common.TimePoint; public class EventQuickfinderDTO extends EventReferenceDTO implements DTO, Comparable { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/EventStageDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventStageDTO.java similarity index 79% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/EventStageDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventStageDTO.java index db896042f4a..7db953cf584 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/EventStageDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/EventStageDTO.java @@ -1,6 +1,6 @@ -package com.sap.sailing.gwt.ui.shared.start; +package com.sap.sailing.gwt.home.communication.start; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; public class EventStageDTO extends EventLinkAndMetadataDTO { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetRecentEventsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetRecentEventsAction.java similarity index 70% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetRecentEventsAction.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetRecentEventsAction.java index 6fdd73eec8b..665277ce74b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetRecentEventsAction.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetRecentEventsAction.java @@ -1,6 +1,5 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.start; +package com.sap.sailing.gwt.home.communication.start; -import java.net.MalformedURLException; import java.net.URL; import java.util.SortedSet; import java.util.TreeSet; @@ -8,13 +7,15 @@ import java.util.UUID; import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; import com.sap.sailing.gwt.server.HomeServiceUtil; import com.sap.sailing.gwt.server.HomeServiceUtil.EventVisitor; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -public class GetRecentEventsAction implements Action> { +public class GetRecentEventsAction implements SailingAction>, IsClientCacheable { private int limit; @@ -26,7 +27,7 @@ public class GetRecentEventsAction implements Action execute(final DispatchContext context) throws MalformedURLException { + public ListResult execute(final SailingDispatchContext context) throws DispatchException { final SortedSet events = new TreeSet<>(); HomeServiceUtil.forAllPublicEvents(context.getRacingEventService(), context.getRequest(), new EventVisitor() { @Override @@ -52,4 +53,9 @@ public class GetRecentEventsAction implements Action>, IsClientCacheable { + private boolean useTeaserImage; + + protected GetStagedEventsAction() { + } + + public GetStagedEventsAction(boolean useTeaserImage) { + this.useTeaserImage = useTeaserImage; + } + + @GwtIncompatible + public ListResult execute(final SailingDispatchContext context) throws DispatchException { + EventStageCandidateCalculator stageCandidateCalculator = new EventStageCandidateCalculator(); + HomeServiceUtil.forAllPublicEvents(context.getRacingEventService(), context.getRequest(), + stageCandidateCalculator); + ListResult result = new ListResult<>(); + int count = 0; + for (Pair pair : stageCandidateCalculator.getFeaturedEvents()) { + count++; + if (count > EventStageCandidateCalculator.MAX_STAGE_EVENTS) { + break; + } + StageEventType stageType = pair.getA(); + EventHolder holder = pair.getB(); + result.addValue(HomeServiceUtil.convertToEventStageDTO(holder.event, holder.baseURL, holder.onRemoteServer, + stageType, context.getRacingEventService(), useTeaserImage)); + } + return result; + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + key.append(useTeaserImage); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetStartViewAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetStartViewAction.java new file mode 100644 index 00000000000..7e0932e201a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/GetStartViewAction.java @@ -0,0 +1,139 @@ +package com.sap.sailing.gwt.home.communication.start; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Random; +import java.util.Set; + +import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.gwt.dispatch.client.caching.IsClientCacheable; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; +import com.sap.sailing.gwt.home.communication.media.SailingVideoDTO; +import com.sap.sailing.gwt.server.EventHolder; +import com.sap.sailing.gwt.server.EventStageCandidateCalculator; +import com.sap.sailing.gwt.server.HomeServiceUtil; +import com.sap.sailing.gwt.server.RecentEventsCalculator; +import com.sap.sailing.gwt.ui.shared.media.MediaConstants; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +public class GetStartViewAction implements SailingAction, IsClientCacheable { + private static final int MAX_RECENT_EVENTS = 3; + private static final int MAX_VIDEO_COUNT = 3; + + public GetStartViewAction() { + } + + @GwtIncompatible + public StartViewDTO execute(SailingDispatchContext context) { + EventStageCandidateCalculator stageCandidateCalculator = new EventStageCandidateCalculator(); + RecentEventsCalculator recentEventsCalculator = new RecentEventsCalculator(); + + HomeServiceUtil.forAllPublicEvents(context.getRacingEventService(), context.getRequest(), stageCandidateCalculator, recentEventsCalculator); + + StartViewDTO result = new StartViewDTO(); + + int count = 0; + for(Pair pair : stageCandidateCalculator.getFeaturedEvents()) { + StageEventType stageType = pair.getA(); + EventHolder holder = pair.getB(); + + count++; + if(count > EventStageCandidateCalculator.MAX_STAGE_EVENTS && stageType != StageEventType.RUNNING) { + break; + } + + result.addStageEvent(HomeServiceUtil.convertToEventStageDTO(holder.event, holder.baseURL, holder.onRemoteServer, stageType, context.getRacingEventService(), false)); + + EventReferenceDTO eventRef = new EventReferenceDTO(holder.event); + + Iterable videosOfEvent = holder.event.getVideos(); + if (!Util.isEmpty(videosOfEvent) && result.getVideos().size() < MAX_VIDEO_COUNT) { + VideoDescriptor youTubeRandomUrl = HomeServiceUtil.getRandomVideo(videosOfEvent); + + MimeType type = youTubeRandomUrl.getMimeType(); + if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { + SailingVideoDTO candidate = new SailingVideoDTO(eventRef, youTubeRandomUrl.getURL().toString(), type, // + youTubeRandomUrl.getCreatedAtDate().asDate() + ); + candidate.setTitle(holder.event.getName()); + result.addVideo(candidate); + } + } + } + + final Set photoGalleryUrls = new HashSet<>(); // using a HashSet here leads to a reasonable + // amount of shuffling + final List videoCandidates = new ArrayList<>(); + + for(EventHolder holder : recentEventsCalculator.getRecentEventsOfLast12Month()) { + if(result.getRecentEvents().size() < MAX_RECENT_EVENTS) { + result.addRecentEvent(HomeServiceUtil.convertToEventListDTO(holder.event, holder.baseURL, holder.onRemoteServer, context.getRacingEventService())); + } + + EventBase event = holder.event; + EventReferenceDTO eventRef = new EventReferenceDTO(holder.event); + + for (ImageDescriptor url : HomeServiceUtil.getSailingLovesPhotographyImages(event)) { + if(url.hasSize()) { + SailingImageDTO sailingImageDTO = new SailingImageDTO(eventRef, url.getURL().toString(), null); + sailingImageDTO.setSizeInPx(url.getWidthInPx(), url.getHeightInPx()); + photoGalleryUrls.add(sailingImageDTO); + } + } + for (VideoDescriptor videoUrl : event.getVideos()) { + MimeType type = videoUrl.getMimeType(); + if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { + SailingVideoDTO candidate = new SailingVideoDTO(eventRef, videoUrl.getURL().toString(), type, // + videoUrl.getCreatedAtDate().asDate() + ); + candidate.setTitle(holder.event.getName()); + videoCandidates.add(candidate); + } + } + } + + final int numberOfCandidatesAvailable = videoCandidates.size(); + if (numberOfCandidatesAvailable <= (MAX_VIDEO_COUNT - result.getVideos().size())) { + // add all we have, no randomize + for (SailingVideoDTO video : videoCandidates) { + result.addVideo(video); + } + } else { + // fill up the list randomly from videoCandidates + final Random videosRandomizer = new Random(numberOfCandidatesAvailable); + randomlyPick: for (int i = 0; i < numberOfCandidatesAvailable; i++) { + int nextVideoindex = videosRandomizer.nextInt(numberOfCandidatesAvailable); + final SailingVideoDTO video = videoCandidates.get(nextVideoindex); + result.addVideo(video); + if (result.getVideos().size() == MAX_VIDEO_COUNT) { + break randomlyPick; + } + } + } + Random random = new Random(); + List shuffledPhotoGallery = new ArrayList<>(photoGalleryUrls); + final int gallerySize = photoGalleryUrls.size(); + for (int i = 0; i < gallerySize; i++) { + Collections.swap(shuffledPhotoGallery, i, random.nextInt(gallerySize)); + } + for (SailingImageDTO holder : shuffledPhotoGallery) { + result.addPhoto(holder); + } + // TODO media + return result; + } + + @Override + public void cacheInstanceKey(StringBuilder key) { + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StageEventType.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StageEventType.java similarity index 55% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StageEventType.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StageEventType.java index d2507f9f64a..2d657428b7e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StageEventType.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StageEventType.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.start; +package com.sap.sailing.gwt.home.communication.start; public enum StageEventType { RUNNING, UPCOMING_SOON, POPULAR diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StartViewDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StartViewDTO.java similarity index 76% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StartViewDTO.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StartViewDTO.java index fb2d448a9ae..15e51419686 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/start/StartViewDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/communication/start/StartViewDTO.java @@ -1,16 +1,16 @@ -package com.sap.sailing.gwt.ui.shared.start; +package com.sap.sailing.gwt.home.communication.start; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; -import com.google.gwt.user.client.rpc.IsSerializable; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; +import com.sap.sailing.gwt.home.communication.media.SailingVideoDTO; -public class StartViewDTO implements IsSerializable { +public class StartViewDTO implements Result { private ArrayList stageEvents = new ArrayList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/DesktopEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/DesktopEntryPoint.java index e89fe17ca92..913b1064c91 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/DesktopEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/DesktopEntryPoint.java @@ -1,9 +1,13 @@ package com.sap.sailing.gwt.home.desktop; +import com.google.gwt.activity.shared.ActivityManager; +import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.sap.sailing.gwt.common.client.SharedResources; +import com.sap.sailing.gwt.home.desktop.app.DesktopActivityManager; import com.sap.sailing.gwt.home.desktop.app.DesktopActivityMapper; import com.sap.sailing.gwt.home.desktop.app.DesktopClientFactory; import com.sap.sailing.gwt.home.desktop.app.TabletAndDesktopApplicationClientFactory; @@ -17,9 +21,11 @@ import com.sap.sse.gwt.client.mvp.AbstractMvpEntryPoint; import com.sap.sse.gwt.resources.CommonControlsCSS; import com.sap.sse.gwt.resources.Highcharts; -public class DesktopEntryPoint extends AbstractMvpEntryPoint { +public class DesktopEntryPoint extends AbstractMvpEntryPoint { @Override public void doOnModuleLoad() { + Document.get().getBody().addClassName(SharedResources.INSTANCE.mainCss().desktop()); + CommonControlsCSS.ensureInjected(); Highcharts.ensureInjected(); @@ -43,13 +49,17 @@ public class DesktopEntryPoint extends AbstractMvpEntryPoint { DesktopClientFactory clientFactory = new TabletAndDesktopApplicationClientFactory(isStandaloneServer); ApplicationHistoryMapper applicationHistoryMapper = GWT.create(ApplicationHistoryMapper.class); initMvp(clientFactory, applicationHistoryMapper, new DesktopActivityMapper(clientFactory)); - - SharedResources.INSTANCE.mediaCss().ensureInjected(); - SharedResources.INSTANCE.mainCss().ensureInjected(); } @Override protected StringMessages createStringMessages() { return GWT.create(StringMessages.class); } + + @Override + protected ActivityManager createActivityManager(ActivityMapper activityMapperRegistry, DesktopClientFactory clientFactory) { + DesktopActivityManager sailingActivityManager = new DesktopActivityManager(activityMapperRegistry, clientFactory.getEventBus()); + sailingActivityManager.setNavigationPathDisplay(clientFactory.getNavigationPathDisplay()); + return sailingActivityManager; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/AbstractApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/AbstractApplicationClientFactory.java old mode 100755 new mode 100644 index e3078db617d..ce10e5ff6b0 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/AbstractApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/AbstractApplicationClientFactory.java @@ -6,8 +6,6 @@ import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.web.bindery.event.shared.EventBus; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.client.HomeService; -import com.sap.sailing.gwt.ui.client.HomeServiceAsync; import com.sap.sailing.gwt.ui.client.MediaService; import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; @@ -16,22 +14,19 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.security.ui.client.SecureClientFactoryImpl; -public abstract class AbstractApplicationClientFactory extends - SecureClientFactoryImpl implements DesktopClientFactory { +public abstract class AbstractApplicationClientFactory> extends + SecureClientFactoryImpl implements DesktopClientFactory { private final SailingServiceAsync sailingService; - private final HomeServiceAsync homeService; private final MediaServiceAsync mediaService; private final DesktopPlacesNavigator navigator; - public AbstractApplicationClientFactory(ApplicationTopLevelView root, EventBus eventBus, + public AbstractApplicationClientFactory(ATLV root, EventBus eventBus, PlaceController placeController, final DesktopPlacesNavigator navigator) { super(root, eventBus, placeController); this.navigator = navigator; sailingService = GWT.create(SailingService.class); - homeService = GWT.create(HomeService.class); mediaService = GWT.create(MediaService.class); EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.sailingServiceRemotePath); - EntryPointHelper.registerASyncService((ServiceDefTarget) homeService, RemoteServiceMappingConstants.homeServiceRemotePath); EntryPointHelper.registerASyncService((ServiceDefTarget) mediaService, RemoteServiceMappingConstants.mediaServiceRemotePath); } @@ -45,11 +40,6 @@ public abstract class AbstractApplicationClientFactory extends return sailingService; } - @Override - public HomeServiceAsync getHomeService() { - return homeService; - } - @Override public MediaServiceAsync getMediaService() { return mediaService; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/ApplicationTopLevelView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/ApplicationTopLevelView.java index 11764e859be..bd3fdb4921f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/ApplicationTopLevelView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/ApplicationTopLevelView.java @@ -1,7 +1,9 @@ package com.sap.sailing.gwt.home.desktop.app; +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; import com.sap.sse.gwt.client.mvp.TopLevelView; -public interface ApplicationTopLevelView extends TopLevelView { +public interface ApplicationTopLevelView extends TopLevelView { void showLoading(boolean visibile); + NPD getNavigationPathDisplay(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityManager.java new file mode 100644 index 00000000000..db887a2371b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityManager.java @@ -0,0 +1,21 @@ +package com.sap.sailing.gwt.home.desktop.app; + +import com.google.gwt.activity.shared.Activity; +import com.google.gwt.activity.shared.ActivityMapper; +import com.google.web.bindery.event.shared.EventBus; +import com.sap.sailing.gwt.home.shared.app.SailingActivityManager; + +public class DesktopActivityManager extends SailingActivityManager { + + public DesktopActivityManager(ActivityMapper mapper, EventBus eventBus) { + super(mapper, eventBus); + } + + @Override + protected void afterNavigationPathIsSetToActivity(Activity activity) { + super.afterNavigationPathIsSetToActivity(activity); + if(activity instanceof WithHeader) { + getNavigationPathDisplay().setWithHeader(true); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityMapper.java index 739f4a17fdf..ca4cd000da2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopActivityMapper.java @@ -3,16 +3,14 @@ package com.sap.sailing.gwt.home.desktop.app; import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.place.shared.Place; +import com.sap.sailing.gwt.common.client.formfactor.DeviceDetector; import com.sap.sailing.gwt.home.desktop.places.aboutus.AboutUsActivityProxy; import com.sap.sailing.gwt.home.desktop.places.aboutus.AboutUsPlace; import com.sap.sailing.gwt.home.desktop.places.contact.ContactActivityProxy; import com.sap.sailing.gwt.home.desktop.places.contact.ContactPlace; import com.sap.sailing.gwt.home.desktop.places.error.ErrorActivityProxy; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; import com.sap.sailing.gwt.home.desktop.places.event.EventActivityProxy; import com.sap.sailing.gwt.home.desktop.places.events.EventsActivityProxy; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultActivityProxy; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.desktop.places.solutions.SolutionsActivityProxy; import com.sap.sailing.gwt.home.desktop.places.sponsoring.SponsoringActivityProxy; import com.sap.sailing.gwt.home.desktop.places.sponsoring.SponsoringPlace; @@ -21,9 +19,12 @@ import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewActivityProxy; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace; import com.sap.sailing.gwt.home.shared.SwitchingEntryPoint; import com.sap.sailing.gwt.home.shared.app.ApplicationPlaceUpdater; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultActivityProxy; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; @@ -39,7 +40,7 @@ public class DesktopActivityMapper implements ActivityMapper { @Override public Activity getActivity(Place rawPlace) { Place place = placeUpdater.getRealPlace(rawPlace); - if (SwitchingEntryPoint.isMobile() // + if (DeviceDetector.isMobile() // && !SwitchingEntryPoint.viewIsLockedToDesktop() && SwitchingEntryPoint.hasMobileVersion(place)) { SwitchingEntryPoint.reloadApp(); @@ -57,7 +58,7 @@ public class DesktopActivityMapper implements ActivityMapper { } else if (place instanceof AbstractSeriesPlace) { return new com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesActivityProxy((AbstractSeriesPlace) place, clientFactory, clientFactory.getHomePlacesNavigator()); } else if (place instanceof EventsPlace) { - return new EventsActivityProxy((EventsPlace) place, clientFactory); + return new EventsActivityProxy((EventsPlace) place, clientFactory, clientFactory.getHomePlacesNavigator()); } else if (place instanceof StartPlace) { return new StartActivityProxy((StartPlace) place, clientFactory); } else if (place instanceof SponsoringPlace) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopClientFactory.java index a90b56afe1f..e930d8b8634 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopClientFactory.java @@ -3,17 +3,18 @@ package com.sap.sailing.gwt.home.desktop.app; import com.sap.sailing.gwt.home.client.place.event.legacy.SeriesClientFactory; import com.sap.sailing.gwt.home.desktop.places.aboutus.AboutUsClientFactory; import com.sap.sailing.gwt.home.desktop.places.contact.ContactClientFactory; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorClientFactory; import com.sap.sailing.gwt.home.desktop.places.event.EventClientFactory; import com.sap.sailing.gwt.home.desktop.places.events.EventsClientFactory; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultClientFactory; import com.sap.sailing.gwt.home.desktop.places.solutions.SolutionsClientFactory; import com.sap.sailing.gwt.home.desktop.places.sponsoring.SponsoringClientFactory; import com.sap.sailing.gwt.home.desktop.places.start.StartClientFactory; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewClientFactory; +import com.sap.sailing.gwt.home.shared.places.error.ErrorClientFactory; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultClientFactory; public interface DesktopClientFactory extends AboutUsClientFactory, ContactClientFactory, EventClientFactory, EventsClientFactory, StartClientFactory, SponsoringClientFactory, SolutionsClientFactory, SearchResultClientFactory, WhatsNewClientFactory, SeriesClientFactory, ErrorClientFactory { DesktopPlacesNavigator getHomePlacesNavigator(); + DesktopResettableNavigationPathDisplay getNavigationPathDisplay(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopPlacesNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopPlacesNavigator.java index b20cfbf3094..1de1efe8804 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopPlacesNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopPlacesNavigator.java @@ -11,7 +11,6 @@ import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegatt import com.sap.sailing.gwt.home.desktop.places.event.regatta.analyticstab.RegattaCompetitorAnalyticsPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.leaderboardtab.RegattaLeaderboardPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.desktop.places.sponsoring.SponsoringPlace; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace.WhatsNewNavigationTabs; @@ -101,7 +100,4 @@ public class DesktopPlacesNavigator extends AbstractPlaceNavigator { return createPlaceNavigation(baseUrl, isOnRemoteServer, regattaPlace); } - public PlaceNavigation getSearchResultNavigation(String searchQuery) { - return createGlobalPlaceNavigation(new SearchResultPlace(searchQuery)); - } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopResettableNavigationPathDisplay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopResettableNavigationPathDisplay.java new file mode 100644 index 00000000000..f34d6fe0a9c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/DesktopResettableNavigationPathDisplay.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.desktop.app; + +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; + +public interface DesktopResettableNavigationPathDisplay extends ResettableNavigationPathDisplay { + void setWithHeader(boolean withHeader); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationClientFactory.java index d5725a3b96f..11bc8d0e8f5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationClientFactory.java @@ -3,10 +3,11 @@ package com.sap.sailing.gwt.home.desktop.app; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.place.shared.PlaceController; import com.google.web.bindery.event.shared.EventBus; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystemImpl; import com.sap.sailing.gwt.home.desktop.places.error.TabletAndDesktopErrorView; import com.sap.sailing.gwt.home.desktop.places.events.EventsView; import com.sap.sailing.gwt.home.desktop.places.events.TabletAndDesktopEventsView; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultView; import com.sap.sailing.gwt.home.desktop.places.searchresult.TabletAndDesktopSearchResultView; import com.sap.sailing.gwt.home.desktop.places.solutions.SolutionsView; import com.sap.sailing.gwt.home.desktop.places.solutions.TabletAndDesktopSolutionsView; @@ -15,15 +16,16 @@ import com.sap.sailing.gwt.home.desktop.places.sponsoring.TabletAndDesktopSponso import com.sap.sailing.gwt.home.desktop.places.start.StartView; import com.sap.sailing.gwt.home.desktop.places.start.TabletAndDesktopStartView; import com.sap.sailing.gwt.home.desktop.places.whatsnew.TabletAndDesktopWhatsNewView; -import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewView; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace.WhatsNewNavigationTabs; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystemImpl; +import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewView; +import com.sap.sailing.gwt.home.shared.partials.busy.BusyViewImpl; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultView; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace.SolutionsNavigationTabs; +import com.sap.sailing.gwt.ui.client.refresh.BusyView; -public class TabletAndDesktopApplicationClientFactory extends AbstractApplicationClientFactory implements DesktopClientFactory { - private final DispatchSystem dispatch = new DispatchSystemImpl(); +public class TabletAndDesktopApplicationClientFactory extends AbstractApplicationClientFactory> implements DesktopClientFactory { + private final SailingDispatchSystem dispatch = new SailingDispatchSystemImpl(); public TabletAndDesktopApplicationClientFactory(boolean isStandaloneServer) { this(new SimpleEventBus(), isStandaloneServer); @@ -40,6 +42,11 @@ public class TabletAndDesktopApplicationClientFactory extends AbstractApplicatio private TabletAndDesktopApplicationClientFactory(EventBus eventBus, PlaceController placeController, DesktopPlacesNavigator placesNavigator) { super(new TabletAndDesktopApplicationView(placesNavigator, eventBus), eventBus, placeController, placesNavigator); } + + @Override + public DesktopResettableNavigationPathDisplay getNavigationPathDisplay() { + return getTopLevelView().getNavigationPathDisplay(); + } @Override public TabletAndDesktopErrorView createErrorView(String errorMessage, Throwable errorReason) { @@ -77,7 +84,12 @@ public class TabletAndDesktopApplicationClientFactory extends AbstractApplicatio } @Override - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return dispatch; } + + @Override + public BusyView createBusyView() { + return new BusyViewImpl(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.java index df89893f69a..fd84b5d43c9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.home.desktop.app; import com.google.gwt.core.client.GWT; +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.ui.AcceptsOneWidget; @@ -8,8 +10,10 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.google.web.bindery.event.shared.EventBus; +import com.sap.sailing.gwt.common.client.controls.tabbar.BreadcrumbPane; import com.sap.sailing.gwt.home.desktop.partials.footer.Footer; import com.sap.sailing.gwt.home.desktop.partials.header.Header; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.DefaultErrorReporter; import com.sap.sse.gwt.client.ErrorReporter; @@ -18,7 +22,7 @@ import com.sap.sse.gwt.client.ErrorReporter; * This is the top-level view of the application. Every time another presenter wants to reveal itself, * {@link TabletAndDesktopApplicationView} will add its content of the target inside the {@code mainContantPanel}. */ -public class TabletAndDesktopApplicationView extends Composite implements ApplicationTopLevelView { +public class TabletAndDesktopApplicationView extends Composite implements ApplicationTopLevelView { interface TabletAndDesktopApplicationViewUiBinder extends UiBinder { } @@ -34,11 +38,20 @@ public class TabletAndDesktopApplicationView extends Composite implements Applic @UiField SimplePanel mainContentPanel; + + @UiField + BreadcrumbPane breadcrumbsUi; + + @UiField + DivElement breadcrumbWrapperUi; + + private final DesktopResettableNavigationPathDisplay navigationPathDisplay; public TabletAndDesktopApplicationView(DesktopPlacesNavigator navigator, EventBus eventBus) { headerPanel = new Header(navigator, eventBus); footerPanel = new Footer(navigator, eventBus); initWidget(uiBinder.createAndBindUi(this)); + navigationPathDisplay = new BreadcrumbNavigationPathDisplay(); } @Override @@ -54,5 +67,40 @@ public class TabletAndDesktopApplicationView extends Composite implements Applic public ErrorReporter getErrorReporter() { return errorReporter; } + + @Override + public DesktopResettableNavigationPathDisplay getNavigationPathDisplay() { + return navigationPathDisplay; + } + + private class BreadcrumbNavigationPathDisplay implements DesktopResettableNavigationPathDisplay { + @Override + public void setWithHeader(boolean withHeader) { + if(withHeader) { + breadcrumbWrapperUi.getStyle().setBackgroundColor("#f2f2f2"); + } else { + breadcrumbWrapperUi.getStyle().clearBackgroundColor();; + } + } + + @Override + public void showNavigationPath(NavigationItem... navigationPath) { + breadcrumbsUi.clear(); + if(ExperimentalFeatures.USE_NAVIGATION_PATH_DISPLAY_ON_DESKTOP) { + for (NavigationItem navigationPathDisplay : navigationPath) { + breadcrumbsUi.addBreadcrumbItem(navigationPathDisplay.getDisplayName(), navigationPathDisplay.getTargetUrl(), navigationPathDisplay); + } + breadcrumbWrapperUi.getStyle().clearDisplay(); + } + } + + @Override + public void reset() { + breadcrumbsUi.clear(); + breadcrumbWrapperUi.getStyle().setDisplay(Display.NONE); + breadcrumbWrapperUi.getStyle().clearBackgroundColor(); + } + + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.ui.xml index 48bfa1a3b78..45d48011aff 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/TabletAndDesktopApplicationView.ui.xml @@ -1,17 +1,32 @@ + xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials" + xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar"> .mainContent { height: 100%; } + .breadcrumb { + font-size: 1rem; + /* @alternate */ font-size: 0.866666666666667em; + font-weight: 600; + padding: 0.666666666666667em 0; + }
+
+
+
+ +
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/WithHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/WithHeader.java new file mode 100644 index 00000000000..9b09676ad4c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/app/WithHeader.java @@ -0,0 +1,5 @@ +package com.sap.sailing.gwt.home.desktop.app; + +public interface WithHeader { + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.ui.xml deleted file mode 100644 index 943cd57ce33..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.ui.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - -
-
-
-
-
-
-
-
- -
- - - -
-
-
-
-
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaser.java index 1b4beabe795..bb3941732db 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaser.java @@ -13,13 +13,13 @@ import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.LabelType; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; import com.sap.sailing.gwt.home.desktop.utils.LongNamesUtil; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.LabelType; public class EventTeaser extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaserSeriesInfoCorner.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaserSeriesInfoCorner.java index 11d9f68dc7a..ab89d9dcb4d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaserSeriesInfoCorner.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/event/EventTeaserSeriesInfoCorner.java @@ -6,9 +6,9 @@ import com.google.gwt.dom.client.DivElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; public class EventTeaserSeriesInfoCorner extends UIObject { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventheader/EventHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventheader/EventHeader.java index 71704e42210..2f4b11ddbf0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventheader/EventHeader.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventheader/EventHeader.java @@ -18,6 +18,8 @@ import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata; import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingButtons; import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingMetadataProvider; import com.sap.sailing.gwt.home.desktop.places.event.EventView; @@ -29,8 +31,6 @@ import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.home.shared.utils.LogoUtil; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata; public class EventHeader extends Composite { private static EventHeaderUiBinder uiBinder = GWT.create(EventHeaderUiBinder.class); @@ -64,7 +64,7 @@ public class EventHeader extends Composite { private Presenter presenter; public EventHeader(EventView.Presenter presenter) { - this.event = presenter.getCtx().getEventDTO(); + this.event = presenter.getEventDTO(); this.presenter = presenter; EventHeaderResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecent.java index 924c8bdf0c1..7e9cb9f423f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecent.java @@ -8,8 +8,8 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListYearDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListYearDTO; public class EventsOverviewRecent extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecentYear.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecentYear.java index 30245ab2cfd..2cb5d76cdb1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecentYear.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/EventsOverviewRecentYear.java @@ -14,13 +14,13 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListYearDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListYearDTO; public class EventsOverviewRecentYear extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/RecentEventTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/RecentEventTeaser.java index b351939a73b..041a1a068bd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/RecentEventTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsrecent/RecentEventTeaser.java @@ -5,11 +5,11 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.LabelType; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; import com.sap.sailing.gwt.home.desktop.partials.event.EventTeaser; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.LabelType; public class RecentEventTeaser extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventstage/EventOverviewStage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventstage/EventOverviewStage.java index 701581c6916..a1466829a0b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventstage/EventOverviewStage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventstage/EventOverviewStage.java @@ -12,6 +12,16 @@ import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.SharedResources; import com.sap.sailing.gwt.common.client.SharedResources.MediaCss; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewStageContentDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewTickerStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewVideoStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.GetEventOverviewStageAction; +import com.sap.sailing.gwt.home.communication.event.news.GetEventOverviewNewsAction; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.desktop.partials.updates.UpdatesBox; import com.sap.sailing.gwt.home.desktop.places.event.EventView; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; @@ -21,15 +31,6 @@ import com.sap.sailing.gwt.home.shared.partials.message.Message; import com.sap.sailing.gwt.home.shared.partials.video.Video; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewStageContentDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewTickerStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewVideoStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventOverviewNewsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventOverviewStageAction; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; public class EventOverviewStage extends Composite { @@ -73,10 +74,11 @@ public class EventOverviewStage extends Composite { public void setupRefresh(RefreshManager refreshManager) { this.refreshManager = refreshManager; - refreshManager.add(refreshable, new GetEventOverviewStageAction(presenter.getCtx().getEventDTO().getId(), false)); + EventViewDTO eventDTO = presenter.getEventDTO(); + refreshManager.add(refreshable, new GetEventOverviewStageAction(eventDTO.getId(), false)); - if(presenter.getCtx().getEventDTO().getState() == EventState.RUNNING) { - refreshManager.add(newsRefreshable, new GetEventOverviewNewsAction(presenter.getCtx().getEventDTO().getId(), 15)); + if(presenter.getEventDTO().getState() == EventState.RUNNING) { + refreshManager.add(newsRefreshable, new GetEventOverviewNewsAction(presenter.getEventDTO().getId(), 15)); } else { updatesUi.removeFromParent(); updatesWrapperUi.removeFromParent(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcoming.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcoming.java index 1aeb4405d70..b48df181c89 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcoming.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcoming.java @@ -15,11 +15,11 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; public class EventsOverviewUpcoming extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcomingEvent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcomingEvent.java index 4371fc17da9..545adb2cd6b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcomingEvent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/eventsupcoming/EventsOverviewUpcomingEvent.java @@ -11,12 +11,12 @@ import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.DateUtil; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; public class EventsOverviewUpcomingEvent extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.java index b67526183f9..64f75954d2a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.java @@ -24,10 +24,10 @@ import com.sap.sailing.gwt.common.client.i18n.TextMessages; import com.sap.sailing.gwt.home.client.place.event.legacy.EventPlace; import com.sap.sailing.gwt.home.client.place.event.legacy.RegattaPlace; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace.SolutionsNavigationTabs; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; @@ -78,7 +78,7 @@ public class Header extends Composite { homeNavigation = navigator.getHomeNavigation(); eventsNavigation = navigator.getEventsNavigation(); - solutionsNavigation = navigator.getSolutionsNavigation(SolutionsNavigationTabs.SailingAnalytics); + solutionsNavigation = navigator.getSolutionsNavigation(SolutionsNavigationTabs.SapInSailing); startPageLink.setHref(homeNavigation.getTargetUrl()); eventsPageLink.setHref(eventsNavigation.getTargetUrl()); @@ -132,6 +132,8 @@ public class Header extends Composite { setActiveLink(startPageLink); } else if(place instanceof SolutionsPlace) { setActiveLink(solutionsPageLink); + } else { + setActiveLink(null); } // TODO add more rules } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.ui.xml old mode 100644 new mode 100755 index 6500c9f8cb7..6159afa5045 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/header/Header.ui.xml @@ -2,17 +2,18 @@ - - + + +
@@ -21,8 +22,10 @@ styleName="{local_res.css.sitenavigation_link}" text="{i18n.home}" /> - + + -
-
-
-
- - - -
-
-
-
-
- + +
+
+
+
+ + + +
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.java index 9df6a400d5d..3aad9fbbf2f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.java @@ -1,84 +1,50 @@ package com.sap.sailing.gwt.home.desktop.partials.searchresult; 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.Element; import com.google.gwt.dom.client.SpanElement; -import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; -import com.google.gwt.uibinder.client.UiHandler; -import com.google.gwt.user.client.Event; -import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.impl.HyperlinkImpl; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegattaPlace; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.EventBaseDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; +import com.sap.sailing.gwt.home.shared.partials.searchresult.AbstractSearchResultItem; -public class SearchResultItem extends Composite { - interface SearchResultUiBinder extends UiBinder { +public class SearchResultItem extends AbstractSearchResultItem { + + private static SearchResultItemUiBinder uiBinder = GWT.create(SearchResultItemUiBinder.class); + + interface SearchResultItemUiBinder extends UiBinder { } - private static SearchResultUiBinder uiBinder = GWT.create(SearchResultUiBinder.class); - - private static final HyperlinkImpl HYPERLINK_IMPL = GWT.create(HyperlinkImpl.class); - - @UiField Anchor regattaLink; - @UiField SpanElement resultRegattaDetails; - @UiField SpanElement resultEventDate; - @UiField SpanElement resultEventVenue; - @UiField Anchor eventOverviewLink; + @UiField AnchorElement resultTitleUi; + @UiField SpanElement resultDescriptionUi; + @UiField DivElement eventInfoContainerUi; + private final DesktopPlacesNavigator navigator; + private final SearchResultDTO item; - private final DesktopPlacesNavigator placeNavigator; - private final PlaceNavigation regattaNavigation; - private final PlaceNavigation eventNavigation; - - public SearchResultItem(DesktopPlacesNavigator navigator, LeaderboardSearchResultDTO searchResult) { - this.placeNavigator = navigator; - - SearchResultResources.INSTANCE.css().ensureInjected(); - initWidget(uiBinder.createAndBindUi(this)); - - EventBaseDTO event = searchResult.getEvent(); - regattaNavigation = placeNavigator.getRegattaNavigation(event.id.toString(), searchResult.getLeaderboardName(), searchResult.getBaseURL(), searchResult.isOnRemoteServer()); - eventNavigation = placeNavigator.getEventNavigation(event.id.toString(), searchResult.getBaseURL(), searchResult.isOnRemoteServer()); - - String headlineLink = searchResult.getLeaderboardDisplayName(); - if(headlineLink == null) { - headlineLink = searchResult.getRegattaName() != null ? searchResult.getRegattaName() : searchResult.getLeaderboardName(); - } - - regattaLink.setHref(regattaNavigation.getTargetUrl()); - regattaLink.setText(headlineLink); -// resultRegattaDetails.setInnerText("I have no idea yet what to show here..."); - eventOverviewLink.setHref(eventNavigation.getTargetUrl()); - eventOverviewLink.setText(searchResult.getEvent().getName()); - resultEventVenue.setInnerText(searchResult.getEvent().venue.getName()); - if(searchResult.getEvent().startDate != null) { - resultEventDate.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(searchResult.getEvent().startDate, searchResult.getEvent().endDate)); - } else { - resultEventDate.setInnerText("Unknown date"); - } + SearchResultItem(DesktopPlacesNavigator navigator, SearchResultDTO item) { + this.navigator = navigator; + this.item = item; + init(uiBinder.createAndBindUi(this), item); + SearchResultEventInfoDTO event = item.getEvents().iterator().next(); + String eventId = String.valueOf(event.getId()), leaderboardName = item.getLeaderboardName(), baseUrl = item.getBaseUrl(); + PlaceNavigation regattaNavigation = navigator.getRegattaNavigation(eventId, leaderboardName, baseUrl, item.isOnRemoteServer()); + regattaNavigation.configureAnchorElement(resultTitleUi); } - @UiHandler("regattaLink") - public void goToRegatta(ClickEvent e) { - handleClickEvent(e, regattaNavigation); - } - - @UiHandler("eventOverviewLink") - public void goToEventPlace(ClickEvent e) { - handleClickEvent(e, eventNavigation); + @Override + protected Element getResultTitleUi() { + return resultTitleUi; } - private void handleClickEvent(ClickEvent e, PlaceNavigation placeNavigation) { - if (HYPERLINK_IMPL.handleAsClick((Event) e.getNativeEvent())) { - placeNavigator.goToPlace(placeNavigation); - e.preventDefault(); - } + @Override + protected void addEventInfo(SearchResultEventInfoDTO event) { + eventInfoContainerUi.appendChild(new SearchResultItemEventInfo( + navigator, event, item.getBaseUrl(), item.isOnRemoteServer()).getElement()); } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.ui.xml index aff81165b66..073a673bac1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItem.ui.xml @@ -3,17 +3,10 @@ - -
- -
- -
-
- - | - | -
-
-
+ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.java new file mode 100644 index 00000000000..d407c13569c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.java @@ -0,0 +1,47 @@ +package com.sap.sailing.gwt.home.desktop.partials.searchresult; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.AnchorElement; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.SpanElement; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; +import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; +import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.partials.searchresult.AbstractSearchResultItemEventInfo; + +public class SearchResultItemEventInfo extends AbstractSearchResultItemEventInfo { + + private static SearchResultItemEventInfoUiBinder uiBinder = GWT.create(SearchResultItemEventInfoUiBinder.class); + + interface SearchResultItemEventInfoUiBinder extends UiBinder { + } + + @UiField AnchorElement eventNameUi; + @UiField SpanElement eventVenueUi; + @UiField SpanElement eventDateUi; + + SearchResultItemEventInfo(DesktopPlacesNavigator navigator, SearchResultEventInfoDTO event, String baseUrl, + boolean isOnRemoteServer) { + init(uiBinder.createAndBindUi(this), event); + String eventId = String.valueOf(event.getId()); + PlaceNavigation eventNavigation = navigator.getEventNavigation(eventId, baseUrl, isOnRemoteServer); + eventNavigation.configureAnchorElement(eventNameUi); + } + + @Override + protected Element getEventNameUi() { + return eventNameUi; + } + + @Override + protected Element getEventVenueUi() { + return eventVenueUi; + } + + @Override + protected Element getEventDateUi() { + return eventDateUi; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.ui.xml new file mode 100644 index 00000000000..26fc1509d0a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/searchresult/SearchResultItemEventInfo.ui.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/seriesheader/SeriesHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/seriesheader/SeriesHeader.java index 32cc3d65e6f..5bc96ce0841 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/seriesheader/SeriesHeader.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/seriesheader/SeriesHeader.java @@ -14,6 +14,9 @@ import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingButtons; import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingMetadataProvider; import com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesView; @@ -22,9 +25,6 @@ import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; public class SeriesHeader extends Composite { private static SeriesHeaderUiBinder uiBinder = GWT.create(SeriesHeaderUiBinder.class); @@ -45,7 +45,7 @@ public class SeriesHeader extends Composite { boolean dropdownShown = false; public SeriesHeader(SeriesView.Presenter presenter) { - this.series = presenter.getCtx().getSeriesDTO(); + this.series = presenter.getSeriesDTO(); this.presenter = presenter; SeriesHeaderResources.INSTANCE.css().ensureInjected(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.gss index fb8706bac91..295b5ab6974 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.gss @@ -1,53 +1,56 @@ +/** + * The solutions page + */ .solutions { - font-size: 15px; - /* @alternate */ font-size: 1rem; - padding-top: 3.4em; + font-size: 1rem; } .solutions_nav { - position: absolute; - top: 4.666666666666667em; - right: 0; - left: 0; - border-bottom: 1px solid #ddd; + padding-top: 1.333333333333333em; + border-bottom: 1px solid #f2f2f2; background: #fff; z-index: 10; text-align: center; } -.solutions_navsticky { - position: fixed; - top: 0; -} .solutions_nav_link { display: inline-block; padding: 1em 0 0.733333333333333em 0; - border-bottom: 0.266666666666667em solid transparent; font-weight: 600; - color: #333; + color: #666; -webkit-transition: 0.2s border ease; - -moz-transition: 0.2s border ease; - -o-transition: 0.2s border ease; - -ms-transition: 0.2s border ease; - transition: 0.2s border ease; + -moz-transition: 0.2s border ease; + transition: 0.2s border ease; margin-right: 1em; + border-bottom: 4px solid transparent; + margin-bottom: -1px } .solutions_nav_link:hover, -.solutions_nav_link:focus, -.solutions_nav_linkactive { - border-bottom-color: #f0ab00; +.solutions_nav_linkactive, +.solutions_nav_link:focus { text-decoration: none; - color: #666; + color: #666; + border-bottom-color: #efaa00; } .solutions_nav_link:last-child { margin-right: 0; } +@media (min-width: 45em) { + .solutions_nav_link { + margin-right: 1em; + } +} +@media (min-width: 61em) { + .solutions_nav_link { + margin-right: 2em; + } +} .solutions_content { position: relative; z-index: 2; } -.solutions_content:nth-child(odd) { +.solutions_content:nth-child(even) { background-color: #f8f8f8; } -.solutions_content:nth-child(even) { +.solutions_content:nth-child(odd) { background-color: #fff; } .solutions_content .parallax { @@ -62,70 +65,142 @@ height: 100%; padding: 3.333333333333333em 0; } -.solutions_contentsap { - max-width: 88em; - margin: auto; - background-repeat: no-repeat; - background-position: center center; - -webkit-background-size: 100%; - -moz-background-size: 100%; - background-size: 100%; - background-image: url("images/home/solutions-sap.png"); +.solutions_content:first-child .gridalternator { + padding: 0.333333333333333em 0 3.333333333333333em; } -.solutions_contentsap .gridalternator { +@media (min-width: 45em) { + .solutions_content .gridalternator { + padding: 5em 0; + } + .solutions_content:first-child .gridalternator { + padding: 0.666666666666667em 0 5em; + } +} +@media (min-width: 61em) { + .solutions_content .gridalternator { + padding: 6.666666666666667em 0; + } + .solutions_content:first-child .gridalternator { + padding: 2em 0 6.666666666666667em; + } +} +.solutions_contentsapinsailing { + width: 100%; + font-size: 1rem; +} +.solutions_contentsapinsailing_body { + margin: auto; + padding-right: 50%; + max-width: 88em; + background-repeat: no-repeat; + background-position: right center; + background-size: 40%; + background-image: url("images/home/solutions-sap-in-sailing.jpg"); +} +.solutions_contentsapinsailing_body .gridalternator { padding: 4em 0 4.333333333333333em; } -.solutions_contentrace { - font-size: 15px; - /* @alternate */ font-size: 1rem; +@media (min-width: 45em) { + .solutions_contentsapinsailing_body .gridalternator { + padding: 5em 0 5.666666666666667em; + } } -.solutions_contentrace .gridalternator { - padding: 2.666666666666667em 0 10%; +@media (min-width: 61em) { + .solutions_contentsapinsailing_body .gridalternator { + padding: 6.666666666666667em 0 12em; + } } -.solutions_contentrace .parallax { - font-size: 15px; - /* @alternate */ font-size: 1rem; +.solutions_contentsap { + font-size: 1rem; + width: 100%; } -.solutions_contentrace .parallax .background { +.solutions_contentsap .gridalternator { margin: auto; - height: 100%; + background-repeat: no-repeat; + background-position: left center; + background-size: 100%; + background-image: url("images/home/solutions-sap.png"); + padding: 4em 0 4.333333333333333em; +} +@media (min-width: 45em) { + .solutions_contentsap .gridalternator { + padding: 5em 0 5.666666666666667em; + } +} +@media (min-width: 61em) { + .solutions_contentsap .gridalternator { + padding: 6.666666666666667em 0 12em; + } +} +.solutions_contentsapsailingracemanager { + width: 100%; +} +.solutions_contentsapsailingracemanager_body { + margin: auto; + padding: 4em 50% 4.333333333333333em 0; max-width: 88em; background-repeat: no-repeat; - background-image: url("images/home/solutions-race.png"); - -webkit-background-size: 100% auto; - -moz-background-size: 100% auto; - background-size: 100% auto; - background-position: center 20em; + background-image: url("images/home/solutions-sap-sailing-race-manager.png"); + background-size: 40%; + background-position: center right; } -.solutions_contentrace .parallax.noparallax .background { - margin-left: 40px; - margin-right: -80px; - margin-top: 110px; - background-position: center bottom; +@media (min-width: 45em) { + .solutions_contentsapsailingracemanager_body .gridalternator { + padding: 5em 0 5.666666666666667em; + } +} +@media (min-width: 61em) { + .solutions_contentsapsailingracemanager_body .gridalternator { + padding: 6.666666666666667em 0 12em; + } } .solutions_contentpost { - font-size: 15px; - /* @alternate */ font-size: 1rem; + font-size: 1rem; } .solutions_contentpost .gridalternator { background-repeat: no-repeat; background-image: url("images/home/solutions-post.png"); background-position: left center; - -webkit-background-size: 100%; - -moz-background-size: 100%; background-size: 100%; padding: 1.666666666666667em 0; } -.solutions_contenttraining { - font-size: 15px; - /* @alternate */ font-size: 1rem; +@media (min-width: 45em) { + .solutions_contentpost .gridalternator { + padding: 3.333333333333333em 0; + } } -.solutions_contenttraining .gridalternator { +@media (min-width: 61em) { + .solutions_contentpost .gridalternator { + padding: 5em 0; + } +} +.solutions_contenttraining { + font-size: 1rem; +} +.solutions_contenttraining_body { + margin: auto; + padding: 4em 50% 4.333333333333333em 0; + max-width: 88em; + background-repeat: no-repeat; + background-image: url("images/home/solutions-training.png"); + background-size: 45%; + background-position: center right; +} +.solutions_contenttraining_body .gridalternator { padding-top: 5em; } +@media (min-width: 45em) { + .solutions_contenttraining_body .gridalternator { + padding-top: 6.666666666666667em; + } +} +@media (min-width: 61em) { + .solutions_contenttraining_body .gridalternator { + padding-top: 8.333333333333334em; + } +} .solutions_contenttraining .parallax { - font-size: 15px; - /* @alternate */ font-size: 1rem; + font-size: 1rem; } .solutions_contenttraining .parallax .background { margin: auto; @@ -133,8 +208,6 @@ max-width: 80em; background-repeat: no-repeat; background-image: url("images/home/solutions-training.png"); - -webkit-background-size: 100% auto; - -moz-background-size: 100% auto; background-size: 100% auto; background-position: center 13.333333333333334em; } @@ -142,72 +215,26 @@ background-position: center 6.666666666666667em; } .solutions_contentsimulator { - font-size: 15px; - /* @alternate */ font-size: 1rem; + font-size: 1rem; } .solutions_contentsimulator .gridalternator { background-repeat: no-repeat; background-image: url("images/home/solutions-simulator.png"); background-position: left center; - -webkit-background-size: 100%; - -moz-background-size: 100%; background-size: 100%; padding: 3.333333333333333em 0 3.333333333333333em; } +@media (min-width: 45em) { + .solutions_contentsimulator .gridalternator { + padding: 5em 0 6.666666666666667em; + } +} +@media (min-width: 61em) { + .solutions_contentsimulator .gridalternator { + padding: 6.666666666666667em 0 13.333333333333334em; + } +} .solutions_content_linkappstore { display: inline-block; margin-top: 2.666666666666667em; } - -@media (min-width: 25em) { - .solutions_nav_link { - margin-right: 1em; - } - .solutions_content .gridalternator { - padding: 5em 0; - } - .solutions_contentsap .gridalternator { - padding: 5em 0 5.666666666666667em; - } - .solutions_contentrace .gridalternator { - padding: 4em 0 15%; - } - .solutions_contentrace .parallax .background { - background-position: center 16.666666666666668em; - } - .solutions_contentpost .gridalternator { - padding: 3.333333333333333em 0; - } - .solutions_contenttraining .gridalternator { - padding-top: 6.666666666666667em; - } - .solutions_contentsimulator .gridalternator { - padding: 5em 0 6.666666666666667em; - } -} -@media (min-width: 50em) { - .solutions_nav_link { - margin-right: 2em; - } - .solutions_content .gridalternator { - padding: 6.666666666666667em 0; - } - .solutions_contentsap .gridalternator { - padding: 6.666666666666667em 0 12em; - } - .solutions_contentrace .gridalternator { - padding: 4em 0 20%; - } - .solutions_contentrace .parallax .background { - background-position: center 13.333333333333334em; - } - .solutions_contentpost .gridalternator { - padding: 5em 0; - } - .solutions_contenttraining .gridalternator { - padding-top: 8.333333333333334em; - } - .solutions_contentsimulator .gridalternator { - padding: 6.666666666666667em 0 13.333333333333334em; - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.java index 753ec251fd5..f6da9b6a6d6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.java @@ -10,7 +10,6 @@ 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; @@ -36,17 +35,20 @@ public class Solutions extends Composite { @UiField Anchor trainingDiaryAnchor; @UiField Anchor simulatorAnchor; + @UiField DivElement sapInSailingDiv; @UiField DivElement sailingAnalyticsDiv; @UiField DivElement raceDiv; @UiField DivElement postRaceDiv; @UiField DivElement trainingDiaryDiv; @UiField DivElement simulatorDiv; + @UiField + Anchor sapInSailingAnchor; @UiField Anchor sailingAnalyticsDetailsAnchor; @UiField Anchor raceCommitteeAppDetailsAnchor; - @UiField Anchor simulatorStartAnchor; @UiField Anchor simulatorAppDetailsAnchor; + private final PlaceNavigation sapInSailingNavigation; private final PlaceNavigation sailingAnalyticsNavigation; private final PlaceNavigation raceCommitteeAppNavigation; private final PlaceNavigation postRaceAnalyticsNavigation; @@ -75,14 +77,15 @@ public class Solutions extends Composite { sailingAnalyticsDetailsAnchor.setHref(sailingAnalyticsDetailsNavigation.getTargetUrl()); raceCommitteeAppDetailsAnchor.setHref(raceCommitteeAppDetailsNavigation.getTargetUrl()); simulatorAppDetailsAnchor.setHref(simulatorAppDetailsNavigation.getTargetUrl()); - simulatorStartAnchor.setHref(placesNavigator.getSimulatorURL()); + sapInSailingNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.SapInSailing); sailingAnalyticsNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.SailingAnalytics); - raceCommitteeAppNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.RaceCommiteeApp); + raceCommitteeAppNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.RaceCommitteeApp); postRaceAnalyticsNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.PostRaceAnalytics); trainingDiaryNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.TrainingDiary); sailingSimulatorNavigation = placesNavigator.getSolutionsNavigation(SolutionsNavigationTabs.SailingSimulator); + sapInSailingAnchor.setHref(sapInSailingNavigation.getTargetUrl()); sailingAnalyticsAnchor.setHref(sailingAnalyticsNavigation.getTargetUrl()); raceAnchor.setHref(raceCommitteeAppNavigation.getTargetUrl()); postRaceAnchor.setHref(postRaceAnalyticsNavigation.getTargetUrl()); @@ -99,6 +102,11 @@ public class Solutions extends Composite { }); } + @UiHandler("sapInSailingAnchor") + public void scrollTosapInSailingAnchor(ClickEvent e) { + scrollToView(SolutionsNavigationTabs.SapInSailing); + handleClickEventWithLocalNavigation(e, sapInSailingNavigation); + } @UiHandler("sailingAnalyticsAnchor") public void scrollToSailingAnalytics(ClickEvent e) { scrollToView(SolutionsNavigationTabs.SailingAnalytics); @@ -107,7 +115,7 @@ public class Solutions extends Composite { @UiHandler("raceAnchor") public void scrollToRace(ClickEvent e) { - scrollToView(SolutionsNavigationTabs.RaceCommiteeApp); + scrollToView(SolutionsNavigationTabs.RaceCommitteeApp); handleClickEventWithLocalNavigation(e, raceCommitteeAppNavigation); } @@ -140,11 +148,17 @@ public class Solutions extends Composite { } private void scrollToView(SolutionsNavigationTabs navigationTab) { - switch (navigationTab) { - case SailingAnalytics: - Window.scrollTo(0, 0); + if (navigationTab == null) { + sapInSailingDiv.scrollIntoView(); + } else { + switch (navigationTab) { + case SapInSailing: + sapInSailingDiv.scrollIntoView(); break; - case RaceCommiteeApp: + case SailingAnalytics: + sailingAnalyticsDiv.scrollIntoView(); + break; + case RaceCommitteeApp: raceDiv.scrollIntoView(); break; case PostRaceAnalytics: @@ -156,6 +170,7 @@ public class Solutions extends Composite { case SailingSimulator: simulatorDiv.scrollIntoView(); break; + } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.ui.xml index bf08a1f9a8e..0205115537d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/Solutions.ui.xml @@ -1,77 +1,191 @@ - - - - - - + + + + + +
-
-
-
- - - - - -
-
-
-
-
-
-

-

-

- -
-
-
-
-
-
-
-
-
-

-

- -
-
-
-
-
-
-

-

-
-
-
-
-
-
-
-

-

- -    - -
-
-
+
+
+
+ + + + + + + + + + + + + + + + + + +
+
+
+ + +
+
+
+
+
+

+ +

+

+ +

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+

+ +

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+
+
+
+
+

+ +

+

+ +

+

+ +

+ + + +
+
+
+
+
+
+
+

+ +

+

+ +

+ + + +
+
+
+
+
+
+
+

+ +

+

+ +

+

+ +

+
+
+
+
+
+
+
+

+ +

+

+ +

+ + + +
+
+
+
+
+
+
+

+ +

+

+ +

+ + + +
+
+
+
-
+ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/SolutionsResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/SolutionsResources.java index 95edb2c85a8..c181cf09303 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/SolutionsResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/solutions/SolutionsResources.java @@ -15,18 +15,21 @@ public interface SolutionsResources extends ClientBundle { public interface LocalCss extends CssResource { String solutions(); String solutions_nav(); - String solutions_navsticky(); String solutions_nav_link(); String solutions_nav_linkactive(); String solutions_content(); String parallax(); String gridalternator(); + String solutions_contentsapinsailing(); + String solutions_contentsapinsailing_body(); String solutions_contentsap(); - String solutions_contentrace(); - String background(); - String noparallax(); + String solutions_contentsapsailingracemanager(); + String solutions_contentsapsailingracemanager_body(); String solutions_contentpost(); String solutions_contenttraining(); + String solutions_contenttraining_body(); + String background(); + String noparallax(); String solutions_contentsimulator(); String solutions_content_linkappstore(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveEventStageTeaser.java index 5cf48ddd054..bb191e5e81a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; public class LiveEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveStageTeaserBand.java index 8d2f764bee2..f04c3689390 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/LiveStageTeaserBand.java @@ -3,9 +3,9 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; /** * Teaser band for a live event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/NoActionStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/NoActionStageTeaserBand.java index 5887aa68c53..6ea4a4f8d0f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/NoActionStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/NoActionStageTeaserBand.java @@ -1,8 +1,8 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; /** * Teaser band with no action on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaser.java index 8baf3bfa9b3..e1db6c9a2b2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; public class PopularEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaserBand.java index bba37564801..0e334dc9788 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/PopularEventStageTeaserBand.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; /** * Teaser band for a popular but finished event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/Stage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/Stage.java index 098bafb2adb..5afb6c77f0a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/Stage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/Stage.java @@ -8,8 +8,8 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; import com.sap.sse.gwt.client.controls.carousel.WidgetCarousel; public class Stage extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaser.java index f0a2512234e..cf93a4c1b02 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaser.java @@ -12,8 +12,8 @@ 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.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.client.controls.carousel.LazyLoadable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaserBand.java index a7ad3a080c9..dfed9e1cb4e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/StageTeaserBand.java @@ -11,11 +11,11 @@ import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.app.PlaceNavigator; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; public abstract class StageTeaserBand extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaser.java index cd88647417e..d51b4cf80e7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; public class UpcomingEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaserBand.java index 713bf7d5078..a7e62e59e5b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/stage/UpcomingEventStageTeaserBand.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.desktop.partials.stage; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; /** * Teaser band for an upcoming event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsList.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsList.java index ac300ee1d94..280d0970f5e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsList.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsList.java @@ -10,14 +10,14 @@ 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.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.LabelType; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderboardDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.MiniLeaderboardItemDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderboardDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.MiniLeaderboardItemDTO; -import com.sap.sailing.gwt.ui.shared.general.LabelType; public class StandingsList extends Widget implements RefreshableWidget { interface MyUiBinder extends UiBinder { @@ -31,6 +31,7 @@ public class StandingsList extends Widget implements RefreshableWidget headerNavigation) { @@ -53,7 +54,11 @@ public class StandingsList extends Widget implements RefreshableWidget
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsListCompetitor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsListCompetitor.java index d4ca9738290..57bcbbfa744 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsListCompetitor.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/standings/StandingsListCompetitor.java @@ -9,10 +9,10 @@ import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.MiniLeaderboardItemDTO; import com.sap.sailing.gwt.ui.client.FlagImageResolver; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.MiniLeaderboardItemDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.SimpleCompetitorDTO; public class StandingsListCompetitor extends UIObject { private static final StringMessages i18n = StringMessages.INSTANCE; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/statistics/StatisticsBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/statistics/StatisticsBox.java index 73fe7d4cd9f..ec03a5ca934 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/statistics/StatisticsBox.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/statistics/StatisticsBox.java @@ -5,8 +5,8 @@ import com.google.gwt.dom.client.UListElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.statistics.EventStatisticsDTO; import com.sap.sailing.gwt.home.shared.partials.statistics.AbstractStatisticsBox; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventStatisticsDTO; public class StatisticsBox extends AbstractStatisticsBox { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBox.java index 2f2d5c5ec2c..a9fcc667018 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBox.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBox.java @@ -10,9 +10,9 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.desktop.places.event.EventView; import com.sap.sailing.gwt.home.desktop.places.event.EventView.Presenter; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public class UpdatesBox extends Composite { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBoxItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBoxItem.java index cfb9256a223..132510bd584 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBoxItem.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/updates/UpdatesBoxItem.java @@ -15,12 +15,12 @@ import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.BoatClassImageResolver; import com.sap.sailing.gwt.common.client.LinkUtil; +import com.sap.sailing.gwt.home.communication.event.news.AbstractRaceNewsEntryDTO; +import com.sap.sailing.gwt.home.communication.event.news.LeaderboardNewsEntryDTO; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.desktop.places.event.EventView; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.news.AbstractRaceNewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.news.LeaderboardNewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; import com.sap.sailing.gwt.ui.shared.util.ConditionalDateTimeFormatter; public class UpdatesBoxItem extends Widget { @@ -76,7 +76,8 @@ public class UpdatesBoxItem extends Widget { } else if(entry instanceof AbstractRaceNewsEntryDTO) { AbstractRaceNewsEntryDTO raceEntry = (AbstractRaceNewsEntryDTO) entry; if(raceEntry.getRegattaAndRaceIdentfier() != null) { - directLink = presenter.getRaceViewerURL(raceEntry.getLeaderboardName(), raceEntry.getRegattaAndRaceIdentfier()); + directLink = presenter.getRaceViewerURL(raceEntry.getLeaderboardName(), raceEntry.getLeaderboardGroupName(), + raceEntry.getRegattaAndRaceIdentfier()); } } if(placeNavigation != null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivity.java index 52d1b9722fb..761bdff691b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivity.java @@ -1,47 +1,25 @@ package com.sap.sailing.gwt.home.desktop.places.error; -import com.google.gwt.activity.shared.AbstractActivity; -import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.shared.places.error.AbstractErrorActivity; +import com.sap.sailing.gwt.home.shared.places.error.ErrorClientFactory; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; +import com.sap.sse.gwt.client.mvp.ErrorView; -public class ErrorActivity extends AbstractActivity { - - private ErrorPlace currentPlace; - private ErrorClientFactory clientFactory; +public class ErrorActivity extends AbstractErrorActivity { public ErrorActivity(ErrorPlace place, ErrorClientFactory clientFactory) { - this.currentPlace = place; - this.clientFactory = clientFactory; + super(place, clientFactory.getPlaceController()); + } + + @Override + protected ErrorView createView(String errorMsg, Throwable reason, Command reloadCommand) { + return new TabletAndDesktopErrorView(errorMsg, reason, reloadCommand); } @Override - public void start(AcceptsOneWidget panel, EventBus eventBus) { - // TODO: the error place should get the error message from the place - final TabletAndDesktopErrorView view; - - Command reloadCommand = null; - if (currentPlace.getComingFrom() != null) { - reloadCommand = new Command() { - - @Override - public void execute() { - clientFactory.getPlaceController().goTo(currentPlace.getComingFrom()); - } - }; - } - - if (currentPlace.hasCustomErrorMessages()) { - view = new TabletAndDesktopErrorView( - currentPlace.getErrorMessage(), - currentPlace.getErrorMessageDetail(), - currentPlace.getException(), reloadCommand); - } else { - view = new TabletAndDesktopErrorView(currentPlace.getErrorMessageDetail(), currentPlace.getException(), - reloadCommand); - } - - panel.setWidget(view); + protected ErrorView createView(String customMsg, String errorMsg, Throwable reason, Command reloadCommand) { + return new TabletAndDesktopErrorView(customMsg, errorMsg, reason, reloadCommand); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivityProxy.java index 1a5781bd363..1c2f0ff163f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorActivityProxy.java @@ -1,12 +1,14 @@ package com.sap.sailing.gwt.home.desktop.places.error; import com.google.gwt.core.client.GWT; +import com.sap.sailing.gwt.home.shared.places.error.ErrorClientFactory; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; public class ErrorActivityProxy extends AbstractActivityProxy { - private final ErrorClientFactory clientFactory; private final ErrorPlace place; + private final ErrorClientFactory clientFactory; public ErrorActivityProxy(ErrorPlace place, ErrorClientFactory clientFactory) { this.place = place; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorClientFactory.java deleted file mode 100644 index f725ceb7256..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorClientFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.error; - -import com.sap.sailing.gwt.ui.client.SailingClientFactory; - -public interface ErrorClientFactory extends SailingClientFactory { - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.java index c2fa5cd24dc..4bce86d8048 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.java @@ -6,7 +6,7 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.home.desktop.partials.error.ErrorMessage; +import com.sap.sailing.gwt.home.shared.partials.error.ErrorMessage; import com.sap.sse.gwt.client.mvp.ErrorView; public class TabletAndDesktopErrorView extends Composite implements ErrorView { @@ -15,16 +15,19 @@ public class TabletAndDesktopErrorView extends Composite implements ErrorView { interface ErrorViewUiBinder extends UiBinder { } - @UiField(provided=true) ErrorMessage errorMessage; + @UiField(provided=true) ErrorMessage errorMessageUi; public TabletAndDesktopErrorView(String errorMessageTextDetail, Throwable errorReason, Command reloadCommand) { - errorMessage = new ErrorMessage(errorMessageTextDetail, errorReason, reloadCommand); - initWidget(uiBinder.createAndBindUi(this)); + this(new ErrorMessage(errorMessageTextDetail, errorReason, reloadCommand)); } public TabletAndDesktopErrorView(String customMessageText, String errorMessageTextDetail, Throwable errorReason, Command reloadCommand) { - errorMessage = new ErrorMessage(customMessageText, errorMessageTextDetail, errorReason, reloadCommand); + this(new ErrorMessage(customMessageText, errorMessageTextDetail, errorReason, reloadCommand)); + } + + private TabletAndDesktopErrorView(ErrorMessage errorMessage) { + errorMessageUi = errorMessage; initWidget(uiBinder.createAndBindUi(this)); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.ui.xml index a075765bfcf..1a962e00a5f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/TabletAndDesktopErrorView.ui.xml @@ -1,8 +1,10 @@ + xmlns:sp="urn:import:com.sap.sailing.gwt.home.shared.partials"> - - + +
+ +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/AbstractEventActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/AbstractEventActivity.java index 8cef89c7f21..dcaa97c38eb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/AbstractEventActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/AbstractEventActivity.java @@ -10,8 +10,15 @@ import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.safehtml.shared.UriUtils; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata; +import com.sap.sailing.gwt.home.communication.media.GetMediaForEventAction; +import com.sap.sailing.gwt.home.communication.media.MediaDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegattaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.leaderboardtab.RegattaLeaderboardPlace; @@ -19,7 +26,6 @@ import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.Regatta import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.event.EventContext; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; @@ -27,15 +33,9 @@ import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; -import com.sap.sailing.gwt.ui.client.HomeServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata.RegattaState; -import com.sap.sailing.gwt.ui.shared.general.EventState; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; -import com.sap.sse.gwt.client.mvp.ErrorView; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; @@ -54,25 +54,29 @@ public abstract class AbstractEventActivity ex private static final ApplicationHistoryMapper historyMapper = GWT.create(ApplicationHistoryMapper.class); - public AbstractEventActivity(PLACE place, EventClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { + protected final EventViewDTO eventDTO; + + public AbstractEventActivity(PLACE place, EventViewDTO eventDTO, EventClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { this.currentPlace = place; + this.eventDTO = eventDTO; this.homePlacesNavigator = homePlacesNavigator; this.ctx = new EventContext(place.getCtx()); this.timerForClientServerOffset = new Timer(PlayModes.Replay); this.clientFactory = clientFactory; } - public HomeServiceAsync getHomeService() { - return clientFactory.getHomeService(); - } - public SailingServiceAsync getSailingService() { return clientFactory.getSailingService(); } - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return clientFactory.getDispatch(); } + + @Override + public ErrorAndBusyClientFactory getErrorAndBusyClientFactory() { + return clientFactory; + } @Override public EventContext getCtx() { @@ -97,7 +101,7 @@ public abstract class AbstractEventActivity ex @Override public HasRegattaMetadata getRegattaMetadata() { - return ctx.getRegatta(); + return null; } @Override @@ -122,23 +126,27 @@ public abstract class AbstractEventActivity ex protected EventContext contextForRegatta(String regattaId) { return new EventContext(ctx).withRegattaId(regattaId).withRegattaAnalyticsManager(null); } - + @Override - public String getRaceViewerURL(StrippedLeaderboardDTO leaderboard, RaceDTO race) { - RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(); - return getRaceViewerURL(leaderboard.name, raceIdentifier); + public String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata) { + return getRaceViewerURL(raceMetadata.getLeaderboardName(), raceMetadata.getLeaderboardGroupName(), + raceMetadata.getRegattaAndRaceIdentifier()); } - public String getRaceViewerURL(String leaderboardName, RegattaAndRaceIdentifier raceIdentifier) { - return EntryPointLinkFactory - .createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName, raceIdentifier.getRegattaName(), raceIdentifier.getRaceName())); + @Override + public String getRaceViewerURL(String leaderboardName, String leaderboardGroupName, RegattaAndRaceIdentifier raceIdentifier) { + return EntryPointLinkFactory.createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName, + leaderboardGroupName, raceIdentifier.getRegattaName(), raceIdentifier.getRaceName())); } - private Map createRaceBoardLinkParameters(String leaderboardName, + private Map createRaceBoardLinkParameters(String leaderboardName, String leaderboardGroupName, String regattaName, String trackedRaceName) { Map linkParams = new HashMap(); linkParams.put("eventId", ctx.getEventId()); linkParams.put("leaderboardName", leaderboardName); + if (leaderboardGroupName != null) { + linkParams.put("leaderboardGroupName", leaderboardGroupName); + } linkParams.put("raceName", trackedRaceName); // TODO this must only be forwarded if there is a logged-on user // linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true"); @@ -185,27 +193,7 @@ public abstract class AbstractEventActivity ex @Override public void ensureMedia(final AsyncCallback callback) { - if (ctx.getMedia() != null) { - callback.onSuccess(ctx.getMedia()); - return; - } - - getHomeService().getMediaForEvent(ctx.getEventDTO().getId(), new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract error message - ErrorView errorView = clientFactory.createErrorView("Load media failure for event", caught); - getView().showErrorInCurrentTab(errorView); - // TODO: notify callback of failure? - // callback.onFailure(caught); - } - - @Override - public void onSuccess(MediaDTO result) { - ctx.withMedia(result); - callback.onSuccess(result); - } - }); + getDispatch().execute(new GetMediaForEventAction(eventDTO.getId()), callback); } @Override @@ -213,13 +201,13 @@ public abstract class AbstractEventActivity ex if (showRegattaMetadata()) { return false; } - return ctx.getEventDTO().isHasMedia(); + return eventDTO.isHasMedia(); } @Override public String getRegattaOverviewLink() { String url = "RegattaOverview.html?ignoreLocalSettings=true&onlyrunningraces=false&event=" + getCtx().getEventId(); - url += "&onlyracesofsameday=" + getCtx().getEventDTO().isRunning(); + url += "&onlyracesofsameday=" + eventDTO.isRunning(); if(showRegattaMetadata()) { if(getRegattaMetadata().isFlexibleLeaderboard()) { String defaultCourseAreaId = getRegattaMetadata().getDefaultCourseAreaId(); @@ -227,7 +215,7 @@ public abstract class AbstractEventActivity ex url += "&coursearea=" + defaultCourseAreaId; } } else { - url += "®atta=" + getCtx().getRegattaId(); + url += "®atta=" + getRegattaId(); } } return url; @@ -235,12 +223,23 @@ public abstract class AbstractEventActivity ex @Override public boolean isEventOrRegattaLive() { - if(showRegattaMetadata()) { - if(ctx.getRegatta().getState() == RegattaState.RUNNING) { - return true; - } + return eventDTO.getState() == EventState.RUNNING; + } + + public String getRegattaId() { + String regattaId = currentPlace.getRegattaId(); + if(regattaId != null) { + return regattaId; } - return ctx.getEventDTO().getState() == EventState.RUNNING; + if(!eventDTO.getRegattas().isEmpty() && (eventDTO.getType() == EventType.SINGLE_REGATTA || eventDTO.getType() == EventType.SERIES_EVENT)) { + return eventDTO.getRegattas().iterator().next().getId(); + } + return null; + } + + @Override + public EventViewDTO getEventDTO() { + return eventDTO; } protected abstract EventView getView(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventActivityProxy.java index ec44d7f3b1f..7c76f0b6dd2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventActivityProxy.java @@ -1,152 +1,66 @@ package com.sap.sailing.gwt.home.desktop.places.event; -import java.util.UUID; - import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; +import com.sap.sailing.gwt.home.desktop.app.WithHeader; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.AbstractMultiregattaEventPlace; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaActivity; -import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.mediatab.MultiregattaMediaPlace; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.overviewtab.MultiregattaOverviewPlace; -import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.regattastab.MultiregattaRegattasPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegattaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaActivity; import com.sap.sailing.gwt.home.desktop.places.event.regatta.leaderboardtab.RegattaLeaderboardPlace; -import com.sap.sailing.gwt.home.desktop.places.event.regatta.mediatab.RegattaMediaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; -import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; import com.sap.sailing.gwt.home.mobile.places.event.latestnews.LatestNewsPlace; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.places.event.AbstractEventActivityProxy; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.event.EventContext; -import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventViewAction; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class EventActivityProxy extends AbstractActivityProxy { +public class EventActivityProxy extends AbstractEventActivityProxy implements WithHeader { - private AbstractEventPlace place; - private EventContext ctx; - private EventClientFactory clientFactory; private DesktopPlacesNavigator homePlacesNavigator; public EventActivityProxy(AbstractEventPlace place, EventClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { - this.place = place; + super(clientFactory, place); this.homePlacesNavigator = homePlacesNavigator; - this.ctx = this.place.getCtx(); - this.clientFactory = clientFactory; } @Override - protected void startAsync() { - if (ctx.getEventDTO() != null) { - afterEventLoad(); - } else { - final UUID eventUUID = UUID.fromString(ctx.getEventId()); - - clientFactory.getDispatch().execute(new GetEventViewAction(eventUUID), new AsyncCallback() { - @Override - public void onSuccess(final EventViewDTO event) { - ctx.updateContext(event); - afterEventLoad(); - } - - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract text? - ErrorPlace errorPlace = new ErrorPlace("Error while loading the event with service getEventViewById()"); - // TODO @FM: reload sinnvoll hier? - errorPlace.setComingFrom(place); - clientFactory.getPlaceController().goTo(errorPlace); - } - }); - - } - } - - private void afterEventLoad() { - if(place instanceof EventDefaultPlace) { - place = getRealPlace(); - } - place = verifyAndAdjustPlace(); - afterLoad(); - } - - private void afterLoad() { + protected void afterEventLoad(final EventClientFactory clientFactory, final EventViewDTO event, + final AbstractEventPlace place) { GWT.runAsync(new AbstractRunAsyncCallback() { @Override public void onSuccess() { - if(place instanceof AbstractEventRegattaPlace) { - super.onSuccess(new EventRegattaActivity((AbstractEventRegattaPlace) place, clientFactory, - homePlacesNavigator)); + if (place instanceof AbstractEventRegattaPlace) { + super.onSuccess(new EventRegattaActivity((AbstractEventRegattaPlace) place, event, clientFactory, + homePlacesNavigator, getNavigationPathDisplay())); } - if(place instanceof AbstractMultiregattaEventPlace) { - super.onSuccess(new EventMultiregattaActivity((AbstractMultiregattaEventPlace) place, - clientFactory, homePlacesNavigator)); + if (place instanceof AbstractMultiregattaEventPlace) { + super.onSuccess(new EventMultiregattaActivity((AbstractMultiregattaEventPlace) place, event, + clientFactory, homePlacesNavigator, getNavigationPathDisplay())); } } }); } - - private AbstractEventPlace getRealPlace() { - EventViewDTO event = ctx.getEventDTO(); - - if(event.getType() == EventType.SERIES_EVENT || event.getType() == EventType.SINGLE_REGATTA) { - return new RegattaOverviewPlace(new EventContext(ctx).withRegattaId(null)); - } - return new MultiregattaOverviewPlace(place.getCtx()); - } - /** - * Checks if the place is valid for the given event. - * If not, the place is automatically being adjusted. - */ - private AbstractEventPlace verifyAndAdjustPlace() { - EventContext contextWithoutRegatta = new EventContext(ctx).withRegattaId(null); - // TODO check if regatta ID is valid - if(place instanceof AbstractMultiregattaEventPlace && ctx.getEventDTO().getType() != EventType.MULTI_REGATTA) { - // Events with a type other than multi regatta only have regatta level pages - if(place instanceof MultiregattaRegattasPlace) { - return new RegattaRacesPlace(contextWithoutRegatta); - } - if(place instanceof MultiregattaMediaPlace) { - return new RegattaMediaPlace(contextWithoutRegatta); + @Override + protected AbstractEventPlace verifyAndAdjustPlace(EventViewDTO event) { + AbstractEventPlace adjustedPlace = super.verifyAndAdjustPlace(event); + EventContext contextWithoutRegatta = new EventContext(adjustedPlace.getCtx()).withRegattaId(null); + if(adjustedPlace instanceof LatestNewsPlace) { + if(event.getType() == EventType.MULTI_REGATTA) { + return new MultiregattaOverviewPlace(contextWithoutRegatta); } return new RegattaOverviewPlace(contextWithoutRegatta); } - if(place instanceof AbstractEventRegattaPlace) { - boolean regattaKnown = ctx.getEventDTO().isRegattaIDKnown(ctx.getRegattaId()); - if(ctx.getEventDTO().getType() != EventType.MULTI_REGATTA && ctx.getRegattaId() != null && !regattaKnown) { - // Regatta ID unknown but unnecessary ... - ctx.withRegattaId(null); - } else if(ctx.getEventDTO().getType() == EventType.MULTI_REGATTA && !regattaKnown) { - return new MultiregattaRegattasPlace(contextWithoutRegatta); - } + if(adjustedPlace instanceof MiniLeaderboardPlace) { + return new RegattaLeaderboardPlace(adjustedPlace.getCtx()); } - - if(place instanceof RegattaMediaPlace && ctx.getEventDTO().getType() == EventType.MULTI_REGATTA) { - // The media page for multi regatta events is on event level only but not on regatta level - return new MultiregattaMediaPlace(new EventContext(ctx).withRegattaId(null)); - } - - if(place instanceof LatestNewsPlace) { - if(ctx.getEventDTO().getType() == EventType.MULTI_REGATTA) { - return new MultiregattaOverviewPlace(new EventContext(ctx).withRegattaId(null)); - } - return new RegattaOverviewPlace(new EventContext(ctx).withRegattaId(null)); - } - - if(place instanceof MiniLeaderboardPlace) { - return new RegattaLeaderboardPlace(place.getCtx()); - } - - // no adjustment necessary - return place; + return adjustedPlace; } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventClientFactory.java index a499726ef5a..39ea679b397 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventClientFactory.java @@ -1,9 +1,8 @@ package com.sap.sailing.gwt.home.desktop.places.event; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; import com.sap.sailing.gwt.ui.client.SailingClientFactory; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; -public interface EventClientFactory extends SailingClientFactory { - - DispatchSystem getDispatch(); +public interface EventClientFactory extends SailingClientFactory, ErrorAndBusyClientFactory, ClientFactoryWithDispatch { } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventView.java index 5c19199a527..d0c0f113290 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/EventView.java @@ -5,24 +5,24 @@ import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.IsWidget; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata; +import com.sap.sailing.gwt.home.communication.media.MediaDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegattaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.leaderboardtab.RegattaLeaderboardPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.event.EventContext; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.client.HomeServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; import com.sap.sse.gwt.client.player.Timer; public interface EventView extends IsWidget { @@ -38,7 +38,6 @@ public interface EventView getRegattaRacesNavigation(String regattaName); PlaceNavigation getRegattaNavigation(String regattaName); PlaceNavigation getRegattaLeaderboardNavigation(String regattaName); @@ -66,7 +61,18 @@ public interface EventView implements EventMultiregattaView.Presenter { private EventMultiregattaView currentView = new TabletAndDesktopMultiRegattaEventView(); - public EventMultiregattaActivity(AbstractMultiregattaEventPlace place, EventClientFactory clientFactory, - DesktopPlacesNavigator homePlacesNavigator) { - super(place, clientFactory, homePlacesNavigator); + public EventMultiregattaActivity(AbstractMultiregattaEventPlace place, EventViewDTO eventDTO, EventClientFactory clientFactory, + DesktopPlacesNavigator homePlacesNavigator, NavigationPathDisplay navigationPathDisplay) { + super(place, eventDTO, clientFactory, homePlacesNavigator); + + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + navigationPathDisplay.showNavigationPath(new NavigationItem(i18n.home(), getHomeNavigation()), + new NavigationItem(i18n.events(), getEventsNavigation()), + new NavigationItem(getEventDTO().getDisplayName(), getCurrentEventNavigation())); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/TabletAndDesktopMultiRegattaEventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/TabletAndDesktopMultiRegattaEventView.java index 589098f4ac4..d8e3c7efcc2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/TabletAndDesktopMultiRegattaEventView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/TabletAndDesktopMultiRegattaEventView.java @@ -52,7 +52,7 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements initWidget(uiBinder.createAndBindUi(this)); initBreadCrumbs(); - String sailorsInfoURL = currentPresenter.getCtx().getEventDTO().getSailorsInfoWebsiteURL(); + String sailorsInfoURL = currentPresenter.getEventDTO().getSailorsInfoWebsiteURL(); if(sailorsInfoURL != null && ! sailorsInfoURL.isEmpty()) { Label label = new Label(); label.getElement().setInnerHTML(i18n.sailorInfoLongText().replace("\n", "
")); @@ -79,7 +79,7 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements StringBuilder titleBuilder = new StringBuilder(TextMessages.INSTANCE.sapSailing()).append(" - "); titleBuilder.append(currentPresenter.showRegattaMetadata() ? currentPresenter.getRegattaMetadata() - .getDisplayName() : currentPresenter.getCtx().getEventDTO().getDisplayName()); + .getDisplayName() : currentPresenter.getEventDTO().getDisplayName()); String currentTabTitle = tabPanelUi.getCurrentTabTitle(); if (currentTabTitle != null && !currentTabTitle.isEmpty()) { titleBuilder.append(" - ").append(currentTabTitle); @@ -96,7 +96,7 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements private void initBreadCrumbs() { addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation()); addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation()); - addBreadCrumbItem(currentPresenter.getCtx().getEventDTO().getDisplayName(), currentPresenter.getCurrentEventNavigation()); + addBreadCrumbItem(currentPresenter.getEventDTO().getDisplayName(), currentPresenter.getCurrentEventNavigation()); } private void addBreadCrumbItem(String label, final PlaceNavigation placeNavigation) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.java index b8bccf2bf03..d144e6db06c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.java @@ -1,25 +1,26 @@ package com.sap.sailing.gwt.home.desktop.places.event.multiregatta.mediatab; -import com.google.gwt.core.client.GWT; -import com.google.gwt.uibinder.client.UiBinder; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.HTMLPanel; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.media.MediaDTO; import com.sap.sailing.gwt.home.desktop.partials.media.MediaPage; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView; -import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView.Presenter; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; /** * Created by pgtaboada on 25.11.14. */ public class MultiregattaMediaTabView extends Composite implements MultiregattaTabView { - - public MultiregattaMediaTabView() { - + + private Presenter currentPresenter; + + @Override + public void setPresenter(EventMultiregattaView.Presenter currentPresenter) { + this.currentPresenter = currentPresenter; } @Override @@ -34,16 +35,10 @@ public class MultiregattaMediaTabView extends Composite implements MultiregattaT @Override public void start(MultiregattaMediaPlace myPlace, final AcceptsOneWidget contentArea) { - final MediaPage mediaPage = new MediaPage(); + ErrorAndBusyClientFactory errorAndBusyClientFactory = currentPresenter.getErrorAndBusyClientFactory(); + final MediaPage mediaPage = new MediaPage(errorAndBusyClientFactory.createBusyView()); initWidget(mediaPage); - - currentPresenter.ensureMedia(new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - - } - + currentPresenter.ensureMedia(new ActivityCallback(errorAndBusyClientFactory, contentArea) { @Override public void onSuccess(MediaDTO media) { contentArea.setWidget(MultiregattaMediaTabView.this); @@ -54,26 +49,10 @@ public class MultiregattaMediaTabView extends Composite implements MultiregattaT @Override public void stop() { - } - // TODO delete UiBinder if we do not need it for the new media page implementation - interface MyBinder extends UiBinder { - } - - @SuppressWarnings("unused") - private static MyBinder ourUiBinder = GWT.create(MyBinder.class); - private Presenter currentPresenter; - @Override public MultiregattaMediaPlace placeToFire() { return new MultiregattaMediaPlace(currentPresenter.getCtx()); } - - @Override - public void setPresenter(EventMultiregattaView.Presenter currentPresenter) { - this.currentPresenter = currentPresenter; - - } - -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.ui.xml deleted file mode 100644 index c149137f7f0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/mediatab/MultiregattaMediaTabView.ui.xml +++ /dev/null @@ -1,6 +0,0 @@ - - -

This is MEDIA tab

-
-
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/overviewtab/MultiregattaOverviewTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/overviewtab/MultiregattaOverviewTabView.java index 117972efa93..81174530b44 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/overviewtab/MultiregattaOverviewTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/overviewtab/MultiregattaOverviewTabView.java @@ -9,6 +9,11 @@ import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTMLPanel; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForEventAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaListViewAction; +import com.sap.sailing.gwt.home.communication.event.statistics.GetEventStatisticsAction; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; import com.sap.sailing.gwt.home.desktop.partials.eventstage.EventOverviewStage; import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList; import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaList; @@ -17,16 +22,12 @@ import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.DropdownFilte import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.DropdownFilter.DropdownFilterList; import com.sap.sailing.gwt.home.desktop.partials.statistics.StatisticsBox; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView; -import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView.Presenter; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; +import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventStatisticsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; /** * Created by pgtaboada on 25.11.14. @@ -66,17 +67,17 @@ public class MultiregattaOverviewTabView extends Composite implements Multiregat stageUi = new EventOverviewStage(currentPresenter); liveRacesListUi = new LiveRacesList(currentPresenter, true); MultiregattaOverviewRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaOverviewRegattasTabViewRegattaFilterList(); - boatCategoryFilterUi = new DropdownFilter(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList); + boatCategoryFilterUi = new DropdownFilter(StringMessages.INSTANCE.all(), regattaFilterList); regattaListUi = new MultiRegattaList(currentPresenter, false); initWidget(ourUiBinder.createAndBindUi(this)); raceOfficeSectionUi.addLink(StringMessages.INSTANCE.racesOverview(), currentPresenter.getRegattaOverviewLink()); - RefreshManager refreshManager = new RefreshManager(this, contentArea, currentPresenter.getDispatch()); + RefreshManager refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory()); stageUi.setupRefresh(refreshManager); - refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId())); + refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getEventDTO().getId())); - refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId())); - refreshManager.add(statisticsBoxUi, new GetEventStatisticsAction(currentPresenter.getCtx().getEventDTO().getId())); + refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getEventDTO().getId())); + refreshManager.add(statisticsBoxUi, new GetEventStatisticsAction(currentPresenter.getEventDTO().getId())); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/regattastab/MultiregattaRegattasTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/regattastab/MultiregattaRegattasTabView.java index c15d267b1ac..fdabe3ff3e3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/regattastab/MultiregattaRegattasTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/multiregatta/regattastab/MultiregattaRegattasTabView.java @@ -9,21 +9,22 @@ import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTMLPanel; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForEventAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaListViewAction; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList; import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaList; import com.sap.sailing.gwt.home.desktop.partials.raceoffice.RaceOfficeSection; import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.DropdownFilter; import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.DropdownFilter.DropdownFilterList; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView; -import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.EventMultiregattaView.Presenter; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.MultiregattaTabView; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; +import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForEventAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaListViewAction; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; /** * Created by pgtaboada on 25.11.14. @@ -60,15 +61,15 @@ public class MultiregattaRegattasTabView extends Composite implements Multiregat public void start(final MultiregattaRegattasPlace myPlace, final AcceptsOneWidget contentArea) { liveRacesListUi = new LiveRacesList(currentPresenter, true); MultiregattaRegattasTabViewRegattaFilterList regattaFilterList = new MultiregattaRegattasTabViewRegattaFilterList(); - boatCategoryFilterUi = new DropdownFilter(StringMessages.INSTANCE.allBoatClasses(), regattaFilterList); + boatCategoryFilterUi = new DropdownFilter(StringMessages.INSTANCE.all(), regattaFilterList); regattaListUi = new MultiRegattaList(currentPresenter, true); initWidget(ourUiBinder.createAndBindUi(this)); raceOfficeSectionUi.addLink(StringMessages.INSTANCE.racesOverview(), currentPresenter.getRegattaOverviewLink()); - RefreshManager refreshManager = new RefreshManager(this, contentArea, currentPresenter.getDispatch()); - refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getCtx().getEventDTO().getId())); + RefreshManager refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory()); + refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForEventAction(currentPresenter.getEventDTO().getId())); - refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getCtx().getEventDTO().getId())); + refreshManager.add(regattaFilterList, new GetRegattaListViewAction(currentPresenter.getEventDTO().getId())); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/EventRegattaActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/EventRegattaActivity.java index 75f913b62ea..04598a7de12 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/EventRegattaActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/EventRegattaActivity.java @@ -1,20 +1,29 @@ package com.sap.sailing.gwt.home.desktop.places.event.regatta; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata.RegattaState; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.desktop.places.event.AbstractEventActivity; import com.sap.sailing.gwt.home.desktop.places.event.EventClientFactory; import com.sap.sailing.gwt.home.desktop.places.event.EventView; import com.sap.sailing.gwt.home.desktop.places.event.EventView.PlaceCallback; import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.places.event.EventContext; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaReferenceDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; @@ -27,9 +36,9 @@ public class EventRegattaActivity extends AbstractEventActivity navigationItems = new ArrayList<>(); + navigationItems.add(new NavigationItem(i18n.home(), getHomeNavigation())); + navigationItems.add(new NavigationItem(i18n.events(), getEventsNavigation())); + if(getEventDTO().getType() == EventType.SERIES_EVENT) { + navigationItems.add(new NavigationItem(getEventDTO().getSeriesName(), getCurrentEventSeriesNavigation())); + } + navigationItems.add(new NavigationItem(getEventDTO().getLocationOrDisplayName(), getCurrentEventNavigation())); + + if(showRegattaMetadata()) { + navigationItems.add(new NavigationItem(getRegattaMetadata().getDisplayName(), getCurrentRegattaOverviewNavigation())); + } + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); } @Override @@ -49,13 +76,13 @@ public class EventRegattaActivity extends AbstractEventActivity getView() { return currentView; } + + public RegattaMetadataDTO getRegatta() { + String regattaId = getRegattaId(); + if(regattaId == null) { + return null; + } + for (RegattaMetadataDTO regatta : eventDTO.getRegattas()) { + if(regattaId.equals(regatta.getId())) { + return regatta; + } + } + return null; + } + + @Override + public HasRegattaMetadata getRegattaMetadata() { + return getRegatta(); + } + + @Override + public boolean isEventOrRegattaLive() { + if(showRegattaMetadata()) { + if(getRegatta().getState() == RegattaState.RUNNING) { + return true; + } + } + return super.isEventOrRegattaLive(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/TabletAndDesktopRegattaEventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/TabletAndDesktopRegattaEventView.java index ff5124c1efb..75ddd21b195 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/TabletAndDesktopRegattaEventView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/TabletAndDesktopRegattaEventView.java @@ -20,12 +20,12 @@ import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanel; import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanelPlaceSelectionEvent; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; import com.sap.sailing.gwt.home.desktop.partials.eventheader.EventHeader; import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; public class TabletAndDesktopRegattaEventView extends Composite implements EventRegattaView { @@ -54,9 +54,9 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event initWidget(uiBinder.createAndBindUi(this)); initBreadCrumbs(); - if(currentPresenter.getCtx().getEventDTO().getType() == EventType.SERIES_EVENT) { + if(currentPresenter.getEventDTO().getType() == EventType.SERIES_EVENT) { final PlaceNavigation currentEventSeriesNavigation = currentPresenter.getCurrentEventSeriesNavigation(); - Anchor seriesAnchor = new Anchor(currentPresenter.getCtx().getEventDTO().getSeriesName()); + Anchor seriesAnchor = new Anchor(currentPresenter.getEventDTO().getSeriesName()); seriesAnchor.setHref(currentEventSeriesNavigation.getTargetUrl()); seriesAnchor.addClickHandler(new ClickHandler() { @Override @@ -82,7 +82,7 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event StringBuilder titleBuilder = new StringBuilder(TextMessages.INSTANCE.sapSailing()).append(" - "); titleBuilder.append(currentPresenter.showRegattaMetadata() ? currentPresenter.getRegattaMetadata() - .getDisplayName() : currentPresenter.getCtx().getEventDTO().getDisplayName()); + .getDisplayName() : currentPresenter.getEventDTO().getDisplayName()); String currentTabTitle = tabPanelUi.getCurrentTabTitle(); if (currentTabTitle != null && !currentTabTitle.isEmpty()) { titleBuilder.append(" - ").append(currentTabTitle); @@ -99,10 +99,10 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event private void initBreadCrumbs() { addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation()); addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation()); - if(currentPresenter.getCtx().getEventDTO().getType() == EventType.SERIES_EVENT) { - addBreadCrumbItem(currentPresenter.getCtx().getEventDTO().getSeriesName(), currentPresenter.getCurrentEventSeriesNavigation()); + if(currentPresenter.getEventDTO().getType() == EventType.SERIES_EVENT) { + addBreadCrumbItem(currentPresenter.getEventDTO().getSeriesName(), currentPresenter.getCurrentEventSeriesNavigation()); } - addBreadCrumbItem(currentPresenter.getCtx().getEventDTO().getLocationOrDisplayName(), currentPresenter.getCurrentEventNavigation()); + addBreadCrumbItem(currentPresenter.getEventDTO().getLocationOrDisplayName(), currentPresenter.getCurrentEventNavigation()); if(currentPresenter.showRegattaMetadata()) { addBreadCrumbItem(currentPresenter.getRegattaMetadata().getDisplayName(), currentPresenter.getCurrentRegattaOverviewNavigation()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/analyticstab/RegattaCompetitorAnalyticsTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/analyticstab/RegattaCompetitorAnalyticsTabView.java index f11e8b5a192..391a1926458 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/analyticstab/RegattaCompetitorAnalyticsTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/analyticstab/RegattaCompetitorAnalyticsTabView.java @@ -56,13 +56,13 @@ public class RegattaCompetitorAnalyticsTabView extends SharedLeaderboardRegattaT @Override public TabView.State getState() { - return currentPresenter.getCtx().getEventDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; + return currentPresenter.getEventDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; } @Override public void start(RegattaCompetitorAnalyticsPlace myPlace, AcceptsOneWidget contentArea) { contentArea.setWidget(new Placeholder()); - String regattaId = myPlace.getRegattaId(); + String regattaId = currentPresenter.getRegattaId(); if (regattaId != null && !regattaId.isEmpty()) { String leaderboardName = regattaId; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/leaderboardtab/RegattaLeaderboardTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/leaderboardtab/RegattaLeaderboardTabView.java index b1bc983e47c..7d6add4f4fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/leaderboardtab/RegattaLeaderboardTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/leaderboardtab/RegattaLeaderboardTabView.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.event.EventState; import com.sap.sailing.gwt.home.desktop.partials.old.leaderboard.OldLeaderboard; import com.sap.sailing.gwt.home.desktop.partials.old.leaderboard.OldLeaderboardDelegateFullscreenViewer; import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaView; @@ -18,7 +19,6 @@ import com.sap.sailing.gwt.home.desktop.places.event.regatta.SharedLeaderboardRe import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaView.Presenter; import com.sap.sailing.gwt.home.shared.partials.placeholder.Placeholder; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; -import com.sap.sailing.gwt.ui.shared.general.EventState; /** * Created by pgtaboada on 25.11.14. @@ -50,13 +50,13 @@ public class RegattaLeaderboardTabView extends SharedLeaderboardRegattaTabView { - - public RegattaMediaTabView() { - + + private Presenter currentPresenter; + + @Override + public void setPresenter(EventRegattaView.Presenter currentPresenter) { + this.currentPresenter = currentPresenter; } @Override @@ -34,16 +35,10 @@ public class RegattaMediaTabView extends Composite implements RegattaTabView() { - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - - } - + currentPresenter.ensureMedia(new ActivityCallback(errorAndBusyClientFactory, contentArea) { @Override public void onSuccess(MediaDTO media) { contentArea.setWidget(RegattaMediaTabView.this); @@ -54,25 +49,10 @@ public class RegattaMediaTabView extends Composite implements RegattaTabView { - } - - @SuppressWarnings("unused") - private static MyBinder ourUiBinder = GWT.create(MyBinder.class); - private Presenter currentPresenter; - @Override public RegattaMediaPlace placeToFire() { return new RegattaMediaPlace(currentPresenter.getCtx()); } - - @Override - public void setPresenter(EventRegattaView.Presenter currentPresenter) { - this.currentPresenter = currentPresenter; - } - -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/mediatab/RegattaMediaTabView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/mediatab/RegattaMediaTabView.ui.xml deleted file mode 100644 index c149137f7f0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/mediatab/RegattaMediaTabView.ui.xml +++ /dev/null @@ -1,6 +0,0 @@ - - -

This is MEDIA tab

-
-
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/overviewtab/RegattaOverviewTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/overviewtab/RegattaOverviewTabView.java index 37ecf379802..22efb5a4088 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/overviewtab/RegattaOverviewTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/overviewtab/RegattaOverviewTabView.java @@ -8,24 +8,25 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForRegattaAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaStatisticsAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaWithProgressAction; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderbordAction; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata.RegattaState; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; import com.sap.sailing.gwt.home.desktop.partials.eventstage.EventOverviewStage; import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList; import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaListItem; import com.sap.sailing.gwt.home.desktop.partials.standings.StandingsList; import com.sap.sailing.gwt.home.desktop.partials.statistics.StatisticsBox; import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaView; -import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaTabView; import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaView.Presenter; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaTabView; import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; +import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForRegattaAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaStatisticsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaWithProgressAction; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata.RegattaState; /** * Created by pgtaboada on 25.11.14. @@ -54,11 +55,10 @@ public class RegattaOverviewTabView extends Composite implements RegattaTabView< @Override public TabView.State getState() { - if(ExperimentalFeatures.SHOW_SINGLE_REGATTA_OVERVIEW) { - return currentPresenter.getCtx().getEventDTO().getType() == EventType.MULTI_REGATTA ? TabView.State.NOT_AVAILABLE_SHOW_NEXT_AVAILABLE - : TabView.State.VISIBLE; + if (currentPresenter.getEventDTO().getType() == EventType.MULTI_REGATTA) { + return ExperimentalFeatures.SHOW_MULTIREGATTAEVENT_REGATTA_OVERVIEW ? State.VISIBLE : State.NOT_AVAILABLE_SHOW_NEXT_AVAILABLE; } else { - return TabView.State.NOT_AVAILABLE_SHOW_NEXT_AVAILABLE; + return ExperimentalFeatures.SHOW_SINGLE_REGATTA_OVERVIEW ? State.VISIBLE : State.NOT_AVAILABLE_SHOW_NEXT_AVAILABLE; } } @@ -67,23 +67,27 @@ public class RegattaOverviewTabView extends Composite implements RegattaTabView< liveRacesListUi = new LiveRacesList(currentPresenter, false); stageUi = new EventOverviewStage(currentPresenter); statisticsBoxUi = new StatisticsBox(false); - standingsUi = new StandingsList(currentPresenter.getRegattaMetadata().getState() == RegattaState.FINISHED, currentPresenter.getRegattaLeaderboardNavigation(myPlace.getRegattaId())); + standingsUi = new StandingsList(currentPresenter.getRegattaMetadata().getState() == RegattaState.FINISHED, currentPresenter.getRegattaLeaderboardNavigation(currentPresenter.getRegattaId())); initWidget(ourUiBinder.createAndBindUi(this)); - RefreshManager refreshManager = new RefreshManager(this, contentArea, currentPresenter.getDispatch()); + RefreshManager refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory()); refreshManager.add(new RefreshableWidget() { @Override public void setData(RegattaWithProgressDTO data) { regattaInfoContainerUi.setWidget(new MultiRegattaListItem(data, true)); } - }, new GetRegattaWithProgressAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId())); + }, new GetRegattaWithProgressAction(currentPresenter.getEventDTO().getId(), currentPresenter.getRegattaId())); - stageUi.setupRefresh(refreshManager); - refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForRegattaAction(currentPresenter.getCtx().getEventDTO() - .getId(), currentPresenter.getCtx().getRegattaId())); - refreshManager.add(standingsUi, new GetMiniLeaderbordAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId(), 5)); - refreshManager.add(statisticsBoxUi, new GetRegattaStatisticsAction(myPlace.getCtx().getEventDTO().getId(), myPlace.getRegattaId())); + if (currentPresenter.getEventDTO().getType() == EventType.MULTI_REGATTA) { + stageUi.removeFromParent(); + } else { + stageUi.setupRefresh(refreshManager); + } + refreshManager.add(liveRacesListUi.getRefreshable(), new GetLiveRacesForRegattaAction(currentPresenter.getEventDTO() + .getId(), currentPresenter.getRegattaId())); + refreshManager.add(standingsUi, new GetMiniLeaderbordAction(currentPresenter.getEventDTO().getId(), currentPresenter.getRegattaId(), 5)); + refreshManager.add(statisticsBoxUi, new GetRegattaStatisticsAction(currentPresenter.getEventDTO().getId(), currentPresenter.getRegattaId())); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.java index ee1f79c7b06..2794088c87a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.java @@ -1,20 +1,33 @@ package com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.UUID; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; -import com.google.gwt.dom.client.Element; -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.ui.AcceptsOneWidget; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.event.GetCompetitionFormatRacesAction; +import com.sap.sailing.gwt.home.communication.event.GetFinishedRacesAction; +import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForRegattaAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaWithProgressAction; +import com.sap.sailing.gwt.home.communication.event.RaceListRaceDTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; import com.sap.sailing.gwt.home.desktop.partials.liveraces.LiveRacesList; import com.sap.sailing.gwt.home.desktop.partials.multiregattalist.MultiRegattaListItem; import com.sap.sailing.gwt.home.desktop.partials.racelist.AbstractRaceList; @@ -24,7 +37,7 @@ import com.sap.sailing.gwt.home.desktop.partials.racelist.RaceListContainer; import com.sap.sailing.gwt.home.desktop.partials.racelist.RaceListDataUtil; import com.sap.sailing.gwt.home.desktop.partials.racelist.SortableRaceListColumn; import com.sap.sailing.gwt.home.desktop.partials.raceoffice.RaceOfficeSection; -import com.sap.sailing.gwt.home.desktop.partials.regattacompetition.RegattaCompetitionSeries; +import com.sap.sailing.gwt.home.desktop.partials.regattacompetition.RegattaCompetition; import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.ListNavigationPanel; import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.ListNavigationPanel.ListNavigationAction; import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.ListNavigationPanel.SelectionCallback; @@ -32,21 +45,16 @@ import com.sap.sailing.gwt.home.desktop.places.event.EventView; import com.sap.sailing.gwt.home.desktop.places.event.regatta.EventRegattaView.Presenter; import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaTabView; import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterPresenter; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterWidget; +import com.sap.sailing.gwt.home.shared.partials.filter.RacesByCompetitorTextBoxFilter; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter; import com.sap.sailing.gwt.home.shared.refresh.ActionProvider.AbstractActionProvider; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; +import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetCompetitionFormatRacesAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetFinishedRacesAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForRegattaAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaWithProgressAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceCompetitionFormatSeriesDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceListRaceDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; /** * Created by pgtaboada on 25.11.14. @@ -56,8 +64,8 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView listNavigationPanelUi; @UiField DivElement listFormatContainerUi; - @UiField FlowPanel compFormatContainerUi; + @UiField RegattaCompetition compFormatContainerUi; @UiField(provided = true) LiveRacesList liveRacesListUi; @UiField(provided = true) RaceListContainer raceListContainerUi; @UiField RaceOfficeSection raceOfficeSectionUi; + private final RacesByCompetitorTextBoxFilter competitorFilterUi = new RacesByCompetitorTextBoxFilter(); + private RegattaRacesTabViewFilterPresenter filterPresenter; private Navigation currentlySelectedTab = Navigation.SORT_LIST_FORMAT; private RefreshManager refreshManager; @@ -108,15 +118,17 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView(new RegattaRacesTabViewNavigationSelectionCallback()); - // listNavigationPanelUi.setAdditionalWidget(new RaceStateLegend()); + listNavigationPanelUi.setAdditionalWidget(competitorFilterUi); liveRacesListUi = new LiveRacesList(currentPresenter, false); - raceListContainerUi = new RaceListContainer<>(I18N.finishedRaces(), I18N.noFinishedRaces(), new RaceListFinishedRaces(currentPresenter)); + RaceListFinishedRaces finishedRacesList = new RaceListFinishedRaces(currentPresenter); + raceListContainerUi = new RaceListContainer<>(I18N.finishedRaces(), I18N.noFinishedRaces(), finishedRacesList); initWidget(ourUiBinder.createAndBindUi(RegattaRacesTabView.this)); raceOfficeSectionUi.addLink(I18N.racesOverview(), currentPresenter.getRegattaOverviewLink()); - refreshManager = new RefreshManager(this, contentArea, currentPresenter.getDispatch()); - UUID eventId = myPlace.getCtx().getEventDTO().getId(); - String regattaId = myPlace.getRegattaId(); + refreshManager = new RefreshManagerWithErrorAndBusy(this, contentArea, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory()); + filterPresenter = new RegattaRacesTabViewFilterPresenter(competitorFilterUi); + UUID eventId = currentPresenter.getEventDTO().getId(); + String regattaId = currentPresenter.getRegattaId(); refreshManager.add(new RefreshableWidget() { @Override public void setData(RegattaWithProgressDTO data) { @@ -124,29 +136,26 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView>() { - @Override - public void setData(ListResult data) { - compFormatContainerUi.clear(); - for (RaceCompetitionFormatSeriesDTO series : data.getValues()) { - compFormatContainerUi.add(new RegattaCompetitionSeries(currentPresenter, series)); - } - } - }, new GetCompetitionFormatRacesAction(eventId, regattaId), Navigation.COMPETITION_FORMAT); + RegattaCompetitionPresenter competitionPresenter = new DesktopRegattaCompetitionPresenter(); + addRacesAction(competitionPresenter, new GetCompetitionFormatRacesAction(eventId, regattaId), Navigation.COMPETITION_FORMAT); + filterPresenter.addHandler(Navigation.COMPETITION_FORMAT, competitionPresenter); } else { listNavigationPanelUi.removeFromParent(); compFormatContainerUi.removeFromParent(); } } - private >> void addRacesAction( - RefreshableWidget widget, A action, Navigation assosiatedTab) { - refreshManager.add(widget, new RegattaRacesTabViewActionProvider<>(action, assosiatedTab)); + private >> void addRacesAction( + final RefreshableWidget widget, A action, Navigation assosiatedTab) { + refreshManager.add(filterPresenter.getRefreshableWidgetWrapper(widget), + new RegattaRacesTabViewActionProvider<>(action, assosiatedTab)); } @Override @@ -168,21 +177,15 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView> extends AbstractActionProvider { + private class RegattaRacesTabViewActionProvider> extends AbstractActionProvider { private final Navigation assosiatedTab; public RegattaRacesTabViewActionProvider(A action, Navigation assosiatedTab) { @@ -252,6 +255,38 @@ public class RegattaRacesTabView extends Composite implements RegattaTabView { + private final Map>> handlersByTab = new HashMap<>(); + + private RegattaRacesTabViewFilterPresenter(FilterWidget filterWidget) { + super(filterWidget); + } + + @Override + protected List> getCurrentValueChangeHandlers() { + return handlersByTab.get(currentlySelectedTab); + } + + private void addHandler(Navigation assosiatedTab, FilterValueChangeHandler handler) { + List> list = handlersByTab.get(assosiatedTab); + if (list == null) this.handlersByTab.put(assosiatedTab, list = new ArrayList<>()); + list.add(handler); + super.addHandler(handler); + } + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.ui.xml index b685df85c7f..77ab15214f4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/event/regatta/racestab/RegattaRacesTabView.ui.xml @@ -21,9 +21,7 @@
- - - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/AbstractEventsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/AbstractEventsView.java index 906336dc374..032b8f9aa96 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/AbstractEventsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/AbstractEventsView.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.places.events; import com.google.gwt.user.client.ui.Composite; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; public abstract class AbstractEventsView extends Composite implements EventsView { protected EventListViewDTO eventListView; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivity.java index 95bf5555f0e..d46e7b767a9 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivity.java @@ -3,42 +3,49 @@ package com.sap.sailing.gwt.home.desktop.places.events; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.communication.event.GetEventListViewAction; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; +import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.partials.placeholder.Placeholder; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sse.gwt.client.mvp.ErrorView; +import com.sap.sailing.gwt.ui.client.StringMessages; public class EventsActivity extends AbstractActivity { private final EventsClientFactory clientFactory; private final EventsPlace place; + private final DesktopPlacesNavigator homePlacesNavigator; - public EventsActivity(EventsPlace place, EventsClientFactory clientFactory) { + public EventsActivity(EventsPlace place, EventsClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator, NavigationPathDisplay navigationPathDisplay) { this.clientFactory = clientFactory; this.place = place; + this.homePlacesNavigator = homePlacesNavigator; + + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + navigationPathDisplay.showNavigationPath(new NavigationItem(i18n.home(), homePlacesNavigator.getHomeNavigation()), + new NavigationItem(i18n.events(), homePlacesNavigator.getEventsNavigation())); } @Override public void start(final AcceptsOneWidget panel, EventBus eventBus) { panel.setWidget(new Placeholder()); - - clientFactory.getHomeService().getEventListView(new AsyncCallback() { + clientFactory.getDispatch().execute(new GetEventListViewAction(), + new ActivityCallback(clientFactory, panel) { @Override public void onSuccess(EventListViewDTO eventListView) { final EventsView eventsView = clientFactory.createEventsView(); panel.setWidget(eventsView.asWidget()); Window.setTitle(place.getTitle()); - eventsView.setEvents(eventListView); } - - @Override - public void onFailure(Throwable caught) { - final ErrorView view = clientFactory.createErrorView("Error while loading the sailing server instances with service getEventListView()", caught); - panel.setWidget(view.asWidget()); - } }); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivityProxy.java index 158f0f08dd6..2aec550831c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsActivityProxy.java @@ -1,17 +1,23 @@ package com.sap.sailing.gwt.home.desktop.places.events; import com.google.gwt.core.client.GWT; +import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.ProvidesNavigationPath; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class EventsActivityProxy extends AbstractActivityProxy { +public class EventsActivityProxy extends AbstractActivityProxy implements ProvidesNavigationPath { private final EventsClientFactory clientFactory; private final EventsPlace place; + private NavigationPathDisplay navigationPathDisplay; + private final DesktopPlacesNavigator homePlacesNavigator; - public EventsActivityProxy(EventsPlace place, EventsClientFactory clientFactory) { + public EventsActivityProxy(EventsPlace place, EventsClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { this.place = place; this.clientFactory = clientFactory; + this.homePlacesNavigator = homePlacesNavigator; } @Override @@ -19,8 +25,13 @@ public class EventsActivityProxy extends AbstractActivityProxy { GWT.runAsync(new AbstractRunAsyncCallback() { @Override public void onSuccess() { - super.onSuccess(new EventsActivity(place, clientFactory)); + super.onSuccess(new EventsActivity(place, clientFactory, homePlacesNavigator, navigationPathDisplay)); } }); } + + @Override + public void setNavigationPathDisplay(NavigationPathDisplay navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsClientFactory.java index e22c4b19335..15c9f46117e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsClientFactory.java @@ -1,7 +1,9 @@ package com.sap.sailing.gwt.home.desktop.places.events; +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; import com.sap.sailing.gwt.ui.client.SailingClientFactory; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; -public interface EventsClientFactory extends SailingClientFactory { +public interface EventsClientFactory extends SailingClientFactory, ErrorAndBusyClientFactory, ClientFactoryWithDispatch { EventsView createEventsView(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsView.java index 62ed904259b..4927a7855b2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/EventsView.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.places.events; import com.google.gwt.user.client.ui.IsWidget; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; public interface EventsView extends IsWidget { void setEvents(EventListViewDTO eventListView); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/TabletAndDesktopEventsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/TabletAndDesktopEventsView.java index fe23fca016a..1030e585fc2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/TabletAndDesktopEventsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/events/TabletAndDesktopEventsView.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.home.desktop.places.events; import com.google.gwt.core.client.GWT; +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.ui.Widget; @@ -8,6 +9,7 @@ import com.sap.sailing.gwt.common.client.controls.tabbar.BreadcrumbPane; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.desktop.partials.eventsrecent.EventsOverviewRecent; import com.sap.sailing.gwt.home.desktop.partials.eventsupcoming.EventsOverviewUpcoming; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; @@ -38,6 +40,9 @@ public class TabletAndDesktopEventsView extends AbstractEventsView { } private void initBreadCrumbs() { + if(ExperimentalFeatures.USE_NAVIGATION_PATH_DISPLAY_ON_DESKTOP) { + breadcrumbs.getElement().getStyle().setDisplay(Display.NONE); + } final PlaceNavigation homeNavigation = navigator.getHomeNavigation(); breadcrumbs.addBreadcrumbItem(i18n.home(), homeNavigation.getTargetUrl(), new Runnable() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivity.java index 8a40b0422a6..ae6b6166134 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivity.java @@ -9,20 +9,22 @@ import com.google.gwt.place.shared.Place; import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.safehtml.shared.UriUtils; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; import com.sap.sailing.gwt.home.client.place.event.legacy.SeriesClientFactory; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; @@ -44,9 +46,12 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese private final UserAgentDetails userAgent = new UserAgentDetails(Window.Navigator.getUserAgent()); private final AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); private final long delayBetweenAutoAdvancesInMilliseconds = 3000l; + private final EventSeriesViewDTO series; - public SeriesActivity(AbstractSeriesTabPlace place, SeriesClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { + public SeriesActivity(AbstractSeriesTabPlace place, EventSeriesViewDTO series, SeriesClientFactory clientFactory, + DesktopPlacesNavigator homePlacesNavigator, NavigationPathDisplay navigationPathDisplay) { this.currentPlace = place; + this.series = series; this.ctx = new SeriesContext(place.getCtx()); this.clientFactory = clientFactory; this.homePlacesNavigator = homePlacesNavigator; @@ -60,6 +65,15 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese userAgent)); } + + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + navigationPathDisplay.showNavigationPath(new NavigationItem(i18n.home(), getHomeNavigation()), + new NavigationItem(i18n.events(), getEventsNavigation()), + new NavigationItem(getSeriesDTO().getDisplayName(), getCurrentEventSeriesNavigation())); } @Override @@ -110,33 +124,13 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese return homePlacesNavigator.getEventSeriesNavigation(ctx.getSeriesId(), null, false); } - @Override - public void ensureMedia(final AsyncCallback callback) { - if(ctx.getMedia() != null) { - callback.onSuccess(ctx.getMedia()); - return; - } - clientFactory.getHomeService().getMediaForEventSeries(ctx.getSeriesDTO().getId(), new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - callback.onFailure(caught); - } - - @Override - public void onSuccess(MediaDTO result) { - ctx.withMedia(result); - callback.onSuccess(result); - } - }); - } - - @Override - public boolean hasMedia() { - return ctx.getSeriesDTO().isHasMedia(); - } - @Override public Timer getAutoRefreshTimer() { return ctx.getAnalyticsManager().getTimer(); } + + @Override + public EventSeriesViewDTO getSeriesDTO() { + return series; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivityProxy.java index d87b19de09f..0b2aa82fa1f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesActivityProxy.java @@ -3,25 +3,29 @@ package com.sap.sailing.gwt.home.desktop.places.fakeseries; import java.util.UUID; import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.gwt.home.client.place.event.legacy.SeriesClientFactory; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.GetEventSeriesViewAction; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; +import com.sap.sailing.gwt.home.desktop.app.WithHeader; import com.sap.sailing.gwt.home.desktop.places.fakeseries.eventstab.SeriesEventsPlace; import com.sap.sailing.gwt.home.desktop.places.fakeseries.overallleaderboardtab.EventSeriesOverallLeaderboardPlace; import com.sap.sailing.gwt.home.mobile.places.series.minileaderboard.SeriesMiniOverallLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.app.ActivityProxyCallback; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.ProvidesNavigationPath; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class SeriesActivityProxy extends AbstractActivityProxy { +public class SeriesActivityProxy extends AbstractActivityProxy implements ProvidesNavigationPath, WithHeader { private AbstractSeriesPlace place; private SeriesContext ctx; private SeriesClientFactory clientFactory; private final DesktopPlacesNavigator homePlacesNavigator; + private NavigationPathDisplay navigationPathDisplay; public SeriesActivityProxy(AbstractSeriesPlace place, SeriesClientFactory clientFactory, DesktopPlacesNavigator homePlacesNavigator) { @@ -30,48 +34,40 @@ public class SeriesActivityProxy extends AbstractActivityProxy { this.clientFactory = clientFactory; this.homePlacesNavigator = homePlacesNavigator; } + + @Override + public void setNavigationPathDisplay(NavigationPathDisplay navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } @Override protected void startAsync() { - if (ctx.getSeriesDTO() != null) { - afterLoad(); - } else { - final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); - clientFactory.getHomeService().getEventSeriesViewById(seriesUUID, new AsyncCallback() { - @Override - public void onSuccess(final EventSeriesViewDTO event) { - ctx.updateContext(event); - afterLoad(); - } - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract text? - ErrorPlace errorPlace = new ErrorPlace( - "Error while loading the series with service getEventSeriesViewById()"); - // TODO @FM: reload sinnvoll hier? - errorPlace.setComingFrom(place); - clientFactory.getPlaceController().goTo(errorPlace); - } - }); - } - } - - private void afterLoad() { - GWT.runAsync(new AbstractRunAsyncCallback() { + final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); + clientFactory.getDispatch().execute(new GetEventSeriesViewAction(seriesUUID), + new ActivityProxyCallback(clientFactory, place) { @Override - public void onSuccess() { - if (place instanceof SeriesDefaultPlace) { - place = getRealPlace(); - } - place = verifyAndAdjustPlace(); - super.onSuccess(new SeriesActivity((AbstractSeriesTabPlace) place, clientFactory, - homePlacesNavigator)); + public void onSuccess(EventSeriesViewDTO series) { + afterLoad(series); } }); } - private AbstractSeriesPlace getRealPlace() { - if (ctx.getSeriesDTO().isHasAnalytics()) { + private void afterLoad(final EventSeriesViewDTO series) { + GWT.runAsync(new AbstractRunAsyncCallback() { + @Override + public void onSuccess() { + if (place instanceof SeriesDefaultPlace) { + place = getRealPlace(series); + } + place = verifyAndAdjustPlace(); + super.onSuccess(new SeriesActivity((AbstractSeriesTabPlace) place, series, clientFactory, + homePlacesNavigator, navigationPathDisplay)); + } + }); + } + + private AbstractSeriesPlace getRealPlace(EventSeriesViewDTO series) { + if (series.isHasAnalytics()) { return new EventSeriesOverallLeaderboardPlace(ctx); } else { return new SeriesEventsPlace(ctx); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesView.java index c772d4ae8ff..9812ad90a79 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/SeriesView.java @@ -4,9 +4,9 @@ import java.util.UUID; import com.google.gwt.place.shared.Place; import com.google.gwt.safehtml.shared.SafeUri; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.IsWidget; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; @@ -14,7 +14,6 @@ import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; import com.sap.sse.gwt.client.player.Timer; public interface SeriesView extends IsWidget { @@ -33,10 +32,9 @@ public interface SeriesView getEventNavigation(UUID eventId); - void ensureMedia(AsyncCallback asyncCallback); - boolean hasMedia(); - Timer getAutoRefreshTimer(); + + EventSeriesViewDTO getSeriesDTO(); } /** diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/TabletAndDesktopSeriesView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/TabletAndDesktopSeriesView.java index 371e315a631..112489d4584 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/TabletAndDesktopSeriesView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/TabletAndDesktopSeriesView.java @@ -55,7 +55,7 @@ public class TabletAndDesktopSeriesView extends Composite implements SeriesView< tabPanelUi.activatePlace(place); StringBuilder titleBuilder = new StringBuilder(TextMessages.INSTANCE.sapSailing()).append(" - "); - titleBuilder.append(currentPresenter.getCtx().getSeriesDTO().getDisplayName()); + titleBuilder.append(currentPresenter.getSeriesDTO().getDisplayName()); String currentTabTitle = tabPanelUi.getCurrentTabTitle(); if (currentTabTitle != null && !currentTabTitle.isEmpty()) { @@ -73,7 +73,7 @@ public class TabletAndDesktopSeriesView extends Composite implements SeriesView< private void initBreadCrumbs() { addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation()); addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation()); - addBreadCrumbItem(currentPresenter.getCtx().getSeriesDTO().getDisplayName(), currentPresenter.getCurrentEventSeriesNavigation()); + addBreadCrumbItem(currentPresenter.getSeriesDTO().getDisplayName(), currentPresenter.getCurrentEventSeriesNavigation()); } private void addBreadCrumbItem(String label, final PlaceNavigation placeNavigation) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/analyticstab/EventSeriesCompetitorAnalyticsTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/analyticstab/EventSeriesCompetitorAnalyticsTabView.java index feca67e33d7..3789e28beb5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/analyticstab/EventSeriesCompetitorAnalyticsTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/analyticstab/EventSeriesCompetitorAnalyticsTabView.java @@ -53,13 +53,13 @@ public class EventSeriesCompetitorAnalyticsTabView extends SharedLeaderboardEven @Override public TabView.State getState() { - return currentPresenter.getCtx().getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; + return currentPresenter.getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; } @Override public void start(EventSeriesCompetitorAnalyticsPlace myPlace, AcceptsOneWidget contentArea) { contentArea.setWidget(new Placeholder()); - String leaderboardName = myPlace.getCtx().getSeriesDTO().getLeaderboardId(); + String leaderboardName = currentPresenter.getSeriesDTO().getLeaderboardId(); if (leaderboardName != null && !leaderboardName.isEmpty()) { EventSeriesAnalyticsDataManager eventSeriesAnalyticsManager = currentPresenter.getCtx().getAnalyticsManager(); if(eventSeriesAnalyticsManager.getLeaderboardPanel() == null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsPlace.java index fce80382075..89b8c8956c1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsPlace.java @@ -2,11 +2,12 @@ package com.sap.sailing.gwt.home.desktop.places.fakeseries.eventstab; import com.google.gwt.place.shared.Prefix; import com.sap.sailing.gwt.home.desktop.places.fakeseries.AbstractSeriesTabPlace; +import com.sap.sailing.gwt.home.shared.app.HasMobileVersion; import com.sap.sailing.gwt.home.shared.places.PlaceTokenPrefixes; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; -public class SeriesEventsPlace extends AbstractSeriesTabPlace { +public class SeriesEventsPlace extends AbstractSeriesTabPlace implements HasMobileVersion { public SeriesEventsPlace(String id) { super(id); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsTabView.java index 220c55754bb..ebd5f94acb4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/eventstab/SeriesEventsTabView.java @@ -8,13 +8,13 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.controls.tabbar.TabView; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; import com.sap.sailing.gwt.home.desktop.partials.eventsrecent.RecentEventTeaser; import com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesTabView; import com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesView; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; /** * Created by pgtaboada on 25.11.14. @@ -46,7 +46,7 @@ public class SeriesEventsTabView extends Composite implements SeriesTabView, @@ -55,13 +55,13 @@ public class EventSeriesLeaderboardsTabView extends Composite implements SeriesT @Override public TabView.State getState() { - return currentPresenter.getCtx().getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; + return currentPresenter.getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; } @Override public void start(final EventSeriesLeaderboardsPlace myPlace, final AcceptsOneWidget contentArea) { contentArea.setWidget(new Placeholder()); - String leaderboardName = myPlace.getCtx().getSeriesDTO().getLeaderboardId(); + String leaderboardName = currentPresenter.getSeriesDTO().getLeaderboardId(); if (leaderboardName != null && !leaderboardName.isEmpty()) { EventSeriesAnalyticsDataManager regattaAnalyticsManager = currentPresenter.getCtx().getAnalyticsManager(); @@ -81,7 +81,7 @@ public class EventSeriesLeaderboardsTabView extends Composite implements SeriesT leaderboard.setMultiLeaderboard(leaderboardPanel, currentPresenter.getAutoRefreshTimer()); leaderboardPanel.addLeaderboardUpdateListener(this); - if (currentPresenter.getCtx().getSeriesDTO().getState() != EventSeriesState.RUNNING) { + if (currentPresenter.getSeriesDTO().getState() != EventSeriesState.RUNNING) { // TODO: this.leaderboard.hideRefresh(); } else { // TODO: start autorefresh? diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/overallleaderboardtab/EventSeriesOverallLeaderboardTabView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/overallleaderboardtab/EventSeriesOverallLeaderboardTabView.java index 371714577d3..05b90dbe4e8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/overallleaderboardtab/EventSeriesOverallLeaderboardTabView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/fakeseries/overallleaderboardtab/EventSeriesOverallLeaderboardTabView.java @@ -49,13 +49,13 @@ public class EventSeriesOverallLeaderboardTabView extends SharedLeaderboardEvent @Override public TabView.State getState() { - return currentPresenter.getCtx().getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; + return currentPresenter.getSeriesDTO().isHasAnalytics() ? TabView.State.VISIBLE : TabView.State.INVISIBLE; } @Override public void start(final EventSeriesOverallLeaderboardPlace myPlace, final AcceptsOneWidget contentArea) { contentArea.setWidget(new Placeholder()); - String leaderboardName = myPlace.getCtx().getSeriesDTO().getLeaderboardId(); + String leaderboardName = currentPresenter.getSeriesDTO().getLeaderboardId(); if (leaderboardName != null && !leaderboardName.isEmpty()) { EventSeriesAnalyticsDataManager eventSeriesAnalyticsManager = currentPresenter.getCtx().getAnalyticsManager(); LeaderboardPanel leaderboardPanel = eventSeriesAnalyticsManager.getLeaderboardPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEvent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEvent.java deleted file mode 100644 index a2dc99d0489..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; - -import com.google.gwt.event.shared.GwtEvent; - -public class SearchEvent extends GwtEvent { - public static Type TYPE = new Type(); - - private final String searchText; - - public SearchEvent(String searchText) { - this.searchText = searchText; - } - - public String getSearchText() { - return searchText; - } - - @Override - public Type getAssociatedType() { - return TYPE; - } - - @Override - protected void dispatch(SearchEventHandler handler) { - handler.onDoSearch(this); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEventHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEventHandler.java deleted file mode 100644 index 221d79fe94b..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchEventHandler.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; - -import com.google.gwt.event.shared.EventHandler; - -public interface SearchEventHandler extends EventHandler { - void onDoSearch(SearchEvent event); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivity.java deleted file mode 100644 index eec4e32c6ee..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivity.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; - -import com.google.gwt.activity.shared.AbstractActivity; -import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.AcceptsOneWidget; -import com.sap.sailing.gwt.home.shared.partials.placeholder.Placeholder; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; -import com.sap.sse.common.search.KeywordQuery; -import com.sap.sse.gwt.client.mvp.ErrorView; - -public class SearchResultActivity extends AbstractActivity { - private final SearchResultClientFactory clientFactory; - - private final SearchResultPlace searchResultPlace; - - private SearchResultView view; - private AcceptsOneWidget panel; - - public SearchResultActivity(SearchResultPlace place, SearchResultClientFactory clientFactory) { - this.clientFactory = clientFactory; - this.searchResultPlace = place; - - bindEvents(); - } - - private void bindEvents() { - clientFactory.getEventBus().addHandler(SearchEvent.TYPE, new SearchEventHandler() { - public void onDoSearch(SearchEvent event) { - if(view != null) { - doSearch(event.getSearchText()); - } - } - }); - } - - @Override - public void start(final AcceptsOneWidget panel, final EventBus eventBus) { - this.panel = panel; - panel.setWidget(new Placeholder()); - - view = clientFactory.createSearchResultView(); - panel.setWidget(view.asWidget()); - Window.setTitle(searchResultPlace.getTitle()); - - - doSearch(searchResultPlace.getSearchText()); - } - - protected void doSearch(final String searchText) { - if (searchText == null || searchText.isEmpty()) - return; - - final KeywordQuery searchQuery = new KeywordQuery(searchText.split("[ \t]+")); - clientFactory.getSailingService().getSearchServerNames(new AsyncCallback>() { - @Override - public void onSuccess(Iterable serverNames) { - view.initSearchResult(searchText); - searchSingleServer(searchText, searchQuery, /* null meaning the "local" server */ null); - for (String serverName : serverNames) { - searchSingleServer(searchText, searchQuery, serverName); - } - } - - @Override - public void onFailure(Throwable caught) { - Window.alert("Error: "+caught.getMessage()); - } - }); - } - - private void searchSingleServer(final String searchText, KeywordQuery searchQuery, String serverName) { - clientFactory.getSailingService().search(serverName, searchQuery, new AsyncCallback>() { - @Override - public void onSuccess(Iterable searchResults) { - view.updateSearchResult(searchText, searchResults); - } - - @Override - public void onFailure(Throwable caught) { - final ErrorView view = clientFactory.createErrorView("Error while seaching with service search()", caught); - panel.setWidget(view.asWidget()); - } - }); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultClientFactory.java deleted file mode 100644 index 96591014ed0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultClientFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; - -import com.sap.sailing.gwt.ui.client.SailingClientFactory; - -public interface SearchResultClientFactory extends SailingClientFactory { - SearchResultView createSearchResultView(); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultView.java deleted file mode 100644 index 11faf04247f..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultView.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; - -import com.google.gwt.user.client.ui.IsWidget; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; - -public interface SearchResultView extends IsWidget { - - void initSearchResult(String searchText); - - void updateSearchResult(String searchText, Iterable searchResultItems); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/TabletAndDesktopSearchResultView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/TabletAndDesktopSearchResultView.java index c9cccb3c217..90be68d6122 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/TabletAndDesktopSearchResultView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/TabletAndDesktopSearchResultView.java @@ -1,13 +1,16 @@ package com.sap.sailing.gwt.home.desktop.places.searchresult; +import java.util.Collection; + 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.Widget; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.desktop.partials.searchresult.SearchResult; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultView; public class TabletAndDesktopSearchResultView extends Composite implements SearchResultView { private static SearchResultUiBinder uiBinder = GWT.create(SearchResultUiBinder.class); @@ -23,12 +26,13 @@ public class TabletAndDesktopSearchResultView extends Composite implements Searc } @Override - public void initSearchResult(String searchText) { - searchResult.init(searchText); + public void setSearchText(String searchText) { + searchResult.setSearchText(searchText); } - + @Override - public void updateSearchResult(String searchText, Iterable searchResultItems) { + public void updateSearchResult(String searchText, Collection searchResultItems) { searchResult.updateSearchResult(searchText, searchResultItems); } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartActivity.java index 62819261076..d9b87c138fc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartActivity.java @@ -3,11 +3,12 @@ package com.sap.sailing.gwt.home.desktop.places.start; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.home.communication.start.GetStartViewAction; +import com.sap.sailing.gwt.home.communication.start.StartViewDTO; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; import com.sap.sailing.gwt.home.shared.partials.placeholder.Placeholder; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; public class StartActivity extends AbstractActivity { private final StartClientFactory clientFactory; @@ -21,14 +22,7 @@ public class StartActivity extends AbstractActivity { @Override public void start(final AcceptsOneWidget panel, EventBus eventBus) { panel.setWidget(new Placeholder()); - clientFactory.getHomeService().getStartView(new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - - } - + clientFactory.getDispatch().execute(new GetStartViewAction(), new ActivityCallback(clientFactory, panel) { @Override public void onSuccess(StartViewDTO result) { final StartView view = clientFactory.createStartView(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartClientFactory.java index b8f22d634eb..91ccb7239bd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartClientFactory.java @@ -1,7 +1,9 @@ package com.sap.sailing.gwt.home.desktop.places.start; +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; import com.sap.sailing.gwt.ui.client.SailingClientFactory; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; -public interface StartClientFactory extends SailingClientFactory { +public interface StartClientFactory extends SailingClientFactory, ErrorAndBusyClientFactory, ClientFactoryWithDispatch { StartView createStartView(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartView.java index 8575c56d7ac..667af10e33f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/StartView.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.desktop.places.start; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; +import com.sap.sailing.gwt.home.communication.start.StartViewDTO; public interface StartView { Widget asWidget(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/TabletAndDesktopStartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/TabletAndDesktopStartView.java index b7ca076c07c..788ce2cdda5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/TabletAndDesktopStartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/start/TabletAndDesktopStartView.java @@ -5,11 +5,11 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.start.StartViewDTO; import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator; import com.sap.sailing.gwt.home.desktop.partials.mainevents.MainEvents; import com.sap.sailing.gwt.home.desktop.partials.mainmedia.MainMedia; import com.sap.sailing.gwt.home.desktop.partials.stage.Stage; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; public class TabletAndDesktopStartView extends Composite implements StartView { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/MobileEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/MobileEntryPoint.java index 43d78c8a1fe..8d6007644ee 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/MobileEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/MobileEntryPoint.java @@ -1,28 +1,33 @@ package com.sap.sailing.gwt.home.mobile; +import com.google.gwt.activity.shared.ActivityManager; +import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; +import com.sap.sailing.gwt.common.client.SharedResources; import com.sap.sailing.gwt.home.mobile.app.MobileActivityMapper; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; -import com.sap.sailing.gwt.home.mobile.resources.SharedResources; import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper; +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.SailingActivityManager; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.client.ServerConfigurationService; import com.sap.sailing.gwt.ui.client.ServerConfigurationServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.gwt.client.mvp.AbstractMvpEntryPoint; +import com.sap.sse.gwt.resources.CommonControlsCSS; -public class MobileEntryPoint extends AbstractMvpEntryPoint { +public class MobileEntryPoint extends AbstractMvpEntryPoint { @Override public void doOnModuleLoad() { + Document.get().getBody().addClassName(SharedResources.INSTANCE.mainCss().mobile()); - SharedResources sRes = GWT.create(SharedResources.class); - sRes.mediaCss().ensureInjected(); - sRes.mainCss().ensureInjected(); - + CommonControlsCSS.ensureInjected(); + ServerConfigurationServiceAsync serverConfigService = GWT.create(ServerConfigurationService.class); EntryPointHelper.registerASyncService((ServiceDefTarget) serverConfigService, RemoteServiceMappingConstants.serverConfigurationServiceRemotePath); @@ -49,5 +54,12 @@ public class MobileEntryPoint extends AbstractMvpEntryPoint { protected StringMessages createStringMessages() { return GWT.create(StringMessages.class); } + + @Override + protected ActivityManager createActivityManager(ActivityMapper activityMapperRegistry, MobileApplicationClientFactory clientFactory) { + SailingActivityManager sailingActivityManager = new SailingActivityManager<>(activityMapperRegistry, clientFactory.getEventBus()); + sailingActivityManager.setNavigationPathDisplay(clientFactory.getNavigationPathDisplay()); + return sailingActivityManager; + } -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileActivityMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileActivityMapper.java index 3905ef61367..c62dc9e6806 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileActivityMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileActivityMapper.java @@ -4,6 +4,7 @@ import com.google.gwt.activity.shared.Activity; import com.google.gwt.activity.shared.ActivityMapper; import com.google.gwt.core.client.GWT; import com.google.gwt.place.shared.Place; +import com.sap.sailing.gwt.home.mobile.places.error.ErrorActivityProxy; import com.sap.sailing.gwt.home.mobile.places.event.EventActivityProxy; import com.sap.sailing.gwt.home.mobile.places.events.EventsActivityProxy; import com.sap.sailing.gwt.home.mobile.places.series.SeriesActivityProxy; @@ -13,9 +14,12 @@ import com.sap.sailing.gwt.home.mobile.places.solutions.SolutionsActivityProxy; import com.sap.sailing.gwt.home.mobile.places.start.StartActivityProxy; import com.sap.sailing.gwt.home.shared.SwitchingEntryPoint; import com.sap.sailing.gwt.home.shared.app.ApplicationPlaceUpdater; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultActivityProxy; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; @@ -36,7 +40,9 @@ public class MobileActivityMapper implements ActivityMapper { SwitchingEntryPoint.reloadApp(); return null; } - if (place instanceof StartPlace) { + if (place instanceof ErrorPlace) { + return new ErrorActivityProxy((ErrorPlace) place, clientFactory); + } else if (place instanceof StartPlace) { return new StartActivityProxy((StartPlace) place, clientFactory); } else if (place instanceof EventsPlace) { return new EventsActivityProxy((EventsPlace) place, clientFactory); @@ -46,6 +52,8 @@ public class MobileActivityMapper implements ActivityMapper { return new SeriesMiniOverallLeaderboardActivityProxy((SeriesMiniOverallLeaderboardPlace) place, clientFactory); } else if (place instanceof AbstractSeriesPlace) { return new SeriesActivityProxy((AbstractSeriesPlace) place, clientFactory); + } else if (place instanceof SearchResultPlace) { + return new SearchResultActivityProxy((SearchResultPlace) place, clientFactory); } else if (place instanceof SolutionsPlace) { return new SolutionsActivityProxy((SolutionsPlace) place, clientFactory); } else { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationClientFactory.java old mode 100755 new mode 100644 index 7c309a3568d..dba888ddab4 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationClientFactory.java @@ -1,19 +1,22 @@ package com.sap.sailing.gwt.home.mobile.app; -import com.google.gwt.core.client.GWT; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceController; -import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.web.bindery.event.shared.EventBus; import com.google.web.bindery.event.shared.SimpleEventBus; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystemImpl; import com.sap.sailing.gwt.home.desktop.app.ApplicationTopLevelView; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystemImpl; +import com.sap.sailing.gwt.home.mobile.places.error.ErrorViewImpl; +import com.sap.sailing.gwt.home.mobile.places.searchresult.SearchResultViewImpl; +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.partials.busy.BusyViewImpl; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultClientFactory; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultView; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.client.HomeService; -import com.sap.sailing.gwt.ui.client.HomeServiceAsync; -import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; -import com.sap.sse.gwt.client.EntryPointHelper; +import com.sap.sailing.gwt.ui.client.refresh.BusyView; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; +import com.sap.sse.gwt.client.mvp.ErrorView; import com.sap.sse.security.ui.client.SecureClientFactoryImpl; /** @@ -21,10 +24,9 @@ import com.sap.sse.security.ui.client.SecureClientFactoryImpl; * @author pgtaboada * */ -public class MobileApplicationClientFactory extends SecureClientFactoryImpl { - private final HomeServiceAsync homeService; +public class MobileApplicationClientFactory extends SecureClientFactoryImpl> implements ErrorAndBusyClientFactory, SearchResultClientFactory { private final MobilePlacesNavigator navigator; - private final DispatchSystem dispatch = new DispatchSystemImpl(); + private final SailingDispatchSystem dispatch = new SailingDispatchSystemImpl(); public MobileApplicationClientFactory(boolean isStandaloneServer) { this(new SimpleEventBus(), isStandaloneServer); @@ -42,23 +44,17 @@ public class MobileApplicationClientFactory extends SecureClientFactoryImpl { this(new MobileApplicationView(navigator, eventBus), eventBus, placeController, navigator); } - public MobileApplicationClientFactory(ApplicationTopLevelView root, EventBus eventBus, + public MobileApplicationClientFactory(MobileApplicationView root, EventBus eventBus, PlaceController placeController, final MobilePlacesNavigator navigator) { super(root, eventBus, placeController); this.navigator = navigator; - this.homeService = GWT.create(HomeService.class); - EntryPointHelper.registerASyncService((ServiceDefTarget) homeService, RemoteServiceMappingConstants.homeServiceRemotePath); } public MobilePlacesNavigator getNavigator() { return navigator; } - public HomeServiceAsync getHomeService() { - return homeService; - } - - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return dispatch; } @@ -66,4 +62,23 @@ public class MobileApplicationClientFactory extends SecureClientFactoryImpl { public Place getDefaultPlace() { return new StartPlace(); } + + @Override + public BusyView createBusyView() { + return new BusyViewImpl(); + } + + @Override + public ErrorView createErrorView(final String errorMessage, final Throwable errorReason) { + return new ErrorViewImpl(errorMessage, errorReason, null); + } + + @Override + public SearchResultView createSearchResultView() { + return new SearchResultViewImpl(navigator); + } + + public ResettableNavigationPathDisplay getNavigationPathDisplay() { + return getTopLevelView().getNavigationPathDisplay(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.java index cd20074b22c..66bc213a76d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.java @@ -14,6 +14,7 @@ import com.sap.sailing.gwt.home.desktop.app.ApplicationTopLevelView; import com.sap.sailing.gwt.home.mobile.partials.footer.Footer; import com.sap.sailing.gwt.home.mobile.partials.header.Header; import com.sap.sailing.gwt.home.shared.app.HasLocationTitle; +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.DefaultErrorReporter; import com.sap.sse.gwt.client.ErrorReporter; @@ -22,7 +23,7 @@ import com.sap.sse.gwt.client.ErrorReporter; * This is the top-level view of the application. Every time another presenter wants to reveal itself, * {@link MobileApplicationView} will add its content of the target inside the {@code mainContantPanel}. */ -public class MobileApplicationView extends Composite implements ApplicationTopLevelView { +public class MobileApplicationView extends Composite implements ApplicationTopLevelView { interface MyBinder extends UiBinder { } @@ -68,4 +69,9 @@ public class MobileApplicationView extends Composite implements ApplicationTopLe public ErrorReporter getErrorReporter() { return errorReporter; } + + @Override + public ResettableNavigationPathDisplay getNavigationPathDisplay() { + return headerPanel.getNavigationPathDisplay(); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.ui.xml index 1b41ab48322..b965d5be933 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobileApplicationView.ui.xml @@ -4,7 +4,7 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.mobile.partials" > + type="com.sap.sailing.gwt.common.client.SharedResources" /> .mainContent { height: 100%; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobilePlacesNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobilePlacesNavigator.java index 4aa8f82b747..ffa27130262 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobilePlacesNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/app/MobilePlacesNavigator.java @@ -3,9 +3,10 @@ package com.sap.sailing.gwt.home.mobile.app; import java.util.List; import com.google.gwt.place.shared.PlaceController; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.desktop.places.aboutus.AboutUsPlace; import com.sap.sailing.gwt.home.desktop.places.contact.ContactPlace; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultPlace; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; 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.mobile.places.event.latestnews.LatestNewsPlace; @@ -20,7 +21,6 @@ import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace.SolutionsNavigationTabs; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public class MobilePlacesNavigator extends AbstractPlaceNavigator { @@ -82,7 +82,8 @@ public class MobilePlacesNavigator extends AbstractPlaceNavigator { return createGlobalPlaceNavigation(new ContactPlace()); } - public PlaceNavigation getSearchResultNavigation(String searchQuery) { - return createGlobalPlaceNavigation(new SearchResultPlace(searchQuery)); + public PlaceNavigation getRegattaOverviewNavigation(String eventId, String leaderboardName, String baseUrl, + boolean isOnRemoteServer) { + return createPlaceNavigation(baseUrl, isOnRemoteServer, new RegattaOverviewPlace(eventId, leaderboardName)); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.java index 6e874ad0d97..1bff4eca105 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.java @@ -9,11 +9,11 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.home.shared.utils.LogoUtil; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; public class EventHeader extends Composite { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.ui.xml index e6fa3e1d129..83a144039e9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventheader/EventHeader.ui.xml @@ -3,7 +3,7 @@ xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"> - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.java index c57280712bf..98147f02cdf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.java @@ -4,12 +4,12 @@ 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.sap.sailing.gwt.home.communication.regatta.RegattaProgressSeriesDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressSeriesDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; public class EventSteps extends Composite implements RefreshableWidget { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.ui.xml index f8670cbae91..cc50f299eb4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventSteps.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.java index ca0a233e37f..058d4bd75b9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.java @@ -13,10 +13,10 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaProgressFleetDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaProgressSeriesDTO; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressFleetDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressSeriesDTO; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; public class EventStepsPhase extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.ui.xml index 5305dfde6a4..a2555bf8c5c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhase.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhaseFleet.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhaseFleet.ui.xml index b60b3f3153c..2f8cb6588f7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhaseFleet.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/eventsteps/EventStepsPhaseFleet.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/footer/Footer.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/footer/Footer.ui.xml index d15e5dda458..f0927400f74 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/footer/Footer.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/footer/Footer.ui.xml @@ -4,7 +4,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.gss index 27329d63d89..8be8070ff78 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.gss @@ -121,6 +121,30 @@ img.header_logo_image { text-transform: uppercase; padding: 1.333333333333333em 1em; } +.header_navigation_nav_sublist_item { + position: relative; + display: block; +} +.header_navigation_nav_sublist_item > .header_navigation_nav_list_item { + text-transform: none; + padding: 1em; +} +.header_navigation_nav_sublist_item:first-child:before { + background: none; +} +.header_navigation_nav_sublist_item:before { + background: url('images/home/arrow-down-grey.png'); + display: block; + height: 25px; + background-position: center; + background-repeat: no-repeat; + background-size: contain; + content: ''; + position: absolute; + top: -10px; + left: 0; + right: 0; +} .header_navigation_icon { position: absolute; top: 50%; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.java index 77fea7346af..7821f05354f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.java @@ -4,6 +4,7 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Element; 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.ClickHandler; import com.google.gwt.uibinder.client.UiBinder; @@ -16,7 +17,9 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; import com.sap.sailing.gwt.common.client.i18n.TextMessages; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay; import com.sap.sailing.gwt.home.shared.utils.DropdownHandler; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -25,13 +28,17 @@ public class Header extends Composite { // @UiField TextBox searchText; // @UiField Button searchButton; + @UiField HeaderResources local_res; @UiField ImageElement dropdownTriggerUi; @UiField Element dropdownContainerUi; @UiField FlowPanel dropdownListUi; + @UiField FlowPanel dropdownListExtUi; @UiField Element searchUi; @UiField DivElement locationTitleUi; + + private final ResettableNavigationPathDisplay navigationPathDisplay; interface HeaderUiBinder extends UiBinder { } @@ -40,14 +47,16 @@ public class Header extends Composite { private DropdownHandler dropdownHandler; public Header(final MobilePlacesNavigator placeNavigator) { - HeaderResources.INSTANCE.css().ensureInjected(); - initWidget(uiBinder.createAndBindUi(this)); + local_res.css().ensureInjected(); + + dropdownListExtUi.getElement().getStyle().setDisplay(Display.NONE); + navigationPathDisplay = new DropdownNavigationPathDisplay(); addNavigation(placeNavigator.getHomeNavigation(), StringMessages.INSTANCE.home()); addNavigation(placeNavigator.getEventsNavigation(), StringMessages.INSTANCE.events()); addNavigation(placeNavigator.getSolutionsNavigation(), TextMessages.INSTANCE.solutions()); - + addUrl("http://blog.sapsailing.com", TextMessages.INSTANCE.blog()); dropdownHandler = new DropdownHandler(dropdownTriggerUi, dropdownContainerUi); Event.sinkEvents(searchUi, Event.ONCLICK); @@ -63,10 +72,13 @@ public class Header extends Composite { }); } + public ResettableNavigationPathDisplay getNavigationPathDisplay() { + return navigationPathDisplay; + } + private void addNavigation(final PlaceNavigation placeNavigation, String name) { HeaderNavigationItem navigationItem = new HeaderNavigationItem(name, placeNavigation.getTargetUrl()); navigationItem.addClickHandler(new ClickHandler() { - @Override public void onClick(ClickEvent event) { if(LinkUtil.handleLinkClick(event.getNativeEvent().cast())) { @@ -79,7 +91,44 @@ public class Header extends Composite { dropdownListUi.add(navigationItem); } + private void addUrl(String url, String name) { + HeaderNavigationItem navigationItem = new HeaderNavigationItem(name, url); + dropdownListUi.add(navigationItem); + } + public void setLocationTitle(String locationTitle) { locationTitleUi.setInnerText(locationTitle); } + + private class DropdownNavigationPathDisplay implements ResettableNavigationPathDisplay { + @Override + public void showNavigationPath(NavigationItem... navigationPath) { + dropdownListExtUi.clear(); + if(ExperimentalFeatures.USE_NAVIGATION_PATH_DISPLAY_ON_MOBILE) { + for (final NavigationItem navigationItem : navigationPath) { + HeaderNavigationItem headerNavItem = new HeaderNavigationItem(navigationItem.getDisplayName(), navigationItem.getTargetUrl()); + headerNavItem.addStyleName(local_res.css().header_navigation_nav_sublist_item()); + headerNavItem.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + if(LinkUtil.handleLinkClick(event.getNativeEvent().cast())) { + event.preventDefault(); + navigationItem.run(); + dropdownHandler.setVisible(false); + } + } + }); + dropdownListExtUi.add(headerNavItem); + } + dropdownListExtUi.getElement().getStyle().clearDisplay(); + } + } + + @Override + public void reset() { + dropdownListExtUi.clear(); + dropdownListExtUi.getElement().getStyle().setDisplay(Display.NONE); + } + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.ui.xml index 7d9cbfa60e1..c6738b9daf6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/Header.ui.xml @@ -6,9 +6,14 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> + + .dropdownListExt { + border-top: 1px solid gray; + } +
@@ -21,6 +26,7 @@
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.java index 2f83557f135..084bb9ee21e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.java @@ -21,7 +21,6 @@ public class HeaderNavigationItem extends Widget implements HasClickHandlers { } private static HeaderUiBinder uiBinder = GWT.create(HeaderUiBinder.class); - public HeaderNavigationItem(String linkText, String link) { setElement(uiBinder.createAndBindUi(this)); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.ui.xml index 1948b1b78d9..65406d81886 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderNavigationItem.ui.xml @@ -4,7 +4,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderResources.java index d64dca1e667..568e66c5f92 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/header/HeaderResources.java @@ -28,5 +28,6 @@ public interface HeaderResources extends ClientBundle { String header_navigation_nav_list(); String header_navigation_nav_list_item(); String header_navigation_icon(); + String header_navigation_nav_sublist_item(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.java index a6cf64e8ba7..ef369691cdf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.java @@ -9,10 +9,10 @@ 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.FlowPanel; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; public class ImageGallery extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.ui.xml index d6a9176f972..b467bf7ec8d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGallery.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGalleryItem.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGalleryItem.ui.xml index 28a55b5b3e8..425707e41e2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGalleryItem.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/ImageGalleryItem.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.java index d6021e09f51..81647b4d2ce 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.java @@ -19,11 +19,13 @@ import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.LayoutPanel; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimpleLayoutPanel; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sse.gwt.client.controls.carousel.ImageCarousel.FullscreenViewer; public class MobileFullscreenGallery implements FullscreenViewer{ @@ -36,17 +38,21 @@ public class MobileFullscreenGallery implements FullscreenViewer handler) { return popup.addCloseHandler(handler); } @Override public void show(SailingImageDTO selectedImage, Collection imageList) { - contentUi.setWidget(new MobileGalleryPlayer(selectedImage, imageList)); + contentUi.setWidget(playerUi = new MobileGalleryPlayer(selectedImage, imageList)); + autoplayActionUi.setStyleName(style.is_autoplaying(), playerUi.isAutoplaying()); contentUi.getWidget().getElement().addClassName(style.content()); mainPanel.onResize(); popup.showPopupPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.ui.xml index c2ceccc15b7..a3d8c6a0ab8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileFullscreenGallery.ui.xml @@ -12,7 +12,10 @@ background-color: rgba(0,0,0,0.9); z-index: 5; } - .closeAction { + .actionContainer { + text-align: right; + } + .action { height: 50px; width: auto; cursor: pointer; @@ -25,13 +28,19 @@ .content { overflow: auto !important; } + .is_autoplaying { + background-color: #f0ab00; + } - - + + + + +
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileGalleryPlayer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileGalleryPlayer.java index 1a10fcb7d72..290bb376020 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileGalleryPlayer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/imagegallery/MobileGalleryPlayer.java @@ -24,6 +24,7 @@ public class MobileGalleryPlayer extends ResizeComposite { @UiField DivElement mainSliderUi; private int selectedIdx; + private boolean autoplay; public MobileGalleryPlayer(ImageDTO selected, Collection images) { initWidget(uiBinder.createAndBindUi(this)); @@ -83,4 +84,27 @@ public class MobileGalleryPlayer extends ResizeComposite { adaptiveHeight : false, }); }-*/; + + private native void _slickPlay() /*-{ + $wnd.$('.mainSlider').slick('slickPlay').slick('slickNext').slick( + 'setOption', 'autoplay', true); // workaround for bug https://github.com/kenwheeler/slick/issues/1446 + }-*/; + + private native void _slickPause() /*-{ + $wnd.$('.mainSlider').slick('slickPause').slick('setOption', + 'autoplay', false); // workaround for bug https://github.com/kenwheeler/slick/issues/1446 + }-*/; + + public void toggleAutoplay() { + autoplay = !autoplay; + if (autoplay) { + _slickPlay(); + } else { + _slickPause(); + } + } + + public boolean isAutoplaying() { + return autoplay; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.java index efa31402e6a..67b8729ade3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.java @@ -7,13 +7,13 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; import com.sap.sailing.gwt.home.mobile.partials.imagegallery.MobileFullscreenGallery; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.mobile.partials.statisticsBox.StatisticsBoxResources; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; import com.sap.sse.gwt.client.controls.carousel.ImageCarousel; public class Impressions extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.ui.xml index bfdea77bf93..d5cae76cea2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/impressions/Impressions.ui.xml @@ -3,7 +3,7 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials"> - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.java index 1e819d3c9e9..82998e84b33 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.java @@ -4,14 +4,14 @@ import com.google.gwt.core.shared.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.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; import com.sap.sailing.gwt.home.mobile.partials.regattaStatus.RegattaStatusRace; import com.sap.sailing.gwt.home.mobile.partials.regattaStatus.RegattaStatusResources; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO; public class RegattaLiveRaces extends Composite implements RefreshableWidget> { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.ui.xml index 4d4c4a0e0a4..fef29081911 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/liveraces/RegattaLiveRaces.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBox.java index 63ca4b7e0eb..9d40f184d26 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBox.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBox.java @@ -10,15 +10,15 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.LabelType; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderboardDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.MiniLeaderboardItemDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderboardDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.MiniLeaderboardItemDTO; -import com.sap.sailing.gwt.ui.shared.general.LabelType; public class MinileaderboardBox extends Composite implements RefreshableWidget { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @@ -31,13 +31,10 @@ public class MinileaderboardBox extends Composite implements RefreshableWidget placeNavigation) { @@ -45,21 +42,15 @@ public class MinileaderboardBox extends Composite implements RefreshableWidget - + .minileaderboard_item { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBoxItemLegend.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBoxItemLegend.ui.xml index 64f0bded71d..05296485afc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBoxItemLegend.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/minileaderboard/MinileaderboardBoxItemLegend.ui.xml @@ -2,7 +2,7 @@ - + .minileaderboard_item_legend { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/quickfinder/Quickfinder.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/quickfinder/Quickfinder.ui.xml index 921724a84a1..b99621bdb0b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/quickfinder/Quickfinder.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/quickfinder/Quickfinder.ui.xml @@ -1,6 +1,6 @@ - + .quickfinder { font-size: 1rem; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.java index bd0f0174647..5cabac588de 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.java @@ -6,9 +6,9 @@ import com.google.gwt.dom.client.DivElement; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; public class EventOverviewRecentSeriesInfo extends UIObject { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.ui.xml index 3661c9f72ad..5c471590b66 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventOverviewRecentSeriesInfo.ui.xml @@ -1,7 +1,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.java index 2d7cebf2f0c..1264ea85478 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.java @@ -9,9 +9,9 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListYearDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListYearDTO; public class EventsOverviewRecent extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.ui.xml index eabd41f6a39..fd5de589a47 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecent.ui.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.java index 65d74003440..4c2c82882bd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.java @@ -13,14 +13,14 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListYearDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.mobile.partials.stage.Stage; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListYearDTO; public class EventsOverviewRecentYear extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.ui.xml index 6a722f710aa..a50d8348c0e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/recents/EventsOverviewRecentYear.ui.xml @@ -2,7 +2,7 @@ - + + type="com.sap.sailing.gwt.common.client.SharedResources" />
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.java index 0859ddf6c5a..ca311b72ff2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.java @@ -1,5 +1,7 @@ package com.sap.sailing.gwt.home.mobile.partials.regattaStatus; +import java.util.HashMap; +import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -8,18 +10,21 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; +import com.sap.sailing.gwt.home.communication.event.RegattasAndLiveRacesDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; +import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.mobile.partials.toggleButton.ToggleButton; import com.sap.sailing.gwt.home.mobile.partials.toggleButton.ToggleButton.ToggleButtonCommand; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase.Presenter; import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.partials.filter.AbstractSelectionFilter; +import com.sap.sailing.gwt.home.shared.partials.regattalist.RegattaListView; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; -import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RegattasAndLiveRacesDTO; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -public class RegattaStatus extends Composite implements RefreshableWidget { +public class RegattaStatus extends Composite implements RefreshableWidget, RegattaListView { private static final String TOGGLEHIDDEN_STYLE = RegattaStatusResources.INSTANCE.css().togglecontainerhidden(); private static RegattaStatusUiBinder uiBinder = GWT.create(RegattaStatusUiBinder.class); @@ -27,11 +32,13 @@ public class RegattaStatus extends Composite implements RefreshableWidget { } + @UiField SectionHeaderContent sectionHeaderUi; @UiField MobileSection regattaContainerUi; @UiField MobileSection collapsableContainerUi; @UiField(provided = true) ToggleButton toggleButtonUi; private final Presenter presenter; // private CollapseAnimation animation; + private final Map stucture = new HashMap<>(); public RegattaStatus(Presenter presenter) { this.presenter = presenter; @@ -48,8 +55,13 @@ public class RegattaStatus extends Composite implements RefreshableWidget filterWidget) { + sectionHeaderUi.initFilterSelectUi(filterWidget); + } + @Override public void setData(RegattasAndLiveRacesDTO data) { + stucture.clear(); regattaContainerUi.clearContent(); collapsableContainerUi.clearContent(); if (data.hasRegattasWithRaces()) { @@ -69,7 +81,13 @@ public class RegattaStatus extends Composite implements RefreshableWidget getItemMap() { + return stucture; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.ui.xml index ef98ee0921d..671ce08af18 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatus.ui.xml @@ -2,13 +2,13 @@ - + - + @@ -19,4 +19,4 @@ - \ No newline at end of file + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.java index af58dec11c4..f8b4c5a22bc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.java @@ -9,14 +9,14 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; +import com.sap.sailing.gwt.home.communication.race.FlagStateDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.RaceProgressDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.shared.utils.HomeSailingFlagsBuilder; import com.sap.sailing.gwt.regattaoverview.client.FlagsMeaningExplanator; -import com.sap.sailing.gwt.regattaoverview.client.SailingFlagsBuilder; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO; -import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.RaceProgressDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceViewState; import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaStatusRace extends Composite { @@ -52,7 +52,7 @@ public class RegattaStatusRace extends Composite { private void initRaceFlagInfo(FlagStateDTO value) { if (value != null) { - raceFlagContainerUi.setInnerSafeHtml(SailingFlagsBuilder.render(value, 0.40, FlagsMeaningExplanator + raceFlagContainerUi.setInnerSafeHtml(HomeSailingFlagsBuilder.render(value, 0.40, FlagsMeaningExplanator .getFlagsMeaning(I18N, value.getLastUpperFlag(), value.getLastLowerFlag(), value.isLastFlagsAreDisplayed()))); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.ui.xml index 178e02cf6fc..cab25b6e7d6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRace.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.java index 2be637a8ba9..2577cdf31eb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.java @@ -10,15 +10,16 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.BoatClassImageResolver; import com.sap.sailing.gwt.common.client.BoatClassImageResources; +import com.sap.sailing.gwt.home.communication.event.LabelType; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; import com.sap.sailing.gwt.home.mobile.partials.section.IsMobileSection; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.ui.shared.dispatch.event.LiveRaceDTO; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.LabelType; +import com.sap.sailing.gwt.home.shared.partials.regattalist.RegattaListView.RegattaListItem; -public class RegattaStatusRegatta extends Composite implements IsMobileSection { +public class RegattaStatusRegatta extends Composite implements IsMobileSection, RegattaListItem { private static RegattaStatusRegattaUiBinder uiBinder = GWT.create(RegattaStatusRegattaUiBinder.class); @@ -61,4 +62,9 @@ public class RegattaStatusRegatta extends Composite implements IsMobileSection { return BoatClassImageResources.INSTANCE.genericBoatClass(); } + @Override + public void doFilter(boolean filter) { + setVisible(!filter); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.ui.xml index 4bdf6ac45a4..0fd7f80c7e2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattaStatus/RegattaStatusRegatta.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.gss index 9c59c4c2d67..3bb25afadfa 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.gss @@ -52,6 +52,8 @@ position: absolute; top: 50%; left: 1.133333333333333em; + right: 2.133333333333333em; + text-align: left; -webkit-transform: translateY(-50%); -moz-transform: translateY(-50%); -ms-transform: translateY(-50%); @@ -105,6 +107,7 @@ } .regattacompetition_phase_fleet_raceplanned { background-color: #999; + font-style: italic; } .regattacompetition_phase_fleet_raceplanned .regattacompetition_phase_fleet_race_title:after { display: none; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.java index 20ae2598711..45a344513b3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.java @@ -6,13 +6,10 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.home.mobile.places.event.races.RacesView.Presenter; -import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceCompetitionFormatFleetDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView; -public class RegattaCompetition extends Composite implements RefreshableWidget> { +public class RegattaCompetition extends Composite implements RegattaCompetitionView { private static RegattaCompetitionUiBinder uiBinder = GWT.create(RegattaCompetitionUiBinder.class); @@ -20,25 +17,22 @@ public class RegattaCompetition extends Composite implements RefreshableWidget data) { + public void clearContent() { regattaSeriesContainerUi.clear(); - for (RaceCompetitionFormatSeriesDTO series : data.getValues()) { - RegattaCompetitionSeries regattaCompetitionSeries = new RegattaCompetitionSeries(series); - int fleetCount = series.getFleets().size(); - for (RaceCompetitionFormatFleetDTO fleet : series.getFleets()) { - regattaCompetitionSeries.addFleet(presenter, fleet, fleetCount); - } - regattaSeriesContainerUi.add(regattaCompetitionSeries); - } + } + + @Override + public RegattaCompetitionSeriesView addSeriesView(RaceCompetitionFormatSeriesDTO series) { + RegattaCompetitionSeries seriesView = new RegattaCompetitionSeries(series); + regattaSeriesContainerUi.add(seriesView); + return seriesView; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.ui.xml index cc58550dec1..fc9df6a4a63 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetition.ui.xml @@ -2,7 +2,7 @@ - + { } - private static final LocalCss CSS = RegattaCompetitionResources.INSTANCE.css(); - - @UiField DivElement raceContainerUi; + @UiField RegattaCompetitionResources local_res; @UiField DivElement fleetCornerUi; @UiField DivElement fleetNameUi; + @UiField DivElement raceContainerUi; + + public RegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet) { + super(fleet); + } + + @Override + public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, String raceViewerUrl) { + RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, raceViewerUrl); + raceContainerUi.appendChild(raceView.getElement()); + return raceView; + } - public RegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet, int fleetCount) { - setElement(uiBinder.createAndBindUi(this)); + @Override + public void setNumberOfFleetsInSeries(int fleetCount) { raceContainerUi.getStyle().setWidth(100.0 / fleetCount, Unit.PCT); - if (fleetCount < 2) raceContainerUi.addClassName(CSS.regattacompetition_phase_fleetfullwidth()); - fleetCornerUi.getStyle().setProperty("borderTopColor", fleet.getFleet().getFleetColor()); - fleetNameUi.setInnerText(fleet.getFleet().getFleetName()); - if (fleet.getFleet().isDefaultFleet()) { - fleetCornerUi.removeFromParent(); - fleetNameUi.removeFromParent(); - } else { - raceContainerUi.getStyle().setBackgroundColor(getBackgroundColor(fleet.getFleet())); - } + setStyleName(raceContainerUi, local_res.css().regattacompetition_phase_fleetfullwidth(), fleetCount < 2); } - - public void addRace(SimpleRaceMetadataDTO race, String raceViewerUrl) { - RegattaCompetitionFleetRace fleetRace = new RegattaCompetitionFleetRace(race, raceViewerUrl); - raceContainerUi.appendChild(fleetRace.getElement()); + + @Override + protected void onDefaultFleetName() { + fleetCornerUi.removeFromParent(); + fleetNameUi.removeFromParent(); } - - private String getBackgroundColor(FleetMetadataDTO fleet) { - Triple rgbValues = new RGBColor(fleet.getFleetColor()).getAsRGB(); - return "rgba(" + rgbValues.getA() + "," + rgbValues.getB() + "," + rgbValues.getC() + ", 0.1)"; + + @Override + protected Element getMainUiElement() { + return uiBinder.createAndBindUi(this); + } + + @Override + protected Element getFleetNameUiElement() { + return fleetNameUi; + } + + @Override + protected Element getFleetCornerUiElement() { + return fleetCornerUi; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleet.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleet.ui.xml index 64fc15b586c..da56516144c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleet.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleet.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.java index 22e163e303b..ac33ab3e8e1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.java @@ -3,16 +3,16 @@ package com.sap.sailing.gwt.home.mobile.partials.regattacompetition; 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.Element; +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.ui.UIObject; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceTrackingState; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionFleetRace; -public class RegattaCompetitionFleetRace extends UIObject { +public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleetRace { private static RegattaCompetitionFleetRaceUiBinder uiBinder = GWT.create(RegattaCompetitionFleetRaceUiBinder.class); @@ -20,37 +20,57 @@ public class RegattaCompetitionFleetRace extends UIObject { } @UiField RegattaCompetitionResources local_res; - @UiField StringMessages i18n; @UiField DivElement raceNameUi; - @UiField DivElement raceDateUi; @UiField DivElement raceStateUi; - private final AnchorElement anchor; + @UiField DivElement raceDateUi; public RegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, String raceViewerUrl) { - setElement(anchor = uiBinder.createAndBindUi(this)); - if (raceViewerUrl != null) this.anchor.setHref(raceViewerUrl); - local_res.css().ensureInjected(); - setupRaceState(race.getTrackingState(), race.getViewState()); - this.raceNameUi.setInnerText(race.getRaceName()); - if (race.getStart() != null) { - this.raceDateUi.setInnerText(DateAndTimeFormatterUtil.weekdayMonthAbbrDayDateFormatter.render(race.getStart())); - } - } - - private void setupRaceState(RaceTrackingState trackingState, RaceViewState viewState) { - // TODO: As long as there is no mobile race viewer, show all races as untracked - boolean isUntrackedRace = true; - // boolean isUntrackedRace = trackingState != RaceTrackingState.TRACKED_VALID_DATA; - if (viewState == RaceViewState.RUNNING) { - anchor.addClassName(local_res.css().regattacompetition_phase_fleet_racelive()); - raceStateUi.setInnerText(isUntrackedRace ? i18n.live() : i18n.actionWatch()); - } else if (viewState == RaceViewState.PLANNED || viewState == RaceViewState.SCHEDULED) { - anchor.addClassName(local_res.css().regattacompetition_phase_fleet_raceplanned()); - raceStateUi.setInnerText(i18n.raceIsPlanned()); - } else { - raceStateUi.setInnerText(isUntrackedRace ? i18n.finished() : i18n.actionAnalyze()); - } - setStyleName(anchor, local_res.css().regattacompetition_phase_fleet_raceuntracked(), true); + super(race, raceViewerUrl); } + @Override + public void doFilter(boolean filter) { + getElement().getStyle().setDisplay(filter ? Display.NONE : Display.BLOCK); + } + + @Override + protected AnchorElement getMainUiElement() { + return uiBinder.createAndBindUi(this); + } + + @Override + protected Element getRaceNameUiElement() { + return raceNameUi; + } + + @Override + protected Element getRaceStateUiElement() { + return raceStateUi; + } + + @Override + protected Element getRaceDateUiElement() { + return raceDateUi; + } + + @Override + protected String getRaceLiveStyleName() { + return local_res.css().regattacompetition_phase_fleet_racelive(); + } + + @Override + protected String getRacePlannedStyleName() { + return local_res.css().regattacompetition_phase_fleet_raceplanned(); + } + + @Override + protected String getRaceUntrackedStyleName() { + return local_res.css().regattacompetition_phase_fleet_raceuntracked(); + } + + @Override + protected boolean isUntrackedRace(RaceTrackingState trackingState) { + return super.isUntrackedRace(trackingState) || !ExperimentalFeatures.ENABLE_RACE_VIEWER_LINK_ON_MOBILE; + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.ui.xml index 549780f5151..209cb78dcf5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionFleetRace.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.java index 57962e1d7a0..8dfb1b70865 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.java @@ -1,62 +1,56 @@ package com.sap.sailing.gwt.home.mobile.partials.regattacompetition; -import static com.sap.sailing.domain.common.LeaderboardNameConstants.DEFAULT_SERIES_NAME; - 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.FlowPanel; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; -import com.sap.sailing.gwt.home.mobile.places.event.races.RacesView.Presenter; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceCompetitionFormatFleetDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.RaceCompetitionFormatSeriesDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.AbstractRegattaCompetitionSeries; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionFleetView; -public class RegattaCompetitionSeries extends Composite { +public class RegattaCompetitionSeries extends AbstractRegattaCompetitionSeries { private static RegattaCompetitionSeriesUiBinder uiBinder = GWT.create(RegattaCompetitionSeriesUiBinder.class); interface RegattaCompetitionSeriesUiBinder extends UiBinder { } - private static final StringMessages I18N = StringMessages.INSTANCE; - @UiField SectionHeaderContent sectionHeaderUi; @UiField FlowPanel fleetContainerUi; - private final MobileSection seriesUi; + @UiField MobileSection seriesUi; public RegattaCompetitionSeries(RaceCompetitionFormatSeriesDTO series) { - initWidget(seriesUi = uiBinder.createAndBindUi(this)); + super(series); seriesUi.setEdgeToEdgeContent(true); - sectionHeaderUi.setSectionTitle(DEFAULT_SERIES_NAME.equals(series.getSeriesName()) ? I18N.races() : series.getSeriesName()); - initSubtitle(series.getCompetitorCount(), series.getFlightCount(), series.getRaceCount()); sectionHeaderUi.initCollapsibility(fleetContainerUi.getElement(), true); } - private void initSubtitle(int competitorCount, int flightCount, int raceCount) { - boolean showFlights = flightCount > 0 && flightCount != raceCount; - if (competitorCount > 0 || showFlights || raceCount > 0) { - String competitors = competitorCount > 0 ? I18N.competitorsCount(competitorCount) : ""; - String competitorsSeparator = competitorCount > 0 ? " | " : ""; - String flights = showFlights ? I18N.flightsCount(flightCount) : ""; - String flightsSeparator = showFlights ? " | " : ""; - String races = raceCount > 0 ? I18N.racesCount(raceCount) : ""; - sectionHeaderUi.setSubtitle(competitors + competitorsSeparator + flights + flightsSeparator + races); - } - } - - public void addFleet(Presenter presenter, RaceCompetitionFormatFleetDTO fleet, int fleetCount) { - RegattaCompetitionFleet competitionFleet = new RegattaCompetitionFleet(fleet, fleetCount); - for (SimpleRaceMetadataDTO race : fleet.getRaces()) { - boolean tracked = race.getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA; - String raceViewerUrl = tracked ? null : null; // TODO No mobile "RaceViewer implemented yet - competitionFleet.addRace(race, raceViewerUrl); - } - fleetContainerUi.add(competitionFleet); + @Override + public RegattaCompetitionFleetView addFleetView(RaceCompetitionFormatFleetDTO fleet) { + RegattaCompetitionFleet fleetView = new RegattaCompetitionFleet(fleet); + fleetContainerUi.add(fleetView); + return fleetView; } + @Override + protected Widget getMainUiWidget() { + return uiBinder.createAndBindUi(this); + } + + @Override + protected void setSeriesName(String seriesName) { + sectionHeaderUi.setSectionTitle(seriesName); + } + + @Override + protected void setRacesFlightAndCompetitorInfo(String flightInfoText, String raceInfoText, String competitorInfoText) { + String competitorsSeparator = competitorInfoText.isEmpty() ? "" : " | "; + String flightSeparator = flightInfoText.isEmpty() ? "" : " | "; + sectionHeaderUi.setSubtitle(competitorInfoText + competitorsSeparator + flightInfoText + flightSeparator + raceInfoText); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.ui.xml index ddf38c500ee..9315157ca5d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/regattacompetition/RegattaCompetitionSeries.ui.xml @@ -2,9 +2,9 @@ - + - + @@ -12,4 +12,4 @@ - \ No newline at end of file + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.gss new file mode 100644 index 00000000000..82a54d160c1 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.gss @@ -0,0 +1,91 @@ +.searchresult { + font-size: 1rem; +} +.searchresult_header { + background: #f2f2f2; + margin: 0; + padding: 0; +} +.searchresult_header_form { + height: 100%; +} +.searchresult_header_form_label { + display: block; + font-size: 1.2em; + padding: 0 0.833333333333333em; + margin: 1.111111111111111em 0; + font-weight: 700; + color: #0a0a0a; +} +.searchresult_header_form_inputwrapper { + padding: 0.333333333333333em; +} +.searchresult_header_form_input { + float: left; + display: block; + font-weight: 600; + padding: 0 2.333333333333333em 0 0.666666666666667em; + width: 100%; + height: 2.666666666666667em; + border: none; + vertical-align: middle; +} +.searchresult_header_form_button { + float: left; + width: 2.333333333333333em; + height: 2.666666666666667em; + margin-left: -2.333333333333333em; + border: none; + vertical-align: middle; + background: url("images/mobile/search-icon-yellow.svg") no-repeat; + background-size: 1.333333333333333em 1.333333333333333em; + background-position: center; +} +.searchresult_amount { + font-size: 0.866666666666667em; + font-weight: 600; + color: #0a0a0a; + padding: 1.153846153846154em; + border-bottom: 1px solid #ccc; +} +.searchresult_item { + padding: 1.333333333333333em 1em; + border-bottom: 1px solid #ccc; + text-decoration: none !important; +} +.searchresult_item_headline { + font-size: 1.066666666666667em; + font-weight: 700; + margin-right: 2em; +} +.searchresult_item_event { + font-size: 0.866666666666667em; + color: #0a0a0a; + margin-right: 2em; +} +.searchresult_item_event_link { + color: #0a0a0a; +} +.searchresult_item_event_link:visited, +.searchresult_item_event_link:active { + color: #0a0a0a; +} +.searchresult_item_event_separator:after { + content: "|"; + margin: 0 0.384615384615385em; + color: #ccc; +} +.searchresult_item_arrow { + background: url("images/home/arrow-down-grey.png"); + background-size: contain; + display: block; + width: 1.333333333333333em; + height: 1.333333333333333em; + top: 50%; + right: 1em; + position: absolute; + -webkit-transform: translateY(-50%) rotate(-90deg); + -moz-transform: translateY(-50%) rotate(-90deg); + -ms-transform: translateY(-50%) rotate(-90deg); + transform: translateY(-50%) rotate(-90deg); +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.java new file mode 100644 index 00000000000..99ca5956fbb --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.java @@ -0,0 +1,62 @@ +package com.sap.sailing.gwt.home.mobile.partials.searchresult; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Element; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; +import com.sap.sailing.gwt.home.shared.partials.searchresult.AbstractSearchResult; + +public class SearchResult extends AbstractSearchResult { + + private static SearchResultUiBinder uiBinder = GWT.create(SearchResultUiBinder.class); + + interface SearchResultUiBinder extends UiBinder { + } + + @UiField TextBox searchInputUi; + @UiField Button searchButtonUi; + @UiField DivElement searchResultAmountUi; + @UiField FlowPanel searchResultContainerUi; + + private final MobilePlacesNavigator navigator; + + public SearchResult(MobilePlacesNavigator navigator) { + this.navigator = navigator; + SearchResultResources.INSTANCE.css().ensureInjected(); + init(navigator, uiBinder.createAndBindUi(this)); + } + + @Override + protected TextBox getSearchTextInputUi() { + return searchInputUi; + } + + @Override + protected Button getSearchButtonUi() { + return searchButtonUi; + } + + @Override + protected Element getSearchResultAmountUi() { + return searchResultAmountUi; + } + + @Override + protected HasWidgets getSearchResultContainerUi() { + return searchResultContainerUi; + } + + @Override + protected void addSearchResultItem(SearchResultDTO searchResult) { + searchResultContainerUi.add(new SearchResultItem(navigator, searchResult)); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.ui.xml new file mode 100644 index 00000000000..2f82547826e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResult.ui.xml @@ -0,0 +1,28 @@ + + + + + + +
+
+
+
+ +
+ + + +
+
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.java new file mode 100644 index 00000000000..a0b85e11b66 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.java @@ -0,0 +1,47 @@ +package com.sap.sailing.gwt.home.mobile.partials.searchresult; + +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.Element; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; +import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; +import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.partials.searchresult.AbstractSearchResultItem; + +public class SearchResultItem extends AbstractSearchResultItem { + + private static SearchResultItemUiBinder uiBinder = GWT.create(SearchResultItemUiBinder.class); + + interface SearchResultItemUiBinder extends UiBinder { + } + + @UiField DivElement resultTitleUi; + @UiField DivElement eventInfoContainerUi; + private final AnchorElement anchorUi; + private final MobilePlacesNavigator navigator; + + SearchResultItem(MobilePlacesNavigator navigator, SearchResultDTO item) { + this.navigator = navigator; + init(anchorUi = uiBinder.createAndBindUi(this), item); + SearchResultEventInfoDTO event = item.getEvents().iterator().next(); + String eventId = String.valueOf(event.getId()), leaderboardName = item.getLeaderboardName(), baseUrl = item.getBaseUrl(); + PlaceNavigation regattaNavigation = navigator.getRegattaOverviewNavigation(eventId, leaderboardName, baseUrl, item.isOnRemoteServer()); + regattaNavigation.configureAnchorElement(anchorUi); + } + + @Override + protected Element getResultTitleUi() { + return resultTitleUi; + } + + @Override + protected void addEventInfo(SearchResultEventInfoDTO event) { + if (eventInfoContainerUi.hasChildNodes()) return; // TODO: Temporary add only one event on mobile + eventInfoContainerUi.appendChild(new SearchResultItemEventInfo(navigator, event).getElement()); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.ui.xml new file mode 100644 index 00000000000..6fe6bff4d8b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItem.ui.xml @@ -0,0 +1,12 @@ + + + + + +
+
+
+
+
+ \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.java new file mode 100644 index 00000000000..5fd24553ea5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.java @@ -0,0 +1,43 @@ +package com.sap.sailing.gwt.home.mobile.partials.searchresult; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.SpanElement; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; +import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; +import com.sap.sailing.gwt.home.shared.partials.searchresult.AbstractSearchResultItemEventInfo; + +public class SearchResultItemEventInfo extends AbstractSearchResultItemEventInfo { + + private static SearchResultItemEventInfoUiBinder uiBinder = GWT.create(SearchResultItemEventInfoUiBinder.class); + + interface SearchResultItemEventInfoUiBinder extends UiBinder { + } + + @UiField DivElement eventNameUi; + @UiField SpanElement eventVenueUi; + @UiField SpanElement eventDateUi; + + SearchResultItemEventInfo(MobilePlacesNavigator navigator, SearchResultEventInfoDTO event) { + init(uiBinder.createAndBindUi(this), event); + } + + @Override + protected Element getEventNameUi() { + return eventNameUi; + } + + @Override + protected Element getEventVenueUi() { + return eventVenueUi; + } + + @Override + protected Element getEventDateUi() { + return eventDateUi; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.ui.xml new file mode 100644 index 00000000000..bc361e49b6a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultItemEventInfo.ui.xml @@ -0,0 +1,14 @@ + + + + + +
+
+
+ + +
+
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultResources.java new file mode 100644 index 00000000000..8e4bac5940f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/searchresult/SearchResultResources.java @@ -0,0 +1,29 @@ +package com.sap.sailing.gwt.home.mobile.partials.searchresult; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; + +public interface SearchResultResources extends ClientBundle { + public static final SearchResultResources INSTANCE = GWT.create(SearchResultResources.class); + + @Source("SearchResult.gss") + LocalCss css(); + + public interface LocalCss extends CssResource { + String searchresult(); + String searchresult_header(); + String searchresult_header_form(); + String searchresult_header_form_label(); + String searchresult_header_form_inputwrapper(); + String searchresult_header_form_input(); + String searchresult_header_form_button(); + String searchresult_amount(); + String searchresult_item(); + String searchresult_item_headline(); + String searchresult_item_event(); + String searchresult_item_event_link(); + String searchresult_item_event_separator(); + String searchresult_item_arrow(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/section/MobileSection.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/section/MobileSection.ui.xml index 3ad3f4cc9ff..d550b0e4acc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/section/MobileSection.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/section/MobileSection.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.gss index e44a3b9ea85..c5aea236817 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.gss @@ -90,6 +90,27 @@ img.sectionheader_item_arrow.accordion.collapsed { -ms-transform: rotate(0deg); transform: rotate(0deg); } +.sectionheader_item_select { + position: absolute; + top: 50%; + right: 1em; + -webkit-transform: translateY(-50%); + -moz-transform: translateY(-50%); + -ms-transform: translateY(-50%); + transform: translateY(-50%); + font-weight: 600; + height: auto; + width: 16.666666666666666em; + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + color: #008fcc; + border: none; + border-radius: 0; + padding: 0.666666666666667em 2em 0.666666666666667em 1em; + background: url("images/mobile/filter.svg") 100% no-repeat transparent; + background-size: 1.333333333333333em; +} .sectionheader_item_adjust_title { margin-left: 4em; margin-right: 2.5em; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.ui.xml index 73e14658dde..29722a5be32 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeader.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.java index 67238584333..664aecc761e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.java @@ -13,21 +13,25 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; +import com.sap.sailing.gwt.home.communication.event.LabelType; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; +import com.sap.sailing.gwt.home.shared.partials.filter.AbstractSelectionFilter; import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; -import com.sap.sailing.gwt.ui.shared.general.LabelType; -public class SectionHeaderContent extends Widget { +public class SectionHeaderContent extends Composite { protected static final String ACCORDION_COLLAPSED_STYLE = SectionHeaderResources.INSTANCE.css().collapsed(); private static MyBinder uiBinder = GWT.create(MyBinder.class); - interface MyBinder extends UiBinder { + interface MyBinder extends UiBinder { } + @UiField SectionHeaderResources local_res; @UiField AnchorElement headerMainUi; @UiField DivElement headerLeftUi; @UiField DivElement titleAndLabelContainerUi; @@ -38,10 +42,12 @@ public class SectionHeaderContent extends Widget { @UiField DivElement headerRightUi; @UiField DivElement infoTextUi; @UiField ImageElement actionArrowUi; + @UiField SimplePanel filterSelectContainerUi; public SectionHeaderContent() { SectionHeaderResources.INSTANCE.css().ensureInjected(); - setElement(uiBinder.createAndBindUi(this)); + initWidget(uiBinder.createAndBindUi(this)); + filterSelectContainerUi.setVisible(false); } public void setSectionTitle(String sectionHeaderTitle) { @@ -121,4 +127,12 @@ public class SectionHeaderContent extends Widget { else element.removeClassName(className); } + public void initFilterSelectUi(AbstractSelectionFilter selectionFilter) { + headerRightUi.getStyle().clearDisplay(); + filterSelectContainerUi.setVisible(true); + filterSelectContainerUi.setWidget(selectionFilter); + selectionFilter.addStyleName(local_res.css().sectionheader_item_select()); + selectionFilter.getElement().setAttribute("dir", "rtl"); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.ui.xml index 2f28910ffca..091af981667 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderContent.ui.xml @@ -1,10 +1,9 @@ - + - + -
+ - \ No newline at end of file + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderResources.java index fc9eb33855a..228676919fc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/sectionHeader/SectionHeaderResources.java @@ -24,6 +24,7 @@ public interface SectionHeaderResources extends ClientBundle { String sectionheader_item_infotext(); String sectionheader_item_arrow(); String sectionheader_item_adjust_title(); + String sectionheader_item_select(); String accordion(); String collapsed(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.java index c07822daf92..ce38785793c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.java @@ -8,11 +8,11 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.home.shared.utils.LogoUtil; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; public class SeriesHeader extends Composite { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.ui.xml index fb5e9e32bec..eb02563f65d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/seriesheader/SeriesHeader.ui.xml @@ -3,7 +3,7 @@ xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"> - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/simpleinfoblock/SimpleInfoBlock.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/simpleinfoblock/SimpleInfoBlock.ui.xml index c1759c1b2ce..eb8d58a8434 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/simpleinfoblock/SimpleInfoBlock.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/simpleinfoblock/SimpleInfoBlock.ui.xml @@ -2,7 +2,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> .description { display: none; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/socialfooter/SocialFooter.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/socialfooter/SocialFooter.ui.xml index f5d0da14854..16989c71521 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/socialfooter/SocialFooter.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/socialfooter/SocialFooter.ui.xml @@ -2,7 +2,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.java index 96d06af51b7..5199e01c4b9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.java @@ -19,6 +19,7 @@ public class Solutions extends Composite { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); + @UiField DivElement sapInSailingDiv; @UiField DivElement sapSailingAnalyticsUi; @UiField DivElement raceCommitteeAppUi; @UiField DivElement postRaceAnalyticsUi; @@ -29,7 +30,8 @@ public class Solutions extends Composite { SolutionsResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); - initAnimation(sapSailingAnalyticsUi, true); + initAnimation(sapInSailingDiv, true); + initAnimation(sapSailingAnalyticsUi, false); initAnimation(raceCommitteeAppUi, false); initAnimation(postRaceAnalyticsUi, false); initAnimation(stgTrainingDiaryUi, false); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.ui.xml index 57e3d8ce093..11fc48186cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/solutions/Solutions.ui.xml @@ -1,86 +1,152 @@ - - - - - - -
-
-
-
-

- -

- {i18n_ubi.solutionsSAPHeadline} -
-
- {i18n.sapSailingAnalytics} -

- -

-

- -

-
-
-
-
-

- -

- -
-
- {i18n_ubi.solutionsRaceHeadline} -

- -

-
-
-
-
-

- -

- -
-
- {i18n_ubi.solutionsPostHeadline} -

- -

-
-
-
-
-

- -

- -
-
- {i18n_ubi.solutionsTrainingHeadline} -

- -

-
-
-
-
-

- -

- -
-
- {i18n_ubi.solutionsSimulatorHeadline} -

- -

-
-
-
-
-
+ + + + + +
+
+
+
+

+ +

+ +
+
+ {i18n.sapInSailing} +

+ +

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+

+ +

+
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+
+
+
+

+ +

+ +
+
+ {i18n.sapSailingAnalytics} +

+ +

+

+ +

+
+
+
+
+

+ +

+ +
+
+ {i18n.sapSailingRaceManager} +

+ +

+
+
+
+
+

+ +

+ +
+
+ {i18n.postRaceAnalytics} +

+ +

+

+ +

+
+
+
+
+

+ +

+ +
+
+ {i18n.i18nDeSolutionsTrainingHeadline} +

+ +

+
+
+
+
+

+ +

+ +
+
+ {i18n.strategySimulator} +

+ +

+
+
+
+
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveEventStageTeaser.java index 83548f2fffb..6262e7c1c95 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; public class LiveEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveStageTeaserBand.java index 2fbfaf3012f..ea47d5a56c5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/LiveStageTeaserBand.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; /** * Teaser band for a live event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/NoActionStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/NoActionStageTeaserBand.java index 516dd9fb8db..8ae3db7c839 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/NoActionStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/NoActionStageTeaserBand.java @@ -1,8 +1,8 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; /** * Teaser band with no action on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaser.java index 610ecdd09bb..1fadf0fef46 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; public class PopularEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaserBand.java index 5297fdf2148..6529a7e9d49 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/PopularEventStageTeaserBand.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; /** * Teaser band for a popular but finished event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.java index dd79d3c3f8b..4e921c4df63 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.java @@ -10,8 +10,8 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; import com.sap.sse.gwt.client.controls.carousel.WidgetCarousel; public class Stage extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.ui.xml index b9201584cf5..6a6954f5566 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/Stage.ui.xml @@ -5,7 +5,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.java index 0a9b8215bd2..afe9cbddc29 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.java @@ -12,8 +12,8 @@ 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.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.gwt.client.controls.carousel.LazyLoadable; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.ui.xml index 7ecb3624b21..0bac3f03ed6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaser.ui.xml @@ -4,7 +4,7 @@ xmlns:sp="urn:import:com.sap.sailing.gwt.home.shared.partials" xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials"> - + .countdownPosition { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.java index ceec29dca9a..d92be73980d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.java @@ -9,11 +9,11 @@ import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.app.PlaceNavigator; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; public abstract class StageTeaserBand extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.ui.xml index 4f2a4af7739..782328e27cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/StageTeaserBand.ui.xml @@ -4,7 +4,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaser.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaser.java index d20b2d6f39e..dee20ca053f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaser.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaser.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; public class UpcomingEventStageTeaser extends StageTeaser { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaserBand.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaserBand.java index 0d65e7973ed..388937c21cb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaserBand.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/stage/UpcomingEventStageTeaserBand.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.mobile.partials.stage; import com.google.gwt.event.dom.client.ClickEvent; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; /** * Teaser band for an upcoming event on the homepage stage diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBox.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBox.ui.xml index 004e1883070..b5d4f152f2e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBox.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBox.ui.xml @@ -3,7 +3,7 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared" xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials"> - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBoxItem.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBoxItem.ui.xml index 8bd39494174..9173599caa5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBoxItem.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/statisticsBox/StatisticsBoxItem.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/toggleButton/ToggleButton.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/toggleButton/ToggleButton.ui.xml index dc0d07aae0d..f50d6c52c53 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/toggleButton/ToggleButton.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/toggleButton/ToggleButton.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.java index b0e28622f6c..ab8bf4361f7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.java @@ -12,10 +12,10 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; public class EventsOverviewUpcoming extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.ui.xml index 6b0d87d5a98..8c6347c2d32 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcoming.ui.xml @@ -4,7 +4,7 @@ xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"> - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.java index 1f4642b71b4..2f5ca17f6be 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.java @@ -10,11 +10,11 @@ import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; public class EventsOverviewUpcomingEvent extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.ui.xml index a7fc0e679db..a881101438e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/upcoming/EventsOverviewUpcomingEvent.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/NewsItemLinkProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/NewsItemLinkProvider.java index 83d7263c0f1..ff4808cab66 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/NewsItemLinkProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/NewsItemLinkProvider.java @@ -2,8 +2,8 @@ package com.sap.sailing.gwt.home.mobile.partials.updatesBox; import java.util.List; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public interface NewsItemLinkProvider { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBox.java index 6db343c4d63..86a8ba741dd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBox.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBox.java @@ -12,13 +12,13 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; import com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderContent; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public class UpdatesBox extends Composite implements RefreshableWidget> { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBoxItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBoxItem.java index 9c071789b06..bcd29d528a1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBoxItem.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/updatesBox/UpdatesBoxItem.java @@ -12,9 +12,9 @@ import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.BoatClassImageResolver; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; import com.sap.sailing.gwt.ui.shared.util.ConditionalDateTimeFormatter; public class UpdatesBoxItem extends Widget { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGallery.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGallery.ui.xml index e999381548b..1617ddb7a55 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGallery.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGallery.ui.xml @@ -2,7 +2,7 @@ - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGalleryVideo.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGalleryVideo.ui.xml index c33e2b326da..21aa2f52a6e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGalleryVideo.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/partials/videogallery/VideoGalleryVideo.ui.xml @@ -2,7 +2,7 @@ - +
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/QuickfinderPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/QuickfinderPresenter.java index 5a3e8669045..5fc34b6c9be 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/QuickfinderPresenter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/QuickfinderPresenter.java @@ -3,12 +3,12 @@ package com.sap.sailing.gwt.home.mobile.places; import java.util.Collection; import java.util.UUID; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; public class QuickfinderPresenter { private static final StringMessages MSG = StringMessages.INSTANCE; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivity.java new file mode 100644 index 00000000000..3cd83cddc12 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivity.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.home.mobile.places.error; + +import com.google.gwt.user.client.Command; +import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.shared.places.error.AbstractErrorActivity; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; +import com.sap.sse.gwt.client.mvp.ErrorView; + +public class ErrorActivity extends AbstractErrorActivity { + + public ErrorActivity(ErrorPlace place, MobileApplicationClientFactory clientFactory) { + super(place, clientFactory.getPlaceController()); + } + + @Override + protected ErrorView createView(String errorMsg, Throwable reason, Command reloadCommand) { + return new ErrorViewImpl(errorMsg, reason, reloadCommand); + } + + @Override + protected ErrorView createView(String customMsg, String errorMsg, Throwable reason, Command reloadCommand) { + return new ErrorViewImpl(customMsg, errorMsg, reason, reloadCommand); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivityProxy.java new file mode 100644 index 00000000000..d2f87b990d4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorActivityProxy.java @@ -0,0 +1,27 @@ +package com.sap.sailing.gwt.home.mobile.places.error; + +import com.google.gwt.core.client.GWT; +import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; +import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; + +public class ErrorActivityProxy extends AbstractActivityProxy { + + private final ErrorPlace place; + private final MobileApplicationClientFactory clientFactory; + + public ErrorActivityProxy(ErrorPlace place, MobileApplicationClientFactory clientFactory) { + this.place = place; + this.clientFactory = clientFactory; + } + + @Override + protected void startAsync() { + GWT.runAsync(new AbstractRunAsyncCallback() { + @Override + public void onSuccess() { + super.onSuccess(new ErrorActivity(place, clientFactory)); + } + }); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.java new file mode 100644 index 00000000000..2c6cb05bafa --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.home.mobile.places.error; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.common.client.SharedResources; +import com.sap.sailing.gwt.home.shared.partials.error.ErrorMessage; +import com.sap.sse.gwt.client.mvp.ErrorView; + +public class ErrorViewImpl extends Composite implements ErrorView { + + private static ErrorViewUiBinder uiBinder = GWT.create(ErrorViewUiBinder.class); + + interface ErrorViewUiBinder extends UiBinder { + } + + @UiField(provided = true) ErrorMessage errorMessageUi; + + public ErrorViewImpl(String errorMessageDetail, Throwable errorReason, Command reloadCommand) { + this(new ErrorMessage(errorMessageDetail, errorReason, reloadCommand)); + } + + public ErrorViewImpl(String errorMessage, String errorMessageDetail, Throwable errorReason, Command reloadCommand) { + this(new ErrorMessage(errorMessage, errorMessageDetail, errorReason, reloadCommand)); + } + + private ErrorViewImpl(ErrorMessage errorMessage) { + errorMessageUi = errorMessage; + initWidget(uiBinder.createAndBindUi(this)); + errorMessageUi.addReloadPageButtonStyleNames(SharedResources.INSTANCE.mediaCss().small12()); + } + +} + \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.ui.xml new file mode 100644 index 00000000000..fad93840ffd --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/error/ErrorViewImpl.ui.xml @@ -0,0 +1,10 @@ + + + + +
+ +
+
+
diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventActivity.java index 12267399f88..d0867a28588 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventActivity.java @@ -4,14 +4,24 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import com.google.gwt.activity.shared.AbstractActivity; -import com.google.gwt.core.shared.GWT; import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.event.news.LeaderboardNewsEntryDTO; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.media.GetMediaForEventAction; +import com.sap.sailing.gwt.home.communication.media.MediaDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.mediatab.MultiregattaMediaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.leaderboardtab.RegattaLeaderboardPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.mediatab.RegattaMediaPlace; @@ -19,54 +29,62 @@ import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.Regatta import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase.Presenter; +import com.sap.sailing.gwt.home.mobile.places.event.latestnews.LatestNewsPlace; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; +import com.sap.sailing.gwt.home.mobile.places.event.overview.AbstractEventOverview; import com.sap.sailing.gwt.home.mobile.places.series.minileaderboard.SeriesMiniOverallLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.event.EventContext; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; +import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; +import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.news.LeaderboardNewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; +import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration; import com.sap.sailing.gwt.ui.shared.util.NullSafeComparableComparator; public abstract class AbstractEventActivity extends AbstractActivity implements Presenter { private final MobileApplicationClientFactory clientFactory; - private final PLACE place; + protected final PLACE place; + protected final EventViewDTO eventDTO; + private AcceptsOneWidget panel; - protected AbstractEventActivity(PLACE place, MobileApplicationClientFactory clientFactory) { + protected AbstractEventActivity(PLACE place, EventViewDTO eventDTO, MobileApplicationClientFactory clientFactory) { + this.eventDTO = eventDTO; this.clientFactory = clientFactory; this.place = place; } @Override public final void start(final AcceptsOneWidget panel, final EventBus eventBus) { + this.panel = panel; final EventViewBase view = initView(); panel.setWidget(view.asWidget()); } protected abstract EventViewBase initView(); - protected final void initSailorInfoOrSeriesNavigation(EventViewBase view) { - EventViewDTO event = getCtx().getEventDTO(); - String sailorInfoUrl = event.getSailorsInfoWebsiteURL(); + protected final void initSeriesNavigation(EventViewBase view) { + if (eventDTO.getType() == EventType.SERIES_EVENT) { + String seriesIdAsString = eventDTO.getSeriesIdAsString(); + PlaceNavigation navigation = clientFactory.getNavigator().getEventSeriesNavigation(seriesIdAsString, null, false); + view.setSeriesNavigation(eventDTO.getSeriesName(), navigation); + } + } + + protected final void initSailorInfo(EventViewBase view) { + String sailorInfoUrl = eventDTO.getSailorsInfoWebsiteURL(); if (sailorInfoUrl != null && !sailorInfoUrl.isEmpty()) { view.setSailorInfos(StringMessages.INSTANCE.sailorInfoLongText(), StringMessages.INSTANCE.sailorInfo(), sailorInfoUrl); - } else if (event.getType() == EventType.SERIES_EVENT) { - String seriesIdAsString = event.getSeriesIdAsString(); - PlaceNavigation navigation = clientFactory.getNavigator().getEventSeriesNavigation(seriesIdAsString, null, false); - view.setSeriesNavigation(event.getSeriesName(), navigation); } } protected final void initQuickfinder(EventViewBase view, boolean showQuickfinder) { - EventViewDTO event = getCtx().getEventDTO(); + EventViewDTO event = eventDTO; if(showQuickfinder && event.getType() == EventType.MULTI_REGATTA) { view.setQuickFinderValues(getSortedQuickFinderValues()); } else if(showQuickfinder && event.getType() == EventType.SERIES_EVENT) { @@ -77,7 +95,7 @@ public abstract class AbstractEventActivity ex } private Collection getSortedQuickFinderValues() { - Collection regattas = place.getCtx().getEventDTO().getRegattas(); + Collection regattas = eventDTO.getRegattas(); List sortedRegattas = new ArrayList(regattas); Collections.sort(sortedRegattas, new Comparator() { private Comparator bootCatComparator = new NullSafeComparableComparator(); @@ -90,17 +108,29 @@ public abstract class AbstractEventActivity ex return sortedRegattas; } - protected final void initMedia(AsyncMediaCallback callback) { - if (getCtx().getEventDTO().isHasMedia()) { - clientFactory.getHomeService().getMediaForEvent(getCtx().getEventDTO().getId(), callback); + protected final void initMedia(final AbstractEventOverview view) { + this.initMedia(new MediaCallback() { + @Override + public void onSuccess(MediaDTO result) { + view.setMediaForImpressions(result.getPhotos().size(), result.getVideos().size(), result.getPhotos()); + } + }); + } + + protected final void initMedia(final MediaCallback callback) { + if (eventDTO.isHasMedia()) { + clientFactory.getDispatch().execute(new GetMediaForEventAction(eventDTO.getId()), + new ActivityCallback(clientFactory, panel) { + @Override + public void onSuccess(MediaDTO result) { + callback.onSuccess(result); + } + }); } } - protected abstract class AsyncMediaCallback implements AsyncCallback { - @Override - public void onFailure(Throwable caught) { - GWT.log("Failed to load media"); - } + protected interface MediaCallback { + void onSuccess(MediaDTO result); } protected final PLACE getPlace() { @@ -112,10 +142,15 @@ public abstract class AbstractEventActivity ex return getPlace().getCtx(); } - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return clientFactory.getDispatch(); } + @Override + public ErrorAndBusyClientFactory getErrorAndBusyClientFactory() { + return clientFactory; + } + @Override public PlaceNavigation getRegattaLeaderboardNavigation(String leaderboardName) { EventContext ctx = new EventContext(getCtx()).withRegattaId(leaderboardName).withRegattaAnalyticsManager(null); @@ -130,7 +165,7 @@ public abstract class AbstractEventActivity ex @Override public PlaceNavigation getMiniOverallLeaderboardNavigation() { - return clientFactory.getNavigator().getSeriesNavigation(new SeriesMiniOverallLeaderboardPlace(new SeriesContext().withId(getCtx().getEventId())), null, false); + return clientFactory.getNavigator().getSeriesNavigation(new SeriesMiniOverallLeaderboardPlace(new SeriesContext(getCtx().getEventId())), null, false); } @Override @@ -144,7 +179,7 @@ public abstract class AbstractEventActivity ex } public PlaceNavigation getMediaPageNavigation() { - if (getCtx().getEventDTO().getType() == EventType.MULTI_REGATTA) { + if (eventDTO.getType() == EventType.MULTI_REGATTA) { return clientFactory.getNavigator().getEventNavigation(new MultiregattaMediaPlace(getCtx()), null, false); } else { return clientFactory.getNavigator().getEventNavigation(new RegattaMediaPlace(getCtx()), null, false); @@ -173,17 +208,101 @@ public abstract class AbstractEventActivity ex return clientFactory.getNavigator().getEventNavigation(new EventDefaultPlace(eventId.toString()), null, false); } + public PlaceNavigation getSeriesNavigationForCurrentEvent() { + return clientFactory.getNavigator().getSeriesNavigation(new SeriesDefaultPlace(place.getEventUuidAsString()), null, false); + } + public PlaceNavigation getRegattaRacesNavigation(String regattaId) { EventContext ctx = new EventContext(getCtx()).withRegattaId(regattaId).withRegattaAnalyticsManager(null); return clientFactory.getNavigator().getEventNavigation(new RegattaRacesPlace(ctx), null, false); } + public PlaceNavigation getLatesNewsNavigation() { + EventContext ctx = new EventContext(getCtx()).withRegattaId(null).withRegattaAnalyticsManager(null); + return clientFactory.getNavigator().getEventNavigation(new LatestNewsPlace(ctx), null, false); + } + @Override public PlaceNavigation getSeriesEventRacesNavigation(UUID eventId) { return clientFactory.getNavigator().getEventNavigation(new RegattaRacesPlace(eventId.toString(), null), null, false); } + + @Override + public String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata) { + return getRaceViewerURL(raceMetadata.getLeaderboardName(), raceMetadata.getLeaderboardGroupName(), + raceMetadata.getRegattaAndRaceIdentifier()); + } + + private String getRaceViewerURL(String leaderboardName, String leaderboardGroupName, RegattaAndRaceIdentifier raceIdentifier) { + return EntryPointLinkFactory.createRaceBoardLink(createRaceBoardLinkParameters(leaderboardName, leaderboardGroupName, + raceIdentifier.getRegattaName(), raceIdentifier.getRaceName())); + } + + private Map createRaceBoardLinkParameters(String leaderboardName, + String leaderboardGroupName, String regattaName, String trackedRaceName) { + Map linkParams = new HashMap(); + linkParams.put("eventId", getCtx().getEventId()); + linkParams.put("leaderboardName", leaderboardName); + if (leaderboardGroupName != null) { + linkParams.put("leaderboardGroupName", leaderboardGroupName); + } + linkParams.put("raceName", trackedRaceName); + linkParams.put("regattaName", regattaName); + linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_MODE, "simple"); + // TODO this must only be forwarded if there is a logged-on user + // linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true"); + return linkParams; + } - public String getRaceViewerURL(String regattaName, String trackedRaceName) { - return null; // TODO No mobile "RaceViewer implemented yet + + public String getRegattaId() { + String regattaId = place.getRegattaId(); + if(regattaId != null) { + return regattaId; + } + if(!eventDTO.getRegattas().isEmpty() && (eventDTO.getType() == EventType.SINGLE_REGATTA || eventDTO.getType() == EventType.SERIES_EVENT)) { + return eventDTO.getRegattas().iterator().next().getId(); + } + return null; + } + + public RegattaMetadataDTO getRegatta() { + String regattaId = getRegattaId(); + if(regattaId == null) { + return null; + } + for (RegattaMetadataDTO regatta : eventDTO.getRegattas()) { + if(regattaId.equals(regatta.getId())) { + return regatta; + } + } + return null; + } + + @Override + public EventViewDTO getEventDTO() { + return eventDTO; + } + + @Override + public boolean isMultiRegattaEvent() { + return getEventDTO().getType() == EventType.MULTI_REGATTA; + } + + protected List getNavigationPathToEventLevel() { + List navigationItems = new ArrayList<>(); + if(getEventDTO().getType() == EventType.SERIES_EVENT) { + navigationItems.add(new NavigationItem(getEventDTO().getSeriesName(), getSeriesNavigationForCurrentEvent())); + } + navigationItems.add(new NavigationItem(getEventDTO().getLocationOrDisplayName(), getEventNavigation())); + return navigationItems; + } + + protected List getNavigationPathToRegattaLevel() { + List navigationItems = getNavigationPathToEventLevel(); + if(getEventDTO().getType() == EventType.MULTI_REGATTA) { + navigationItems.add(new NavigationItem(getRegatta().getDisplayName(), getRegattaOverviewNavigation(getRegattaId()))); + } + return navigationItems; } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.java index 23a6c8c89fd..b82f5805c9c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.java @@ -11,6 +11,9 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; import com.sap.sailing.gwt.home.mobile.partials.eventheader.EventHeader; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.mobile.partials.section.MobileSection; @@ -19,11 +22,8 @@ import com.sap.sailing.gwt.home.mobile.partials.simpleinfoblock.SimpleInfoBlock; import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; +import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; public abstract class AbstractEventView

extends Composite implements EventViewBase { @@ -46,30 +46,42 @@ public abstract class AbstractEventView

exten protected final P currentPresenter; protected final RefreshManager refreshManager; private final AbstractEventViewLayout layout; + + private final SimplePanel contentRoot = new SimplePanel(); + private final boolean supportsRefresh; public AbstractEventView(P presenter, boolean showRegattaName, boolean enableLogoNavigation) { + this(presenter, showRegattaName, enableLogoNavigation, true); + } + + public AbstractEventView(P presenter, boolean showRegattaName, boolean enableLogoNavigation, boolean supportsRefresh) { this.currentPresenter = presenter; - this.refreshManager = new RefreshManager(this, currentPresenter.getDispatch()); - String regattaName = showRegattaName ? currentPresenter.getCtx().getRegatta().getDisplayName() : null; + this.supportsRefresh = supportsRefresh; + String regattaName = showRegattaName ? currentPresenter.getRegatta().getDisplayName() : null; PlaceNavigation logoNavigation = enableLogoNavigation ? currentPresenter.getEventNavigation() : null; - this.layout = new AbstractEventViewLayout(currentPresenter.getCtx().getEventDTO(), regattaName, logoNavigation); + this.layout = new AbstractEventViewLayout(currentPresenter.getEventDTO(), regattaName, logoNavigation); initWidget(uiBinder.createAndBindUi(this.layout)); + this.refreshManager = new RefreshManagerWithErrorAndBusy(contentRoot, layout.viewContentUi, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory()); } protected void setViewContent(Widget contentWidget) { - layout.viewContentUi.setWidget(contentWidget); + if(supportsRefresh) { + contentRoot.setWidget(contentWidget); + } else { + layout.viewContentUi.setWidget(contentWidget); + } } protected UUID getEventId() { - return currentPresenter.getCtx().getEventDTO().getId(); + return currentPresenter.getEventDTO().getId(); } protected String getRegattaId() { - return currentPresenter.getCtx().getRegattaId(); + return currentPresenter.getRegattaId(); } protected boolean isMultiRegattaEvent() { - return currentPresenter.getCtx().getEventDTO().getType() == EventType.MULTI_REGATTA; + return currentPresenter.isMultiRegattaEvent(); } protected void setQuickFinderValues(Quickfinder quickfinder, Collection regattaMetadatas) { @@ -83,7 +95,7 @@ public abstract class AbstractEventView

exten protected void initRacesNavigation(Panel container) { MobileSection mobileSection = new MobileSection(); SectionHeaderContent header = new SectionHeaderContent(); - header.setSectionTitle(StringMessages.INSTANCE.racesCount(currentPresenter.getCtx().getRegatta().getRaceCount())); + header.setSectionTitle(StringMessages.INSTANCE.racesCount(currentPresenter.getRegatta().getRaceCount())); header.setInfoText(StringMessages.INSTANCE.showAll()); header.setClickAction(currentPresenter.getRegattaRacesNavigation(getRegattaId())); mobileSection.addHeader(header); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.ui.xml index 3e1ee552c1a..04b1b458666 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/AbstractEventView.ui.xml @@ -1,7 +1,7 @@ - + .headerWrapper { background-color: #f2f2f2; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventActivityProxy.java old mode 100755 new mode 100644 index b7501d7baf2..1a0375faa50 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventActivityProxy.java @@ -1,11 +1,10 @@ package com.sap.sailing.gwt.home.mobile.places.event; -import java.util.UUID; - import com.google.gwt.core.client.GWT; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.mediatab.MultiregattaMediaPlace; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.overviewtab.MultiregattaOverviewPlace; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.regattastab.MultiregattaRegattasPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.mediatab.RegattaMediaPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; @@ -15,66 +14,36 @@ import com.sap.sailing.gwt.home.mobile.places.event.latestnews.LatestNewsPlace; import com.sap.sailing.gwt.home.mobile.places.event.media.MediaActivity; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardActivity; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; -import com.sap.sailing.gwt.home.mobile.places.event.overview.EventActivity; +import com.sap.sailing.gwt.home.mobile.places.event.overview.multiregatta.MultiRegattaActivity; +import com.sap.sailing.gwt.home.mobile.places.event.overview.regatta.RegattaActivity; import com.sap.sailing.gwt.home.mobile.places.event.races.RacesActivity; -import com.sap.sailing.gwt.home.mobile.places.event.regatta.RegattaActivity; +import com.sap.sailing.gwt.home.shared.places.event.AbstractEventActivityProxy; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; -import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventViewAction; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class EventActivityProxy extends AbstractActivityProxy { - - private final MobileApplicationClientFactory clientFactory; - private final AbstractEventPlace currentPlace; +public class EventActivityProxy extends AbstractEventActivityProxy { public EventActivityProxy(AbstractEventPlace place, MobileApplicationClientFactory clientFactory) { - this.currentPlace = place; - this.clientFactory = clientFactory; - } - - @Override - protected void startAsync() { - if(currentPlace.getCtx().getEventDTO() != null) { - afterEventLoad(); - return; - } - UUID eventId = UUID.fromString(currentPlace.getCtx().getEventId()); - clientFactory.getDispatch().execute(new GetEventViewAction(eventId), new AsyncCallback() { - @Override - public void onSuccess(final EventViewDTO event) { - currentPlace.getCtx().updateContext(event); - afterEventLoad(); - } - - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract text? - ErrorPlace errorPlace = new ErrorPlace("Error while loading the event with service getEventViewById()"); - // TODO @FM: reload sinnvoll hier? - errorPlace.setComingFrom(currentPlace); - clientFactory.getPlaceController().goTo(errorPlace); - } - }); + super(clientFactory, place); } - private void afterEventLoad() { + @Override + protected void afterEventLoad(final MobileApplicationClientFactory clientFactory, final EventViewDTO event, + final AbstractEventPlace place) { GWT.runAsync(new AbstractRunAsyncCallback() { @Override public void onSuccess() { - if (currentPlace instanceof EventDefaultPlace) { - super.onSuccess(new EventActivity(currentPlace, clientFactory)); - } else if (currentPlace instanceof RegattaOverviewPlace) { - super.onSuccess(new RegattaActivity((RegattaOverviewPlace) currentPlace, clientFactory)); - } else if (currentPlace instanceof RegattaRacesPlace) { - super.onSuccess(new RacesActivity((RegattaRacesPlace) currentPlace, clientFactory)); - } else if (currentPlace instanceof MiniLeaderboardPlace) { - super.onSuccess(new MiniLeaderboardActivity((MiniLeaderboardPlace) currentPlace, clientFactory)); - } else if (currentPlace instanceof LatestNewsPlace) { - super.onSuccess(new LatestNewsActivity((LatestNewsPlace) currentPlace, clientFactory)); - } else if (currentPlace instanceof RegattaMediaPlace || currentPlace instanceof MultiregattaMediaPlace) { - super.onSuccess(new MediaActivity(currentPlace, clientFactory)); + if (place instanceof MultiregattaOverviewPlace || place instanceof MultiregattaRegattasPlace) { + super.onSuccess(new MultiRegattaActivity(place, event, getNavigationPathDisplay(), clientFactory)); + } else if (place instanceof RegattaOverviewPlace) { + super.onSuccess(new RegattaActivity((RegattaOverviewPlace) place, event, getNavigationPathDisplay(), clientFactory)); + } else if (place instanceof RegattaRacesPlace) { + super.onSuccess(new RacesActivity((RegattaRacesPlace) place, event, getNavigationPathDisplay(), clientFactory)); + } else if (place instanceof MiniLeaderboardPlace) { + super.onSuccess(new MiniLeaderboardActivity((MiniLeaderboardPlace) place, event, getNavigationPathDisplay(), clientFactory)); + } else if (place instanceof LatestNewsPlace) { + super.onSuccess(new LatestNewsActivity((LatestNewsPlace) place, event, getNavigationPathDisplay(), clientFactory)); + } else if (place instanceof RegattaMediaPlace || place instanceof MultiregattaMediaPlace) { + super.onSuccess(new MediaActivity(place, event, getNavigationPathDisplay(), clientFactory)); } } }); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventViewBase.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventViewBase.java index 5b9b21652ed..ca3af4bdb7e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventViewBase.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/EventViewBase.java @@ -3,6 +3,12 @@ package com.sap.sailing.gwt.home.mobile.places.event; import java.util.Collection; import com.google.gwt.user.client.ui.IsWidget; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.mobile.partials.updatesBox.NewsItemLinkProvider; import com.sap.sailing.gwt.home.mobile.places.RegattaLeaderboardNavigationProvider; import com.sap.sailing.gwt.home.mobile.places.RegattaOverviewNavigationProvider; import com.sap.sailing.gwt.home.mobile.places.RegattaRacesNavigationProvider; @@ -10,10 +16,8 @@ import com.sap.sailing.gwt.home.mobile.places.SeriesEventOverviewNavigationProvi import com.sap.sailing.gwt.home.mobile.places.SeriesEventRacesNavigationProvider; import com.sap.sailing.gwt.home.mobile.places.SeriesLeaderboardNavigationProvider; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.event.EventContext; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; public interface EventViewBase extends IsWidget { @@ -29,13 +33,26 @@ public interface EventViewBase extends IsWidget { public interface Presenter extends RegattaLeaderboardNavigationProvider, SeriesLeaderboardNavigationProvider, RegattaRacesNavigationProvider, SeriesEventRacesNavigationProvider, RegattaOverviewNavigationProvider, - SeriesEventOverviewNavigationProvider { + SeriesEventOverviewNavigationProvider, NewsItemLinkProvider { EventContext getCtx(); - DispatchSystem getDispatch(); + SailingDispatchSystem getDispatch(); + + ErrorAndBusyClientFactory getErrorAndBusyClientFactory(); PlaceNavigation getEventNavigation(); + + PlaceNavigation getMediaPageNavigation(); + + String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata); + String getRegattaId(); + + RegattaMetadataDTO getRegatta(); + + EventViewDTO getEventDTO(); + + boolean isMultiRegattaEvent(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsActivity.java index fa804acba03..aef260f8542 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsActivity.java @@ -1,15 +1,29 @@ package com.sap.sailing.gwt.home.mobile.places.event.latestnews; +import java.util.List; + import com.google.gwt.user.client.Window; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; import com.sap.sailing.gwt.home.mobile.places.event.latestnews.LatestNewsView.Presenter; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; +import com.sap.sailing.gwt.ui.client.StringMessages; public class LatestNewsActivity extends AbstractEventActivity implements Presenter { - public LatestNewsActivity(LatestNewsPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); + public LatestNewsActivity(LatestNewsPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + List navigationItems = getNavigationPathToEventLevel(); + navigationItems.add(new NavigationItem(i18n.latestNews(), getLatesNewsNavigation())); + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsPlace.java index 5c5899d23f5..cda6074ee28 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsPlace.java @@ -6,11 +6,11 @@ import java.util.List; import com.google.gwt.place.shared.Prefix; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.shared.app.HasMobileVersion; import com.sap.sailing.gwt.home.shared.places.PlaceTokenPrefixes; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; import com.sap.sailing.gwt.home.shared.places.event.EventContext; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public class LatestNewsPlace extends AbstractEventPlace implements HasMobileVersion { private List news = new LinkedList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsView.java index 1f56266103b..5ab996f2a71 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsView.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.mobile.places.event.latestnews; import java.util.List; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.mobile.partials.updatesBox.NewsItemLinkProvider; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public interface LatestNewsView extends EventViewBase { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsViewImpl.java index 783326c5dc4..9043d6aaca3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/latestnews/LatestNewsViewImpl.java @@ -2,10 +2,10 @@ package com.sap.sailing.gwt.home.mobile.places.event.latestnews; import java.util.List; +import com.sap.sailing.gwt.home.communication.event.news.GetEventOverviewNewsAction; +import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO; import com.sap.sailing.gwt.home.mobile.partials.updatesBox.UpdatesBox; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventOverviewNewsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.news.NewsEntryDTO; public class LatestNewsViewImpl extends AbstractEventView implements LatestNewsView { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaActivity.java index 53ca528a162..7de3b7602d9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaActivity.java @@ -1,23 +1,37 @@ package com.sap.sailing.gwt.home.mobile.places.event.media; +import java.util.List; + +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.media.MediaDTO; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; import com.sap.sailing.gwt.home.mobile.places.event.media.MediaView.Presenter; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; public class MediaActivity extends AbstractEventActivity implements Presenter { - public MediaActivity(AbstractEventPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); + public MediaActivity(AbstractEventPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + List navigationItems = getNavigationPathToEventLevel(); + navigationItems.add(new NavigationItem(i18n.media(), getMediaPageNavigation())); + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); } @Override protected EventViewBase initView() { final MediaView view = new MediaViewImpl(this); initQuickfinder(view, false); - initMedia(new AsyncMediaCallback() { + initMedia(new MediaCallback() { @Override public void onSuccess(MediaDTO result) { view.setMedia(result.getVideos(), result.getPhotos()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaView.java index b078d544857..115c3a3dba3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaView.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.mobile.places.event.media; import java.util.Collection; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; +import com.sap.sailing.gwt.home.communication.media.SailingVideoDTO; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; public interface MediaView extends EventViewBase { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.java index 4f2ade890dd..b633cce1732 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.java @@ -7,11 +7,11 @@ import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.media.SailingImageDTO; +import com.sap.sailing.gwt.home.communication.media.SailingVideoDTO; import com.sap.sailing.gwt.home.mobile.partials.imagegallery.ImageGallery; import com.sap.sailing.gwt.home.mobile.partials.videogallery.VideoGallery; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; public class MediaViewImpl extends AbstractEventView implements MediaView { @@ -25,7 +25,7 @@ public class MediaViewImpl extends AbstractEventView implem @UiField ImageGallery imageGalleryUi; public MediaViewImpl(MediaView.Presenter presenter) { - super(presenter, false, true); + super(presenter, false, true, false); setViewContent(uiBinder.createAndBindUi(this)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.ui.xml index 6dce0efbb5f..fe0e870f4d4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/media/MediaViewImpl.ui.xml @@ -2,7 +2,7 @@ - + .pageTitle { font-size: 1.066666666666667em; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardActivity.java index e2763755b42..6cb83f64322 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardActivity.java @@ -1,14 +1,28 @@ package com.sap.sailing.gwt.home.mobile.places.event.minileaderboard; +import java.util.List; + +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardView.Presenter; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; +import com.sap.sailing.gwt.ui.client.StringMessages; public class MiniLeaderboardActivity extends AbstractEventActivity implements Presenter { - public MiniLeaderboardActivity(MiniLeaderboardPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); + public MiniLeaderboardActivity(MiniLeaderboardPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + List navigationItems = getNavigationPathToRegattaLevel(); + navigationItems.add(new NavigationItem(i18n.results(), getRegattaMiniLeaderboardNavigation(getRegattaId()))); + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardViewImpl.java index 974efc80749..cc2d4497a35 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/minileaderboard/MiniLeaderboardViewImpl.java @@ -1,10 +1,9 @@ package com.sap.sailing.gwt.home.mobile.places.event.minileaderboard; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderbordAction; import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; public class MiniLeaderboardViewImpl extends AbstractEventView implements MiniLeaderboardView { @@ -13,9 +12,8 @@ public class MiniLeaderboardViewImpl extends AbstractEventView { + + private EventOverviewStage overviewStageUi; + private UpdatesBox updatesBoxUi; + private Impressions impressionsUi; + private StatisticsBox statisticsBoxUi; + + public AbstractEventOverview(EventViewBase.Presenter presenter, boolean showRegattaName, boolean enableLogoNavigation) { + super(presenter, showRegattaName, enableLogoNavigation); + } + + protected void setupOverviewStage(Panel container) { + overviewStageUi = new EventOverviewStage(currentPresenter); + refreshManager.add(overviewStageUi, new GetEventOverviewStageAction(getEventId(), true)); + container.add(overviewStageUi); + } + + protected void setupUpdateBox(Panel container) { + updatesBoxUi = new UpdatesBox(currentPresenter, refreshManager); + if (currentPresenter.getEventDTO().getState() == EventState.RUNNING) { + refreshManager.add(updatesBoxUi, new GetEventOverviewNewsAction(getEventId(), 2)); + container.add(updatesBoxUi); + } + } + + protected void setupImpressions(Panel container) { + impressionsUi = new Impressions(); + impressionsUi.getElement().getStyle().setDisplay(Display.NONE); + container.add(impressionsUi); + } + + protected void setupStatisticsBox(Panel container, boolean forRegattaOnly) { + statisticsBoxUi = new StatisticsBox(!forRegattaOnly); + refreshManager.add(statisticsBoxUi, forRegattaOnly ? new GetRegattaStatisticsAction(getEventId(), + getRegattaId()) : new GetEventStatisticsAction(getEventId())); + container.add(statisticsBoxUi); + } + + public void setMediaForImpressions(int nrOfImages, int nrOfVideos, Collection images) { + impressionsUi.getElement().getStyle().setDisplay(Display.BLOCK); + impressionsUi.setStatistis(nrOfImages, nrOfVideos); + impressionsUi.addImages(images); + // TODO: desktop media navigation + impressionsUi.setClickDestinaton(currentPresenter.getMediaPageNavigation()); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventActivity.java deleted file mode 100644 index 3bc1e2a2db0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventActivity.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.overview; - -import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; -import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; -import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; -import com.sap.sailing.gwt.home.mobile.places.event.overview.EventView.Presenter; -import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; - -public class EventActivity extends AbstractEventActivity implements Presenter { - - public EventActivity(AbstractEventPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); - } - - @Override - protected EventViewBase initView() { - final EventView view = new EventViewImpl(this); - initSailorInfoOrSeriesNavigation(view); - initQuickfinder(view, true); - initMedia(new AsyncMediaCallback() { - @Override - public void onSuccess(MediaDTO result) { - view.setMediaForImpressions(result.getPhotos().size(), result.getVideos().size(), result.getPhotos()); - } - }); - return view; - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventOverviewStage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventOverviewStage.java index 07d19192375..01b74df2d9e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventOverviewStage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventOverviewStage.java @@ -6,6 +6,10 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewStageContentDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewTickerStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewVideoStageDTO; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; @@ -14,10 +18,6 @@ import com.sap.sailing.gwt.home.shared.partials.countdown.Countdown.CountdownNav import com.sap.sailing.gwt.home.shared.partials.message.Message; import com.sap.sailing.gwt.home.shared.partials.video.Video; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewStageContentDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewTickerStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewVideoStageDTO; public class EventOverviewStage extends Composite implements RefreshableWidget { @@ -33,7 +33,7 @@ public class EventOverviewStage extends Composite implements RefreshableWidget -

- +
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventView.java deleted file mode 100644 index ba950916737..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventView.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.overview; - -import java.util.Collection; - -import com.sap.sailing.gwt.home.mobile.partials.updatesBox.NewsItemLinkProvider; -import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; -import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; - -public interface EventView extends EventViewBase { - - void setMediaForImpressions(int nrOfImages, int nrOfVideos, Collection images); - - public interface Presenter extends EventViewBase.Presenter, NewsItemLinkProvider { - String getRaceViewerURL(String regattaName, String trackedRaceName); - PlaceNavigation getMediaPageNavigation(); - } -} - diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventViewImpl.java deleted file mode 100644 index 46413fd6e20..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/EventViewImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.overview; - -import java.util.Collection; - -import com.google.gwt.dom.client.Style.Display; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Panel; -import com.sap.sailing.gwt.home.mobile.partials.eventsteps.EventSteps; -import com.sap.sailing.gwt.home.mobile.partials.impressions.Impressions; -import com.sap.sailing.gwt.home.mobile.partials.liveraces.RegattaLiveRaces; -import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; -import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; -import com.sap.sailing.gwt.home.mobile.partials.regattaStatus.RegattaStatus; -import com.sap.sailing.gwt.home.mobile.partials.statisticsBox.StatisticsBox; -import com.sap.sailing.gwt.home.mobile.partials.updatesBox.UpdatesBox; -import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; -import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; -import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventOverviewNewsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventOverviewStageAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetEventStatisticsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForRegattaAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaStatisticsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaWithProgressAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattasAndLiveRacesForEventAction; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; - -public class EventViewImpl extends AbstractEventView implements EventView { - - private static final StringMessages MSG = StringMessages.INSTANCE; - - private EventOverviewStage overviewStageUi; - private EventSteps eventStepsUi; - private RegattaLiveRaces liveRacesUi; - private Impressions impressionsUi; - private StatisticsBox statisticsBoxUi; - private UpdatesBox updatesBoxUi; - - public EventViewImpl(EventView.Presenter presenter) { - super(presenter, false, false); - FlowPanel container = new FlowPanel(); - if (isMultiRegattaEvent()) { - this.setupOverviewStage(container); - this.setupRegattaStatusList(container); - } else { - this.setupProgress(container); - this.setupLiveRaces(container); - this.setupOverviewStage(container); - this.setupMiniLeaderboard(container); - if (ExperimentalFeatures.SHOW_REGATTA_OVERVIEW_AND_RACES_ON_MOBILE) { - initRacesNavigation(container); - } - } - this.setupUpdateBox(container); - this.setupImpressions(container); - this.setupStatisticsBox(container); - setViewContent(container); - } - - private void setupProgress(Panel container) { - eventStepsUi = new EventSteps(); - if (ExperimentalFeatures.SHOW_REGATTA_PROGRESS_ON_MOBILE) { - refreshManager.add(eventStepsUi, new GetRegattaWithProgressAction(getEventId(), getRegattaId())); - container.add(eventStepsUi); - } - } - - private void setupOverviewStage(Panel container) { - overviewStageUi = new EventOverviewStage(currentPresenter); - refreshManager.add(overviewStageUi, new GetEventOverviewStageAction(getEventId(), true)); - container.add(overviewStageUi); - } - - private void setupRegattaStatusList(Panel container) { - RegattaStatus regattaStatus = new RegattaStatus(currentPresenter); - container.add(regattaStatus); - refreshManager.add(regattaStatus, new GetRegattasAndLiveRacesForEventAction(getEventId())); - } - - private void setupLiveRaces(Panel container) { - if (ExperimentalFeatures.SHOW_REGATTA_LIVE_RACES_ON_MOBILE) { - liveRacesUi = new RegattaLiveRaces(); - refreshManager.add(liveRacesUi, new GetLiveRacesForRegattaAction(getEventId(), getRegattaId())); - container.add(liveRacesUi); - } - } - - private void setupMiniLeaderboard(Panel container) { - MinileaderboardBox miniLeaderboard = new MinileaderboardBox(false); - miniLeaderboard.setAction(MSG.showAll(), currentPresenter.getRegattaMiniLeaderboardNavigation(getRegattaId())); - refreshManager.add(miniLeaderboard, new GetMiniLeaderbordAction(getEventId(), getRegattaId(), 3)); - container.add(miniLeaderboard); - } - - private void setupUpdateBox(Panel container) { - updatesBoxUi = new UpdatesBox(currentPresenter, refreshManager); - if (currentPresenter.getCtx().getEventDTO().getState() == EventState.RUNNING) { - refreshManager.add(updatesBoxUi, new GetEventOverviewNewsAction(getEventId(), 2)); - container.add(updatesBoxUi); - } - } - - private void setupImpressions(Panel container) { - impressionsUi = new Impressions(); - impressionsUi.getElement().getStyle().setDisplay(Display.NONE); - container.add(impressionsUi); - } - - private void setupStatisticsBox(Panel container) { - statisticsBoxUi = new StatisticsBox(isMultiRegattaEvent()); - refreshManager.add(statisticsBoxUi, isMultiRegattaEvent() ? new GetEventStatisticsAction(getEventId()) - : new GetRegattaStatisticsAction(getEventId(), getRegattaId())); - container.add(statisticsBoxUi); - } - - @Override - protected void setQuickFinderValues(Quickfinder quickfinder, String seriesName, Collection eventsOfSeries) { - QuickfinderPresenter.getForSeriesEventOverview(quickfinder, seriesName, currentPresenter, eventsOfSeries); - } - - @Override - public void setMediaForImpressions(int nrOfImages, int nrOfVideos, Collection images) { - impressionsUi.getElement().getStyle().setDisplay(Display.BLOCK); - impressionsUi.setStatistis(nrOfImages, nrOfVideos); - impressionsUi.addImages(images); - // TODO: desktop media navigation - impressionsUi.setClickDestinaton(currentPresenter.getMediaPageNavigation()); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaActivity.java new file mode 100644 index 00000000000..0242247e4c9 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaActivity.java @@ -0,0 +1,32 @@ +package com.sap.sailing.gwt.home.mobile.places.event.overview.multiregatta; + +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; +import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; +import com.sap.sailing.gwt.home.mobile.places.event.overview.AbstractEventOverview; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; +import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace; + +public class MultiRegattaActivity extends AbstractEventActivity implements EventViewBase.Presenter { + + public MultiRegattaActivity(AbstractEventPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + navigationPathDisplay.showNavigationPath(new NavigationItem(getEventDTO().getLocationOrDisplayName(), getEventNavigation())); + } + + @Override + protected EventViewBase initView() { + final AbstractEventOverview view = new MultiRegattaViewImpl(this); + initSailorInfo(view); + initQuickfinder(view, true); + initMedia(view); + return view; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaViewImpl.java new file mode 100644 index 00000000000..9e7257165ec --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/multiregatta/MultiRegattaViewImpl.java @@ -0,0 +1,68 @@ +package com.sap.sailing.gwt.home.mobile.places.event.overview.multiregatta; + +import java.util.Arrays; +import java.util.List; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Panel; +import com.sap.sailing.gwt.home.communication.event.GetRegattasAndLiveRacesForEventAction; +import com.sap.sailing.gwt.home.communication.event.RegattasAndLiveRacesDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.mobile.partials.regattaStatus.RegattaStatus; +import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; +import com.sap.sailing.gwt.home.mobile.places.event.overview.AbstractEventOverview; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterPresenter; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterWidget; +import com.sap.sailing.gwt.home.shared.partials.filter.RegattaByBootCategoryFilter; +import com.sap.sailing.gwt.home.shared.partials.regattalist.RegattaListPresenter; + +public class MultiRegattaViewImpl extends AbstractEventOverview { + + private RegattaStatus regattaStatusUi; + + public MultiRegattaViewImpl(EventViewBase.Presenter presenter) { + super(presenter, false, false); + FlowPanel container = new FlowPanel(); + this.setupOverviewStage(container); + this.setupRegattaStatusList(container); + this.setupUpdateBox(container); + this.setupImpressions(container); + this.setupStatisticsBox(container, false); + setViewContent(container); + } + + private void setupRegattaStatusList(Panel container) { + regattaStatusUi = new RegattaStatus(currentPresenter); + RegattaListPresenter regattaListPresenter = + new RegattaListPresenter(regattaStatusUi); + RegattaByBootCategoryFilter bootCategoryFilter = new RegattaByBootCategoryFilter(); + if (ExperimentalFeatures.SHOW_BOAT_CATEGORY_FILTER_ON_MOBILE) { + regattaStatusUi.setFilterSectionWidget(bootCategoryFilter); + } + MultiRegattaViewImplFilterPresenter filterPresenter = + new MultiRegattaViewImplFilterPresenter(bootCategoryFilter, regattaListPresenter); + container.add(regattaStatusUi); + refreshManager.add(filterPresenter.getRefreshableWidgetWrapper( + regattaListPresenter.getRefreshableWidgetWrapper(regattaStatusUi)), + new GetRegattasAndLiveRacesForEventAction(getEventId())); + } + + private class MultiRegattaViewImplFilterPresenter extends FilterPresenter { + private final List> valueChangeHandler; + + public MultiRegattaViewImplFilterPresenter(FilterWidget filterWidget, + FilterValueChangeHandler valueChangeHandler) { + super(filterWidget); + this.valueChangeHandler = Arrays.asList(valueChangeHandler); + super.addHandler(valueChangeHandler); + } + @Override + protected List> getCurrentValueChangeHandlers() { + return valueChangeHandler; + } + + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaActivity.java new file mode 100644 index 00000000000..b29c62bf5e5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaActivity.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.home.mobile.places.event.overview.regatta; + +import java.util.List; + +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; +import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; +import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; +import com.sap.sailing.gwt.home.mobile.places.event.overview.AbstractEventOverview; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; + +public class RegattaActivity extends AbstractEventActivity implements EventViewBase.Presenter { + + public RegattaActivity(RegattaOverviewPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + List navigationItems = getNavigationPathToRegattaLevel(); + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); + } + + @Override + protected EventViewBase initView() { + final AbstractEventOverview view = new RegattaOverviewImpl(this); + initSeriesNavigation(view); + initQuickfinder(view, true); + if (!isMultiRegattaEvent()) { + initMedia(view); + } + return view; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaOverviewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaOverviewImpl.java new file mode 100644 index 00000000000..6e797b16023 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/overview/regatta/RegattaOverviewImpl.java @@ -0,0 +1,82 @@ +package com.sap.sailing.gwt.home.mobile.places.event.overview.regatta; + +import java.util.Collection; + +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Panel; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.GetLiveRacesForRegattaAction; +import com.sap.sailing.gwt.home.communication.event.GetRegattaWithProgressAction; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderbordAction; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.mobile.partials.eventsteps.EventSteps; +import com.sap.sailing.gwt.home.mobile.partials.liveraces.RegattaLiveRaces; +import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; +import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; +import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; +import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; +import com.sap.sailing.gwt.home.mobile.places.event.overview.AbstractEventOverview; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public class RegattaOverviewImpl extends AbstractEventOverview { + + private static final StringMessages MSG = StringMessages.INSTANCE; + + private EventSteps eventStepsUi; + private RegattaLiveRaces liveRacesUi; + + public RegattaOverviewImpl(EventViewBase.Presenter presenter) { + super(presenter, presenter.isMultiRegattaEvent(), presenter.isMultiRegattaEvent()); + FlowPanel container = new FlowPanel(); + this.setupProgress(container); + this.setupLiveRaces(container); + if (!isMultiRegattaEvent()) { + this.setupOverviewStage(container); + } + this.setupMiniLeaderboard(container); + if (ExperimentalFeatures.SHOW_REGATTA_OVERVIEW_AND_RACES_ON_MOBILE) { + initRacesNavigation(container); + } + if (!isMultiRegattaEvent()) { + this.setupUpdateBox(container); + this.setupImpressions(container); + } + this.setupStatisticsBox(container, presenter.isMultiRegattaEvent()); + setViewContent(container); + } + + private void setupProgress(Panel container) { + eventStepsUi = new EventSteps(); + if (ExperimentalFeatures.SHOW_REGATTA_PROGRESS_ON_MOBILE) { + refreshManager.add(eventStepsUi, new GetRegattaWithProgressAction(getEventId(), getRegattaId())); + container.add(eventStepsUi); + } + } + + private void setupLiveRaces(Panel container) { + if (ExperimentalFeatures.SHOW_REGATTA_LIVE_RACES_ON_MOBILE) { + liveRacesUi = new RegattaLiveRaces(); + refreshManager.add(liveRacesUi, new GetLiveRacesForRegattaAction(getEventId(), getRegattaId())); + container.add(liveRacesUi); + } + } + + private void setupMiniLeaderboard(Panel container) { + MinileaderboardBox miniLeaderboard = new MinileaderboardBox(false); + miniLeaderboard.setAction(MSG.showAll(), currentPresenter.getRegattaMiniLeaderboardNavigation(getRegattaId())); + refreshManager.add(miniLeaderboard, new GetMiniLeaderbordAction(getEventId(), getRegattaId(), 3)); + container.add(miniLeaderboard); + } + + @Override + protected void setQuickFinderValues(Quickfinder quickfinder, Collection regattaMetadatas) { + QuickfinderPresenter.getForRegattaOverview(quickfinder, currentPresenter, regattaMetadatas); + } + + @Override + protected void setQuickFinderValues(Quickfinder quickfinder, String seriesName, Collection eventsOfSeries) { + QuickfinderPresenter.getForSeriesEventOverview(quickfinder, seriesName, currentPresenter, eventsOfSeries); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesActivity.java index 0ac1b08e90d..bac62f55092 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesActivity.java @@ -1,15 +1,29 @@ package com.sap.sailing.gwt.home.mobile.places.event.races; +import java.util.List; + +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; import com.sap.sailing.gwt.home.mobile.places.event.races.RacesView.Presenter; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; +import com.sap.sailing.gwt.ui.client.StringMessages; public class RacesActivity extends AbstractEventActivity implements Presenter { - public RacesActivity(RegattaRacesPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); + public RacesActivity(RegattaRacesPlace place, EventViewDTO eventDTO, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + super(place, eventDTO, clientFactory); + initNavigationPath(navigationPathDisplay); + } + + private void initNavigationPath(NavigationPathDisplay navigationPathDisplay) { + StringMessages i18n = StringMessages.INSTANCE; + List navigationItems = getNavigationPathToRegattaLevel(); + navigationItems.add(new NavigationItem(i18n.races(), getRegattaRacesNavigation(getRegattaId()))); + navigationPathDisplay.showNavigationPath(navigationItems.toArray(new NavigationItem[navigationItems.size()])); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesView.java index a7c0c19c532..e457c2af812 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesView.java @@ -5,7 +5,6 @@ import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; public interface RacesView extends EventViewBase { public interface Presenter extends EventViewBase.Presenter { - } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.java index 0b85bc6e5be..64d1ed4c660 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.java @@ -1,19 +1,28 @@ package com.sap.sailing.gwt.home.mobile.places.event.races; +import java.util.Arrays; import java.util.Collection; +import java.util.List; 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.Widget; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.GetCompetitionFormatRacesAction; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetition; import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetCompetitionFormatRacesAction; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterPresenter; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterWidget; +import com.sap.sailing.gwt.home.shared.partials.filter.RacesByCompetitorTextBoxFilter; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionPresenter; public class RacesViewImpl extends AbstractEventView implements RacesView { @@ -22,13 +31,18 @@ public class RacesViewImpl extends AbstractEventView implem interface RacesViewImplUiBinder extends UiBinder { } - @UiField(provided = true) RegattaCompetition regattaCompetitionUi; + @UiField RacesByCompetitorTextBoxFilter competitorFilterUi; + @UiField RegattaCompetition regattaCompetitionUi; - public RacesViewImpl(RacesView.Presenter presenter) { - super(presenter, presenter.getCtx().getEventDTO().getType() == EventType.MULTI_REGATTA, true); - regattaCompetitionUi = new RegattaCompetition(presenter); - refreshManager.add(regattaCompetitionUi, new GetCompetitionFormatRacesAction(getEventId(), getRegattaId())); + public RacesViewImpl(final RacesView.Presenter presenter) { + super(presenter, presenter.isMultiRegattaEvent(), true); setViewContent(uiBinder.createAndBindUi(this)); + RegattaCompetitionPresenter competitionPresenter = new MobileRegattaCompetitionPresenter(); + RacesViewImplFilterPresenter filterPresenter = new RacesViewImplFilterPresenter(competitorFilterUi, competitionPresenter); + refreshManager.add(filterPresenter.getRefreshableWidgetWrapper(competitionPresenter), new GetCompetitionFormatRacesAction(getEventId(), getRegattaId())); + if (!ExperimentalFeatures.SHOW_RACES_BY_COMPETITOR_FILTER) { + competitorFilterUi.removeFromParent(); + } } @Override @@ -41,4 +55,31 @@ public class RacesViewImpl extends AbstractEventView implem QuickfinderPresenter.getForSeriesEventRaces(quickfinder, seriesName, currentPresenter, eventsOfSeries); } + private class MobileRegattaCompetitionPresenter extends RegattaCompetitionPresenter { + public MobileRegattaCompetitionPresenter() { + super(regattaCompetitionUi); + } + + @Override + protected String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata) { + return ExperimentalFeatures.ENABLE_RACE_VIEWER_LINK_ON_MOBILE ? currentPresenter.getRaceViewerURL(raceMetadata) : null; + } + } + + private class RacesViewImplFilterPresenter extends FilterPresenter { + private final List> valueChangeHandler; + + public RacesViewImplFilterPresenter(FilterWidget filterWidget, + FilterValueChangeHandler valueChangeHandler) { + super(filterWidget); + this.valueChangeHandler = Arrays.asList(valueChangeHandler); + super.addHandler(valueChangeHandler); + } + + @Override + protected List> getCurrentValueChangeHandlers() { + return valueChangeHandler; + } + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.ui.xml index c7c078ad88b..14f2f8f1334 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/races/RacesViewImpl.ui.xml @@ -4,18 +4,25 @@ xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:sp="urn:import:com.sap.sailing.gwt.home.shared.partials"> - + .pageTitle { font-size: 1.066666666666667em; font-weight: 700; margin: 0.666666666666667em 0; } + .filter { + margin-bottom: 0.666666666666667em; + } + .filter > input { + width: 100%; + }
+
- \ No newline at end of file + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaActivity.java deleted file mode 100644 index 5d76daf13e9..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaActivity.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.regatta; - -import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; -import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; -import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventActivity; -import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; - -public class RegattaActivity extends AbstractEventActivity implements RegattaView.Presenter { - - public RegattaActivity(RegattaOverviewPlace place, MobileApplicationClientFactory clientFactory) { - super(place, clientFactory); - } - - @Override - protected EventViewBase initView() { - final RegattaView view = new RegattaViewImpl(this); - initQuickfinder(view, true); - return view; - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaView.java deleted file mode 100644 index e6eb2d511e7..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaView.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.regatta; - -import com.sap.sailing.gwt.home.mobile.places.event.EventViewBase; - -public interface RegattaView extends EventViewBase { - - public interface Presenter extends EventViewBase.Presenter { - - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaViewImpl.java deleted file mode 100644 index 13d11714235..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/event/regatta/RegattaViewImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.places.event.regatta; - -import java.util.Collection; - -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Panel; -import com.sap.sailing.gwt.home.mobile.partials.eventsteps.EventSteps; -import com.sap.sailing.gwt.home.mobile.partials.liveraces.RegattaLiveRaces; -import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; -import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; -import com.sap.sailing.gwt.home.mobile.partials.statisticsBox.StatisticsBox; -import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; -import com.sap.sailing.gwt.home.mobile.places.event.AbstractEventView; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetLiveRacesForRegattaAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaStatisticsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetRegattaWithProgressAction; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; - -public class RegattaViewImpl extends AbstractEventView implements RegattaView { - - private EventSteps regattaProgressUi; - private RegattaLiveRaces liveRacesUi; - private MinileaderboardBox leaderboardUi; - private StatisticsBox statisticsUi; - - public RegattaViewImpl(RegattaView.Presenter presenter) { - super(presenter, true, true); - Panel container = new FlowPanel(); - this.initRegattaProgressUi(container); - this.initLiveRaces(container); - this.initLeaderboardUi(container); - this.initRacesNavigation(container); - this.initStatisticsUi(container); - setViewContent(container); - } - - private void initRegattaProgressUi(Panel container) { - regattaProgressUi = new EventSteps(); - refreshManager.add(regattaProgressUi, new GetRegattaWithProgressAction(getEventId(), getRegattaId())); - container.add(regattaProgressUi); - } - - private void initLiveRaces(Panel container) { - liveRacesUi = new RegattaLiveRaces(); - refreshManager.add(liveRacesUi, new GetLiveRacesForRegattaAction(getEventId(), getRegattaId())); - container.add(liveRacesUi); - } - - private void initLeaderboardUi(Panel container) { - leaderboardUi = new MinileaderboardBox(false); - leaderboardUi.setAction(StringMessages.INSTANCE.showAll(), currentPresenter.getRegattaMiniLeaderboardNavigation(getRegattaId())); - refreshManager.add(leaderboardUi, new GetMiniLeaderbordAction(getEventId(), getRegattaId(), 3)); - container.add(leaderboardUi); - } - - private void initStatisticsUi(Panel container) { - statisticsUi = new StatisticsBox(false); - refreshManager.add(statisticsUi, new GetRegattaStatisticsAction(getEventId(), getRegattaId())); - container.add(statisticsUi); - } - - @Override - protected void setQuickFinderValues(Quickfinder quickfinder, Collection regattaMetadatas) { - QuickfinderPresenter.getForRegattaOverview(quickfinder, currentPresenter, regattaMetadatas); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsActivity.java index b0e934efe63..5ded10c5a3b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsActivity.java @@ -3,18 +3,18 @@ package com.sap.sailing.gwt.home.mobile.places.events; import java.util.UUID; import com.google.gwt.activity.shared.AbstractActivity; -import com.google.gwt.core.shared.GWT; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.GetEventListViewAction; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.mobile.places.events.EventsView.Presenter; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; import com.sap.sailing.gwt.home.shared.partials.placeholder.Placeholder; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; public class EventsActivity extends AbstractActivity implements Presenter { private final MobileApplicationClientFactory clientFactory; @@ -31,22 +31,15 @@ public class EventsActivity extends AbstractActivity implements Presenter { panel.setWidget(new Placeholder()); Window.setTitle(TextMessages.INSTANCE.events()); final EventsView view = new EventsViewImpl(this); - clientFactory.getHomeService().getEventListView(new AsyncCallback() { + + clientFactory.getDispatch().execute(new GetEventListViewAction(), + new ActivityCallback(clientFactory, panel) { @Override public void onSuccess(EventListViewDTO eventListView) { panel.setWidget(view.asWidget()); Window.setTitle(place.getTitle()); view.setEvents(eventListView); } - @Override - public void onFailure(Throwable caught) { - // TODO: create mobile error view - GWT.log("error", caught); - // final ErrorView view = - // clientFactory.createErrorView("Error while loading the sailing server instances with service getEventListView()", - // caught); - // panel.setWidget(view.asWidget()); - } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsView.java index 55e6ae83573..c03b18808e1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsView.java @@ -3,8 +3,8 @@ package com.sap.sailing.gwt.home.mobile.places.events; import java.util.UUID; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; public interface EventsView { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.java index 15418c559f7..b8b8be5315f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.java @@ -7,11 +7,11 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListYearDTO; import com.sap.sailing.gwt.home.mobile.partials.recents.EventsOverviewRecent; import com.sap.sailing.gwt.home.mobile.partials.upcoming.EventsOverviewUpcoming; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListYearDTO; public class EventsViewImpl extends Composite implements EventsView { private static StartPageViewUiBinder uiBinder = GWT.create(StartPageViewUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.ui.xml index d790d5c03d3..d7d3cf30f2e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/events/EventsViewImpl.ui.xml @@ -8,7 +8,7 @@ > + type="com.sap.sailing.gwt.common.client.SharedResources" /> diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/searchresult/SearchResultViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/searchresult/SearchResultViewImpl.java new file mode 100644 index 00000000000..52abd266777 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/searchresult/SearchResultViewImpl.java @@ -0,0 +1,29 @@ +package com.sap.sailing.gwt.home.mobile.places.searchresult; + +import java.util.Collection; + +import com.google.gwt.user.client.ui.Composite; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; +import com.sap.sailing.gwt.home.mobile.partials.searchresult.SearchResult; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultView; + +public class SearchResultViewImpl extends Composite implements SearchResultView { + + private final SearchResult searchResultUi; + + public SearchResultViewImpl(MobilePlacesNavigator navigator) { + initWidget(searchResultUi = new SearchResult(navigator)); + } + + @Override + public void setSearchText(String searchText) { + searchResultUi.setSearchText(searchText); + } + + @Override + public void updateSearchResult(String searchText, Collection searchResultItems) { + searchResultUi.updateSearchResult(searchText, searchResultItems); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivity.java index d570f732749..f1f2238c249 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivity.java @@ -4,24 +4,29 @@ import java.util.UUID; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.GetEventSeriesViewAction; import com.sap.sailing.gwt.home.desktop.places.fakeseries.overallleaderboardtab.EventSeriesOverallLeaderboardPlace; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; import com.sap.sailing.gwt.home.mobile.places.series.minileaderboard.SeriesMiniOverallLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; public class SeriesActivity extends AbstractActivity implements SeriesView.Presenter { private final MobileApplicationClientFactory clientFactory; private final AbstractSeriesPlace place; + private EventSeriesViewDTO series; + private final NavigationPathDisplay navigationPathDisplay; - public SeriesActivity(AbstractSeriesPlace place, MobileApplicationClientFactory clientFactory) { + public SeriesActivity(AbstractSeriesPlace place, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + this.navigationPathDisplay = navigationPathDisplay; this.clientFactory = clientFactory; this.place = place; } @@ -29,34 +34,27 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese @Override public void start(final AcceptsOneWidget panel, final EventBus eventBus) { final SeriesContext ctx = place.getCtx(); - if (ctx.getSeriesDTO() != null) { - initUi(panel, eventBus); - } else { - final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); - clientFactory.getHomeService().getEventSeriesViewById(seriesUUID, new AsyncCallback() { - @Override - public void onSuccess(final EventSeriesViewDTO event) { - ctx.updateContext(event); - initUi(panel, eventBus); - } - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract text? - ErrorPlace errorPlace = new ErrorPlace( - "Error while loading the series with service getEventSeriesViewById()"); - // TODO @FM: reload sinnvoll hier? - errorPlace.setComingFrom(place); - clientFactory.getPlaceController().goTo(errorPlace); - } - }); - } + final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); + clientFactory.getDispatch().execute(new GetEventSeriesViewAction(seriesUUID), + new ActivityCallback(clientFactory, panel) { + @Override + public void onSuccess(EventSeriesViewDTO series) { + SeriesActivity.this.series = series; + initUi(panel, eventBus, series); + } + }); } - private void initUi(final AcceptsOneWidget panel, EventBus eventBus) { + private void initUi(final AcceptsOneWidget panel, EventBus eventBus, EventSeriesViewDTO series) { final SeriesView view = new SeriesViewImpl(this); - EventSeriesViewDTO series = getCtx().getSeriesDTO(); view.setQuickFinderValues(series.getDisplayName(), series.getEvents()); panel.setWidget(view.asWidget()); + + initNavigationPath(); + } + + private void initNavigationPath() { + navigationPathDisplay.showNavigationPath(new NavigationItem(series.getDisplayName(), clientFactory.getNavigator().getSeriesNavigation(place, null, false))); } @Override @@ -64,7 +62,7 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese return place.getCtx(); } - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return clientFactory.getDispatch(); } @@ -87,4 +85,9 @@ public class SeriesActivity extends AbstractActivity implements SeriesView.Prese public PlaceNavigation getEventNavigation(String eventId) { return clientFactory.getNavigator().getEventNavigation(eventId, null, false); } + + @Override + public EventSeriesViewDTO getSeriesDTO() { + return series; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivityProxy.java index 567e406a08d..1bd0f3811f5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesActivityProxy.java @@ -2,25 +2,33 @@ package com.sap.sailing.gwt.home.mobile.places.series; import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.ProvidesNavigationPath; import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class SeriesActivityProxy extends AbstractActivityProxy { +public class SeriesActivityProxy extends AbstractActivityProxy implements ProvidesNavigationPath { private final MobileApplicationClientFactory clientFactory; private final AbstractSeriesPlace currentPlace; + private NavigationPathDisplay navigationPathDisplay; public SeriesActivityProxy(AbstractSeriesPlace place, MobileApplicationClientFactory clientFactory) { this.currentPlace = place; this.clientFactory = clientFactory; } + + @Override + public void setNavigationPathDisplay(NavigationPathDisplay navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } @Override protected void startAsync() { GWT.runAsync(new AbstractRunAsyncCallback() { @Override public void onSuccess() { - super.onSuccess(new SeriesActivity(currentPlace, clientFactory)); + super.onSuccess(new SeriesActivity(currentPlace, navigationPathDisplay, clientFactory)); } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesView.java index dbd1fe3f695..2aed79e2ca4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesView.java @@ -3,11 +3,12 @@ package com.sap.sailing.gwt.home.mobile.places.series; import java.util.Collection; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.mobile.places.SeriesLeaderboardNavigationProvider; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; public interface SeriesView { @@ -17,8 +18,11 @@ public interface SeriesView { public interface Presenter extends OverallLeaderboardNavigationProvider, SeriesLeaderboardNavigationProvider { SeriesContext getCtx(); - DispatchSystem getDispatch(); + + SailingDispatchSystem getDispatch(); PlaceNavigation getEventNavigation(String eventId); + + EventSeriesViewDTO getSeriesDTO(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.java index 1961de93f25..3adb52f5082 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.java @@ -8,19 +8,20 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.event.GetSeriesStatisticsAction; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniOverallLeaderbordAction; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.mobile.partials.recents.EventsOverviewRecentYearEvent; import com.sap.sailing.gwt.home.mobile.partials.seriesheader.SeriesHeader; import com.sap.sailing.gwt.home.mobile.partials.statisticsBox.StatisticsBox; import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; +import com.sap.sailing.gwt.home.shared.refresh.LifecycleRefreshManager; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniOverallLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetSeriesStatisticsAction; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; public class SeriesViewImpl extends Composite implements SeriesView { private static final StringMessages MSG = StringMessages.INSTANCE; @@ -40,8 +41,8 @@ public class SeriesViewImpl extends Composite implements SeriesView { public SeriesViewImpl(SeriesView.Presenter presenter) { this.currentPresenter = presenter; - this.refreshManager = new RefreshManager(this, currentPresenter.getDispatch()); - EventSeriesViewDTO series = currentPresenter.getCtx().getSeriesDTO(); + this.refreshManager = new LifecycleRefreshManager(this, currentPresenter.getDispatch()); + EventSeriesViewDTO series = currentPresenter.getSeriesDTO(); eventHeaderUi = new SeriesHeader(series); this.setupStatisticsBox(series); leaderboardUi = new MinileaderboardBox(true); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.ui.xml index 1beee5b8881..190698b5be5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/SeriesViewImpl.ui.xml @@ -8,7 +8,7 @@ > + type="com.sap.sailing.gwt.common.client.SharedResources" /> .headerWrapper { background-color: #f2f2f2; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivity.java index 8037259edd4..e1e553310dc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivity.java @@ -4,23 +4,29 @@ import java.util.UUID; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; -import com.sap.sailing.gwt.home.desktop.places.error.ErrorPlace; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.GetEventSeriesViewAction; import com.sap.sailing.gwt.home.desktop.places.fakeseries.overallleaderboardtab.EventSeriesOverallLeaderboardPlace; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay.NavigationItem; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; public class SeriesMiniOverallLeaderboardActivity extends AbstractActivity implements SeriesMiniOverallLeaderboardView.Presenter { private final MobileApplicationClientFactory clientFactory; private final SeriesMiniOverallLeaderboardPlace place; + private EventSeriesViewDTO series; + private final NavigationPathDisplay navigationPathDisplay; - public SeriesMiniOverallLeaderboardActivity(SeriesMiniOverallLeaderboardPlace place, MobileApplicationClientFactory clientFactory) { + public SeriesMiniOverallLeaderboardActivity(SeriesMiniOverallLeaderboardPlace place, NavigationPathDisplay navigationPathDisplay, MobileApplicationClientFactory clientFactory) { + this.navigationPathDisplay = navigationPathDisplay; this.clientFactory = clientFactory; this.place = place; } @@ -28,34 +34,29 @@ public class SeriesMiniOverallLeaderboardActivity extends AbstractActivity imple @Override public void start(final AcceptsOneWidget panel, final EventBus eventBus) { final SeriesContext ctx = place.getCtx(); - if (ctx.getSeriesDTO() != null) { - initUi(panel, eventBus); - } else { - final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); - clientFactory.getHomeService().getEventSeriesViewById(seriesUUID, new AsyncCallback() { - @Override - public void onSuccess(final EventSeriesViewDTO event) { - ctx.updateContext(event); - initUi(panel, eventBus); - } - @Override - public void onFailure(Throwable caught) { - // TODO @FM: extract text? - ErrorPlace errorPlace = new ErrorPlace( - "Error while loading the series with service getEventSeriesViewById()"); - // TODO @FM: reload sinnvoll hier? - errorPlace.setComingFrom(place); - clientFactory.getPlaceController().goTo(errorPlace); - } - }); - } + final UUID seriesUUID = UUID.fromString(ctx.getSeriesId()); + clientFactory.getDispatch().execute(new GetEventSeriesViewAction(seriesUUID), + new ActivityCallback(clientFactory, panel) { + + @Override + public void onSuccess(final EventSeriesViewDTO series) { + SeriesMiniOverallLeaderboardActivity.this.series = series; + initUi(panel, eventBus, series); + } + }); } - private void initUi(AcceptsOneWidget panel, EventBus eventBus) { + private void initUi(AcceptsOneWidget panel, EventBus eventBus, EventSeriesViewDTO series) { final SeriesMiniOverallLeaderboardView view = new SeriesMiniOverallLeaderboardViewImpl(this); - EventSeriesViewDTO series = getCtx().getSeriesDTO(); view.setQuickFinderValues(series.getDisplayName(), series.getEvents()); panel.setWidget(view.asWidget()); + + initNavigationPath(); + } + + private void initNavigationPath() { + navigationPathDisplay.showNavigationPath(new NavigationItem(series.getDisplayName(), clientFactory.getNavigator().getSeriesNavigation(new SeriesDefaultPlace(getCtx()), null, false)), + new NavigationItem(StringMessages.INSTANCE.overallStandings(), clientFactory.getNavigator().getSeriesNavigation(place, null, false))); } @Override @@ -64,7 +65,7 @@ public class SeriesMiniOverallLeaderboardActivity extends AbstractActivity imple } @Override - public DispatchSystem getDispatch() { + public SailingDispatchSystem getDispatch() { return clientFactory.getDispatch(); } @@ -87,4 +88,9 @@ public class SeriesMiniOverallLeaderboardActivity extends AbstractActivity imple public PlaceNavigation getSeriesNavigation() { return clientFactory.getNavigator().getSeriesNavigation(new SeriesDefaultPlace(getCtx()), null, false); } + + @Override + public EventSeriesViewDTO getSeriesDTO() { + return series; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivityProxy.java index 4d4f8d78f57..6a78c02729b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardActivityProxy.java @@ -2,24 +2,32 @@ package com.sap.sailing.gwt.home.mobile.places.series.minileaderboard; import com.google.gwt.core.client.GWT; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.ProvidesNavigationPath; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; -public class SeriesMiniOverallLeaderboardActivityProxy extends AbstractActivityProxy { +public class SeriesMiniOverallLeaderboardActivityProxy extends AbstractActivityProxy implements ProvidesNavigationPath { private final MobileApplicationClientFactory clientFactory; private final SeriesMiniOverallLeaderboardPlace currentPlace; + private NavigationPathDisplay navigationPathDisplay; public SeriesMiniOverallLeaderboardActivityProxy(SeriesMiniOverallLeaderboardPlace place, MobileApplicationClientFactory clientFactory) { this.currentPlace = place; this.clientFactory = clientFactory; } + + @Override + public void setNavigationPathDisplay(NavigationPathDisplay navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } @Override protected void startAsync() { GWT.runAsync(new AbstractRunAsyncCallback() { @Override public void onSuccess() { - super.onSuccess(new SeriesMiniOverallLeaderboardActivity(currentPlace, clientFactory)); + super.onSuccess(new SeriesMiniOverallLeaderboardActivity(currentPlace, navigationPathDisplay, clientFactory)); } }); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardView.java index c4e2cb84922..3c6eb5092f9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardView.java @@ -3,21 +3,24 @@ package com.sap.sailing.gwt.home.mobile.places.series.minileaderboard; import java.util.Collection; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO; import com.sap.sailing.gwt.home.mobile.places.SeriesLeaderboardNavigationProvider; import com.sap.sailing.gwt.home.mobile.places.series.OverallLeaderboardNavigationProvider; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; public interface SeriesMiniOverallLeaderboardView { public interface Presenter extends OverallLeaderboardNavigationProvider, SeriesLeaderboardNavigationProvider { - DispatchSystem getDispatch(); + SailingDispatchSystem getDispatch(); SeriesContext getCtx(); PlaceNavigation getSeriesNavigation(); + + EventSeriesViewDTO getSeriesDTO(); } Widget asWidget(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.java index 13f5edf07d5..c30a3667813 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.java @@ -8,15 +8,16 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniOverallLeaderbordAction; import com.sap.sailing.gwt.home.mobile.partials.minileaderboard.MinileaderboardBox; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.mobile.partials.seriesheader.SeriesHeader; import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext; +import com.sap.sailing.gwt.home.shared.refresh.LifecycleRefreshManager; import com.sap.sailing.gwt.home.shared.refresh.RefreshManager; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.GetMiniOverallLeaderbordAction; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; public class SeriesMiniOverallLeaderboardViewImpl extends Composite implements SeriesMiniOverallLeaderboardView { private static final StringMessages MSG = StringMessages.INSTANCE; @@ -35,10 +36,9 @@ public class SeriesMiniOverallLeaderboardViewImpl extends Composite implements S public SeriesMiniOverallLeaderboardViewImpl(Presenter presenter) { this.currentPresenter = presenter; minileaderboardUi = new MinileaderboardBox(true); - minileaderboardUi.setShowIfEmpty(true); - eventHeaderUi = new SeriesHeader(presenter.getCtx().getSeriesDTO(), presenter.getSeriesNavigation()); + eventHeaderUi = new SeriesHeader(presenter.getSeriesDTO(), presenter.getSeriesNavigation()); initWidget(uiBinder.createAndBindUi(this)); - RefreshManager refreshManager = new RefreshManager(this, currentPresenter.getDispatch()); + RefreshManager refreshManager = new LifecycleRefreshManager(this, currentPresenter.getDispatch()); SeriesContext ctx = presenter.getCtx(); refreshManager.add(minileaderboardUi, new GetMiniOverallLeaderbordAction(UUID.fromString(ctx.getSeriesId()))); minileaderboardUi.setAction(MSG.details(), presenter.getOverallLeaderboardNavigation()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.ui.xml index 8327bc9e63c..5299e018463 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/series/minileaderboard/SeriesMiniOverallLeaderboardViewImpl.ui.xml @@ -9,7 +9,7 @@ + type="com.sap.sailing.gwt.common.client.SharedResources" /> .headerWrapper { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartActivity.java index 2d21e45842e..7789d31e0d7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartActivity.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartActivity.java @@ -3,18 +3,18 @@ package com.sap.sailing.gwt.home.mobile.places.start; import com.google.gwt.activity.shared.AbstractActivity; import com.google.gwt.event.shared.EventBus; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.home.communication.start.EventQuickfinderDTO; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; +import com.sap.sailing.gwt.home.communication.start.GetRecentEventsAction; +import com.sap.sailing.gwt.home.communication.start.GetStagedEventsAction; import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.mobile.places.start.StartView.Presenter; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.dispatch.start.EventQuickfinderDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.start.GetRecentEventsAction; -import com.sap.sailing.gwt.ui.shared.dispatch.start.GetStagedEventsAction; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; public class StartActivity extends AbstractActivity implements Presenter { private final MobileApplicationClientFactory clientFactory; @@ -29,12 +29,8 @@ public class StartActivity extends AbstractActivity implements Presenter { public void start(final AcceptsOneWidget panel, EventBus eventBus) { Window.setTitle(place.getTitle()); final StartView view = new StartViewImpl(StartActivity.this); - clientFactory.getDispatch().execute(new GetStagedEventsAction(true), new AsyncCallback>() { - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - } - + clientFactory.getDispatch().execute(new GetStagedEventsAction(true), + new ActivityCallback>(clientFactory, panel) { @Override public void onSuccess(ListResult result) { panel.setWidget(view.asWidget()); @@ -42,12 +38,8 @@ public class StartActivity extends AbstractActivity implements Presenter { view.setFeaturedEvents(result.getValues()); } }); - clientFactory.getDispatch().execute(new GetRecentEventsAction(15), new AsyncCallback>() { - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - } - + clientFactory.getDispatch().execute(new GetRecentEventsAction(15), + new ActivityCallback>(clientFactory, panel) { @Override public void onSuccess(ListResult result) { view.setQuickFinderValues(result.getValues()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartView.java index d7ce832dd89..15f482647e2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartView.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartView.java @@ -4,10 +4,10 @@ import java.util.Collection; import java.util.List; import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; +import com.sap.sailing.gwt.home.communication.start.EventQuickfinderDTO; import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; -import com.sap.sailing.gwt.ui.shared.dispatch.start.EventQuickfinderDTO; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; public interface StartView { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.java index f2be6312ef9..45c71621760 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.java @@ -10,13 +10,13 @@ import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.start.EventQuickfinderDTO; import com.sap.sailing.gwt.home.mobile.partials.quickfinder.Quickfinder; import com.sap.sailing.gwt.home.mobile.partials.stage.Stage; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.start.EventQuickfinderDTO; -import com.sap.sailing.gwt.ui.shared.general.EventLinkAndMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; public class StartViewImpl extends Composite implements StartView { private static StartPageViewUiBinder uiBinder = GWT.create(StartPageViewUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.ui.xml index ddfe8324fc8..ca256220158 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.ui.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/places/start/StartViewImpl.ui.xml @@ -7,7 +7,7 @@ > + type="com.sap.sailing.gwt.common.client.SharedResources" /> .headerWrapper { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/SharedResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/SharedResources.java deleted file mode 100644 index 187bf2ce221..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/SharedResources.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.sap.sailing.gwt.home.mobile.resources; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.resources.client.ClientBundle; -import com.google.gwt.resources.client.CssResource; - -public interface SharedResources extends ClientBundle { - public static final SharedResources INSTANCE = GWT.create(SharedResources.class); - - @Source("css/main.gss") - MainCss mainCss(); - - @Source("css/media.gss") - MediaCss mediaCss(); - - - - public interface MainCss extends CssResource{ - String wrapper(); - String navbar(); - String navbar_button(); - String navbar_buttonhidden(); - String navbar_buttonactive(); - String button(); - String buttonsmall(); - String buttonstrong(); - String buttoninactive(); - String buttonprimary(); - String buttonred(); - String buttonrefresh(); - String buttonarrowdown(); - String buttonsearch(); - String buttonarrowrightwhite(); - String label(); - String labellarge(); - String morelink(); - String dummy(); - String mainsection(); - String mainsection_header(); - String mainsection_header_title(); - String mainsection_navigation(); - String lightbox(); - String lightbox_overlay(); - String lightbox_content(); - String lightbox_close(); - String stickyheader(); - String slideto(); - String slidetonav(); - String slidetoactive(); - String fleetcorner(); - } - - public interface MediaCss extends CssResource{ - String grid(); - String stackenblochen(); - String column(); - String columns(); - String small1(); - String small2(); - String small3(); - String small4(); - String small5(); - String small6(); - String small7(); - String small8(); - String small9(); - String small10(); - String small11(); - String small12(); - String smalloffset0(); - String smalloffset1(); - String smalloffset2(); - String smalloffset3(); - String smalloffset4(); - String smalloffset5(); - String smalloffset6(); - String smalloffset7(); - String smalloffset8(); - String smalloffset9(); - String smalloffset10(); - String smalloffset11(); - String showonsmall(); - String hideonsmall(); - String showonmedium(); - String hideonmedium(); - String showonlarge(); - String hideonlarge(); - String smallcentered(); - String smalluncentered(); - String medium1(); - String medium2(); - String medium3(); - String medium4(); - String medium5(); - String medium6(); - String medium7(); - String medium8(); - String medium9(); - String medium10(); - String medium11(); - String medium12(); - String mediumoffset0(); - String mediumoffset1(); - String mediumoffset2(); - String mediumoffset3(); - String mediumoffset4(); - String mediumoffset5(); - String mediumoffset6(); - String mediumoffset7(); - String mediumoffset8(); - String mediumoffset9(); - String mediumoffset10(); - String mediumoffset11(); - String mediumcentered(); - String mediumuncentered(); - String large1(); - String large2(); - String large3(); - String large4(); - String large5(); - String large6(); - String large7(); - String large8(); - String large9(); - String large10(); - String large11(); - String large12(); - String largeoffset0(); - String largeoffset1(); - String largeoffset2(); - String largeoffset3(); - String largeoffset4(); - String largeoffset5(); - String largeoffset6(); - String largeoffset7(); - String largeoffset8(); - String largeoffset9(); - String largeoffset10(); - String largeoffset11(); - String largecentered(); - String largeuncentered(); - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/main.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/main.gss deleted file mode 100644 index 9b2d1fbec02..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/main.gss +++ /dev/null @@ -1,427 +0,0 @@ -/** - * The main styling styles - */ -*, -*:before, -*:after { - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html, -body { - height: 100%; - font-family: 'Open Sans', sans-serif; - font-size: 93.75%; - line-height: 1.333; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -ms-content-zooming: none; -} -figure { - margin: 0; -} -a { - text-decoration: none; - color: #008fcc; -} -a:hover { - text-decoration: underline; -} -a img { - vertical-align: bottom; -} -hr { - font-size: 1rem; - margin: 0; - height: 1px; - border: none; - border-top: 1px solid #ebebeb; -} -h1 { - font-size: 2.133333333333333em; -} -h2 { - font-size: 1.466666666666667em; - font-weight: bold; - color: #008fcc; - margin-top: 0.7em; - margin-bottom: 0.7em; -} -h3 { - font-size: 1.2em; - font-weight: bold; - margin: 0 0 0.5em; -} -h4 { - font-size: 1em; - font-weight: bold; - color: #008fcc; -} -h5 { - font-size: 0.866666666666667em; - font-weight: 600; - color: #008fcc; -} -figure img { - display: block; -} -figcaption { - margin-top: 1.333333333333333em; -} -.wrapper { - font-size: 1rem; - position: relative; - min-height: 100%; - padding-bottom: 11.333333333333334em; -} -.navbar { - font-size: 1rem; -} -.navbar_button { - font-size: 1.2em; - display: inline-block; - font-weight: 600; - color: #666; - border: 1px solid #dedede; - padding: 0.833333333333333em 0.944444444444444em; - background-color: #ebebeb; - -webkit-transition: background-color 0.2s, border-color 0.2s; - -moz-transition: background-color 0.2s, border-color 0.2s; - transition: background-color 0.2s, border-color 0.2s; - text-decoration: none; - margin-right: 0.555555555555556em; -} -.navbar_buttonhidden { - display: block; -} -.navbar_button:hover { - background-color: #dedede; - outline: none; - text-decoration: none; -} -.navbar_buttonactive { - color: #333; - background-color: #fff; - border-bottom: 1px solid #fff; -} -.navbar_buttonactive:hover { - background-color: #dedede; - border-bottom: 1px solid #dedede; -} -.button { - font-size: 1rem; - display: inline-block; - font-weight: 600; - color: #fff; - border: none; - padding: 0.666666666666667em 2em; - border-radius: 0.2em; - background-color: #efaa00; - -webkit-transition: background-color 0.2s; - -moz-transition: background-color 0.2s; - transition: background-color 0.2s; - text-decoration: none; -} -.button:hover { - background-color: #d79900; - outline: none; - text-decoration: none; -} -.buttonsmall { - visibility: inherit; -} -.buttonstrong { - font-size: 0.933333333333333rem; - font-weight: 700; - text-transform: uppercase; - padding: 0.714285714285714em 1.071428571428571em; -} -.buttoninactive { - background-color: #ebebeb; - pointer-events: none; -} -.buttoninactive:hover { - background-color: #ebebeb; -} -.buttonprimary { - background-color: #008fcc; -} -.buttonprimary:hover { - background-color: #0081b8; -} -.buttonred { - background-color: #e94a1b; -} -.buttonred:hover { - background-color: #d54115; -} -.buttonrefresh { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAppJREFUeNrsl09o03AUx9MEi0rXSuhE66wMKoO5YlXYUc966NF5sB4UOoUdFXYdDnYaCj2VFobCpoeo61xZKQrCGIjt2jlxQ0vr0vWwTdYmzZImTZrnwSbUSbemW4tIHuTy4/d4n9/393t/YgAA5F82gw6oA+qAOqAO+J8DFt+etBrPee6gpp4e7ITLhRgwtEItLcnMyqqYI4iOG2T2QAEAoKmPnraYhbTfD3uZLIlCJhigZzqtzcZpyomJOvsqXG59N49USCalfDwmSxxbu15hSZJ5d+VyWwCLYbtd5rc2Vah8PMYuuN0UgaHKHorAUHbB7a4wqZQqprC9XZxzOFoOSBEYWiYnJwEAhJTPVwv21zN4feyokPL51MNQy5+pV0Zjy6+YIjCUW/R6G91fXnv+TIHkEg/utwywtPzooRYwVckQjstlqgAAIP6cn28JYOnL8HCzKgAAImSCASWztWS1ZjgVMjk0pAWQi9+7q/gy7/v7G/VD96uTTPRCL3q8u1vaiESUNWkjEsHMTicTOe/Yt5DPnj5VSgx6MYvrkrJmtHs8pcSglwl32Q6tUO98uHZVVe+3Gg378qtjY7tvgP/+9MmhvkE6hOMgSyIAQDUrNb1BfmX0sVY4zVlczUCQRYahQziuGfLryIgWOM2A7CfPbUWFcvbli4b9Pg7cbEsvpggMlQrJpAIpZIIB+o3JtNf+qmLAfxsfb08vnnM4antxZSeTrteLpXw8pvZifmuzOHvG1r5phiXJPycrjpXy8VitwuohuNw6E3X2tW3cAgCEnum0Cmm/X8nseib8mJigpy3mZuMceKJmwl22I2cHbmEW10XU3NuLIAhSKSwm5FKWFLNTUx3XM2v6P4kOqAPqgDqgDqgD1rVfAwAVWx4m+SNozQAAAABJRU5ErkJggg=="); -} -.buttonrefresh, -.buttonarrowdown { - background-repeat: no-repeat; - background-position: left top; - background-size: cover; - width: 2.333333333333333em; - height: 0; - padding: 2.333333333333333em 0 0 0; - border: 0; - overflow: hidden; - white-space: nowrap; -} -.buttonsearch { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2NTg0MEE1MTVFN0UxMUU0QkNGMTk0Q0UzOUEwNUNFMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo2NTg0MEE1MjVFN0UxMUU0QkNGMTk0Q0UzOUEwNUNFMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjY1ODQwQTRGNUU3RTExRTRCQ0YxOTRDRTM5QTA1Q0UzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjY1ODQwQTUwNUU3RTExRTRCQ0YxOTRDRTM5QTA1Q0UzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+tERf2gAAArFJREFUeNrMmE1kXFEUx28SwjAMjxCGIQwhzCoMQysVugqlhJBVyCqLbELpqtmEUFJddZFNFhVSpd20uqgw1VIhixgSIqREYiKRSExkhNTruZzhOO5999737m3m8DdzZt6773fP/Trn9cRxLBysD/QUNAaKQEP4eQI6xc/voN/Cl0lAC1VBG6Cr2M6aoHegkmX7WpkuKIPW4/R2B1oBRSEAJ0G3BoAz0DaoZbjuGEfBG+CS5kG7oFegiua+MYxYU3Gv7OyUD0AV3CFo2qHhHGhBM2efZQGcUjT4ER+YZg7JRbLF2msljEAiYFkx515nXYXYuS+s3QNQvyvghiJywpPyoAZr/4ULYFXRw5xHQKkh3HY6dmGz/fTifv2S7d+LoLbwa39Ab4gvT6BZm5MkYj3b9Rw5qojN84ZNBB+B+gnzexHOLvGs7lgFVEy6oQNI7asIax+YP2oCLBP/BrQXGHCH+RUT4ADxZcr0NzDgEfMLJsA88dsivN0wP2cCvCZ+/j8ARsw/NwGeEr+IWXNIK7kC7hNfbje1wIA1xQaeCPiL/TYRGHCSzfkfppMkx/K2Q9tMI2X6dU+e9dPmJGmzzVNWanOBorfE5viqbVWnyjSKnqNXY9E7thkp6qywlGvLY8pVVNQpc64Ja4S9ovbJA2QJMyRqm2lrkqoi7W9kKMBrmgpvPEtVN60pGZdBBYeorRnePAxnqYufa4rxFg677MQoSdlL6MtS8xtbDJkgk/6s4J7ow+qgCcVwGyFtC/CLlGBNtlpHXCFtJ3sBQesWUPe4Smc0+5wTZI/j+0GBCa488Acx+xkk7waP8Gw15ZUjoE28lybLT1jyIkTACs4kq0g+JKAV5EMDGiHTzMEQNgyqK+bk424B1EF+7hXdY/u4immNJLopgh2TLxLe4vf5fwIMADtbDGrkqxb2AAAAAElFTkSuQmCC"); - background-color: transparent; - background-size: contain; - background-position: center center; - background-repeat: no-repeat; - width: 1.333333333333333em; - height: 1.333333333333333em; - padding: 0; -} -.buttonsearch:hover { - background-color: transparent; - outline: none; - text-decoration: none; -} -.buttonarrowdown { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAALFJREFUeNrs1TEOgjAUxnFx5iDscgPvwXkYuYdXwBPgAYwrsxPGIAPPvKQkxLQO5UE0+X9J06Ff0186tImI7H45CUCAAAECBAgQIMA1s1+y+dkUpUXna/QGY0Z/q0QztCcJddyauG7UOdHA8XWXKT7khNO47rbArj5kIeQnTrubA0NIS9xioA9piTMB+pBWODPgHGmJ02H6UD/OeaZzerxc+eoAAgQIECBAgAD/AvgWYACm/8hEADYaXwAAAABJRU5ErkJggg=="); - width: 2.666666666666667em; - padding: 2.733333333333333em 0 0 0; -} -.buttonarrowrightwhite:after { - content: ''; - display: inline-block; - margin-left: 0.666666666666667em; - width: 0.466666666666667em; - height: 0.8em; - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAMCAYAAACulacQAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFtJREFUeNpi+P///wEgPgzEokDMgIxBxMn/EHAVXQGIkIBKYCiAqUJXIIEsiVUBA5ojRJEUnGFiwAR/ofQvXLpQjMXpILxeOY8rEEAOegfER4DYAYhfI7sMIMAAiXvwy2upI1UAAAAASUVORK5CYII="); - background-size: contain; - background-repeat: no-repeat; -} -.label { - display: inline-block; - font-size: 0.666666666666667rem; - font-weight: 600; - color: #fff; - padding: 1px 0.666666666666667em; - position: relative; - margin-left: 1em; - height: 1.6em; - line-height: 1.6em; -} -.label:before { - content: ''; - position: absolute; - top: 0; - left: -0.8em; - width: 0; - height: 0; - border-top: 0.8em solid transparent; - border-bottom: 0.8em solid transparent; - border-right: 0.8em solid transparent; -} -.labellarge { - height: 2.4em; - line-height: 2.1em; - margin-left: 1.2em; -} -.labellarge:before { - left: -1.2em; - border-top-width: 1.2em; - border-bottom-width: 1.2em; - border-right-width: 1.2em; -} -.label[data-labeltype='live'] { - background-color: #e94a1b; - vertical-align: middle; - margin-top: -0.416666666666667em; -} -.label[data-labeltype='live']:before { - border-right-color: #e94a1b; -} -.label[data-labeltype='finished'] { - background-color: #8ab54e; - vertical-align: middle; - margin-top: -0.416666666666667em; -} -.label[data-labeltype='finished']:before { - border-right-color: #8ab54e; -} -.label[data-labeltype='next'] { - background-color: #efaa00; - vertical-align: middle; - margin-top: -0.416666666666667em; -} -.label[data-labeltype='next']:before { - border-right-color: #efaa00; -} -.label[data-labeltype='progress'] { - background-color: #efaa00; - vertical-align: middle; - margin-top: -0.416666666666667em; -} -.label[data-labeltype='progress']:before { - border-right-color: #efaa00; -} -.label[data-labeltype='upcoming'] { - color: #f6f9fc; - background-color: #666; - vertical-align: middle; - margin-top: -0.416666666666667em; -} -.label[data-labeltype='upcoming']:before { - border-right-color: #666; -} -.label[data-labeltype='new'], -.label[data-labeltype='updated'] { - background-color: #efaa00; - text-transform: uppercase; - vertical-align: middle; -} -.label[data-labeltype='new']:before, -.label[data-labeltype='updated']:before { - border-right-color: #efaa00; -} -.label[data-labeltype='ess'] { - background-color: #a71724; -} -.label[data-labeltype='ess']:before { - border-right-color: #a71724; -} -.label[data-labeltype='worldcup'] { - background-color: #c79242; -} -.label[data-labeltype='worldcup']:before { - border-right-color: #c79242; -} -.label[data-labeltype='bundesliga'] { - background-color: #005fa7; -} -.label[data-labeltype='bundesliga']:before { - border-right-color: #005fa7; -} -.morelink { - color: #008fcc; - text-transform: uppercase; - text-align: center; - font-size: 0.933333333333333em; - font-weight: 700; - padding: 1.866666666666667em; - display: block; - text-decoration: none; -} -.morelink:hover { - text-decoration: underline; -} -.dummy { - font-size: 1rem; - min-height: 25em; - position: relative; -} -.dummy:after { - content: 'Dummy content'; - position: absolute; - top: 50%; - left: 50%; - font-weight: 700; - font-size: 6em; - color: #f7f7f7; - text-shadow: 1px 1px 0 #eee, 2px 2px 0 #eee, 3px 3px 0 #eee, 4px 4px 0 #eee, 5px 5px 0 #eee, 6px 6px 0 #eee, 7px 7px 0 #eee; - -webkit-transform: translate(-50%, -50%); - -moz-transform: translate(-50%, -50%); - -ms-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); -} -.mainsection { - padding-top: 5.333333333333333em; - padding-bottom: 5.333333333333333em; -} -.mainsection_header { - text-align: center; - margin-bottom: 4em; -} -.mainsection_header p { - margin-top: 0; - font-size: 1.2em; -} -.mainsection_header_title { - margin: 0 0 0.5em; - font-size: 2.4em; - color: #008fcc; - text-align: center; -} -.mainsection_navigation { - text-align: center; -} -.lightbox { - font-size: 1rem; -} -.lightbox_overlay { - display: none; - font-size: 1rem; - background: rgba(0,0,0,0.75); - width: 100%; - height: 100%; - position: fixed; - left: 0; - top: 0; - z-index: 10; - -webkit-transition: opacity 0.3s ease; - -moz-transition: opacity 0.3s ease; - transition: opacity 0.3s ease; -} -.lightbox_content { - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translate(-50%, -50%); - -moz-transform: translate(-50%, -50%); - -ms-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); - max-width: 90%; - max-height: 90%; - overflow: hidden; -} -.lightbox_close { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHVJREFUeNqsk4EJACEIReWawY2bMLh5LME7JNQEE4So/x9pCUTUVvaVuBKSieJpIAuOkYSgaDn6t/EmIdrMHtQHJ4g2/5pd4EFM8w7whK7ZAliQEZWWaVbY3AeqcbuEUhMj4fEZ8XTV6CNlzC7kyjCVxnkKMABEXRUAnXsRRQAAAABJRU5ErkJggg=="); - background-repeat: no-repeat; - background-position: center center; - width: 1.333333333333333em; - height: 0; - padding-top: 1.333333333333333em; - position: absolute; - top: 1.333333333333333em; - right: 1.333333333333333em; - cursor: pointer; - z-index: 2; -} -.stickyheader { - background: inherit; -} -.slideto { - background: inherit; - border-bottom: 0.266666666666667em solid transparent; -} -.slidetonav { - background: inherit; -} -.slidetoactive { - border-bottom-color: #efaa00; - text-decoration: none; - color: #dedede; -} -.slidetoactive:hover { - border-bottom-color: #d79900; -} -.fleetcorner { - position: absolute; - top: 0.333333333333333em; - left: 0.333333333333333em; - width: 0; - height: 0; - border-style: solid; - border-width: 1em 1em 0 0; - color: transparent; -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/media.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/media.gss deleted file mode 100644 index 611ff15f214..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/mobile/resources/css/media.gss +++ /dev/null @@ -1,450 +0,0 @@ -/** - * The grid styles - */ -.grid, -.stackenblochen { - display: block; - width: 100%; - max-width: 80rem; - list-style: none; - margin: 0 auto; - zoom: 1; -} -.grid:before, -.stackenblochen:before, -.grid:after, -.stackenblochen:after { - content: ""; - display: table; -} -.grid:after, -.stackenblochen:after { - clear: both; -} -.grid *, -.stackenblochen * { - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.grid .grid, -.stackenblochen .grid, -.grid .stackenblochen, -.stackenblochen .stackenblochen { - width: auto; - max-width: none; - margin-left: -1rem; - margin-right: -1rem; -} -.column, -.columns { - float: left; - padding: 0 1rem; - position: relative; - width: 100%; -} -.column img, -.columns img { - max-width: 100%; - height: auto; - ms-interpolation-mode: bicubic; -} -.small1 { - width: 8.3333333333333%; -} -.small2 { - width: 16.6666666666667%; -} -.small3 { - width: 25%; -} -.small4 { - width: 33.3333333333333%; -} -.small5 { - width: 41.6666666666667%; -} -.small6 { - width: 50%; -} -.small7 { - width: 58.3333333333333%; -} -.small8 { - width: 66.6666666666667%; -} -.small9 { - width: 75%; -} -.small10 { - width: 83.3333333333333%; -} -.small11 { - width: 91.6666666666667%; -} -.small12 { - width: 100%; -} -.smalloffset0 { - margin-left: 0% !important; -} -.smalloffset1 { - margin-left: 8.3333333333333% !important; -} -.smalloffset2 { - margin-left: 16.6666666666667% !important; -} -.smalloffset3 { - margin-left: 25% !important; -} -.smalloffset4 { - margin-left: 33.3333333333333% !important; -} -.smalloffset5 { - margin-left: 41.6666666666667% !important; -} -.smalloffset6 { - margin-left: 50% !important; -} -.smalloffset7 { - margin-left: 58.3333333333333% !important; -} -.smalloffset8 { - margin-left: 66.6666666666667% !important; -} -.smalloffset9 { - margin-left: 75% !important; -} -.smalloffset10 { - margin-left: 83.3333333333333% !important; -} -.smalloffset11 { - margin-left: 91.6666666666667% !important; -} -.showonsmall { - display: inherit !important; -} -.hideonsmall { - display: none !important; -} -table.showonsmall { - display: table !important; -} -tr.showonsmall { - display: table-row !important; -} -td.showonsmall, -th.showonsmall { - display: table-cell !important; -} -.showonmedium { - display: none !important; -} -.hideonmedium { - display: inherit !important; -} -table.hideonmedium { - display: table !important; -} -tr.hideonmedium { - display: table-row !important; -} -td.hideonmedium, -th.hideonmedium { - display: table-cell !important; -} -.showonlarge { - display: none !important; -} -.hideonlarge { - display: inherit !important; -} -table.hideonlarge { - display: table !important; -} -tr.hideonlarge { - display: table-row !important; -} -td.hideonlarge, -th.hideonlarge { - display: table-cell !important; -} -.column.smallcentered, -.columns.smallcentered { - margin-left: auto; - margin-right: auto; - float: none; -} -.column.smalluncentered, -.columns.smalluncentered { - margin-left: 0; - margin-right: 0; - float: left !important; -} -@media (min-width: 45em) { - .medium1 { - width: 8.3333333333333%; - } - .medium2 { - width: 16.6666666666667%; - } - .medium3 { - width: 25%; - } - .medium4 { - width: 33.3333333333333%; - } - .medium5 { - width: 41.6666666666667%; - } - .medium6 { - width: 50%; - } - .medium7 { - width: 58.3333333333333%; - } - .medium8 { - width: 66.6666666666667%; - } - .medium9 { - width: 75%; - } - .medium10 { - width: 83.3333333333333%; - } - .medium11 { - width: 91.6666666666667%; - } - .medium12 { - width: 100%; - } - .mediumoffset0 { - margin-left: 0% !important; - } - .mediumoffset1 { - margin-left: 8.3333333333333% !important; - } - .mediumoffset2 { - margin-left: 16.6666666666667% !important; - } - .mediumoffset3 { - margin-left: 25% !important; - } - .mediumoffset4 { - margin-left: 33.3333333333333% !important; - } - .mediumoffset5 { - margin-left: 41.6666666666667% !important; - } - .mediumoffset6 { - margin-left: 50% !important; - } - .mediumoffset7 { - margin-left: 58.3333333333333% !important; - } - .mediumoffset8 { - margin-left: 66.6666666666667% !important; - } - .mediumoffset9 { - margin-left: 75% !important; - } - .mediumoffset10 { - margin-left: 83.3333333333333% !important; - } - .mediumoffset11 { - margin-left: 91.6666666666667% !important; - } - .showonsmall { - display: none !important; - } - .hideonsmall { - display: inherit !important; - } - table.hideonsmall { - display: table !important; - } - tr.hideonsmall { - display: table-row !important; - } - td.hideonsmall, - th.hideonsmall { - display: table-cell !important; - } - .showonmedium { - display: inherit !important; - } - .hideonmedium { - display: none !important; - } - table.showonmedium { - display: table !important; - } - tr.showonmedium { - display: table-row !important; - } - td.showonmedium, - th.showonmedium { - display: table-cell !important; - } - .showonlarge { - display: none !important; - } - .hideonlarge { - display: inherit !important; - } - table.hideonlarge { - display: table !important; - } - tr.hideonlarge { - display: table-row !important; - } - td.hideonlarge, - th.hideonlarge { - display: table-cell !important; - } - .column.mediumcentered, - .columns.mediumcentered { - margin-left: auto; - margin-right: auto; - float: none; - } - .column.mediumuncentered, - .columns.mediumuncentered { - margin-left: 0; - margin-right: 0; - float: left !important; - } -} -@media (min-width: 61em) { - .large1 { - width: 8.3333333333333%; - } - .large2 { - width: 16.6666666666667%; - } - .large3 { - width: 25%; - } - .large4 { - width: 33.3333333333333%; - } - .large5 { - width: 41.6666666666667%; - } - .large6 { - width: 50%; - } - .large7 { - width: 58.3333333333333%; - } - .large8 { - width: 66.6666666666667%; - } - .large9 { - width: 75%; - } - .large10 { - width: 83.3333333333333%; - } - .large11 { - width: 91.6666666666667%; - } - .large12 { - width: 100%; - } - .largeoffset0 { - margin-left: 0% !important; - } - .largeoffset1 { - margin-left: 8.3333333333333% !important; - } - .largeoffset2 { - margin-left: 16.6666666666667% !important; - } - .largeoffset3 { - margin-left: 25% !important; - } - .largeoffset4 { - margin-left: 33.3333333333333% !important; - } - .largeoffset5 { - margin-left: 41.6666666666667% !important; - } - .largeoffset6 { - margin-left: 50% !important; - } - .largeoffset7 { - margin-left: 58.3333333333333% !important; - } - .largeoffset8 { - margin-left: 66.6666666666667% !important; - } - .largeoffset9 { - margin-left: 75% !important; - } - .largeoffset10 { - margin-left: 83.3333333333333% !important; - } - .largeoffset11 { - margin-left: 91.6666666666667% !important; - } - .showonsmall { - display: none !important; - } - .hideonsmall { - display: inherit !important; - } - table.hideonsmall { - display: table !important; - } - tr.hideonsmall { - display: table-row !important; - } - td.hideonsmall, - th.hideonsmall { - display: table-cell !important; - } - .showonmedium { - display: none !important; - } - .hideonmedium { - display: inherit !important; - } - table.hideonmedium { - display: table !important; - } - tr.hideonmedium { - display: table-row !important; - } - td.hideonmedium, - th.hideonmedium { - display: table-cell !important; - } - .showonlarge { - display: inherit !important; - } - .hideonlarge { - display: none !important; - } - table.showonlarge { - display: table !important; - } - tr.showonlarge { - display: table-row !important; - } - td.showonlarge, - th.showonlarge { - display: table-cell !important; - } - .column.largecentered, - .columns.largecentered { - margin-left: auto; - margin-right: auto; - float: none; - } - .column.largeuncentered, - .columns.largeuncentered { - margin-left: 0; - margin-right: 0; - float: left !important; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventActionUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/EventActionUtil.java similarity index 77% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventActionUtil.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/EventActionUtil.java index 53d83fe4f4b..a061e3d421e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/EventActionUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/EventActionUtil.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.UUID; @@ -6,12 +6,12 @@ import com.google.gwt.core.shared.GwtIncompatible; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventState; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.general.EventState; import com.sap.sailing.server.RacingEventService; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -24,19 +24,19 @@ public final class EventActionUtil { private EventActionUtil() { } - protected interface CalculationWithEvent { + public interface CalculationWithEvent { ResultWithTTL calculateWithEvent(Event event); } - protected interface RaceCallback { + public interface RaceCallback { void doForRace(RaceContext context); } - protected interface LeaderboardCallback { + public interface LeaderboardCallback { void doForLeaderboard(LeaderboardContext context); } - public static LeaderboardContext getOverallLeaderboardContext(DispatchContext context, UUID eventId) { + public static LeaderboardContext getOverallLeaderboardContext(SailingDispatchContext context, UUID eventId) { RacingEventService service = context.getRacingEventService(); Event event = service.getEvent(eventId); if(!HomeServiceUtil.isFakeSeries(event)) { @@ -47,7 +47,7 @@ public final class EventActionUtil { return new LeaderboardContext(context, event, leaderboardGroup, overallLeaderboard); } - public static LeaderboardContext getLeaderboardContext(DispatchContext context, UUID eventId, String leaderboardId) { + public static LeaderboardContext getLeaderboardContext(SailingDispatchContext context, UUID eventId, String leaderboardId) { RacingEventService service = context.getRacingEventService(); Event event = service.getEvent(eventId); for(LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { @@ -60,7 +60,7 @@ public final class EventActionUtil { throw new DispatchException("The leaderboard is not part of the given event."); } - public static Duration getEventStateDependentTTL(DispatchContext context, UUID eventId, Duration liveTTL) { + public static Duration getEventStateDependentTTL(SailingDispatchContext context, UUID eventId, Duration liveTTL) { Event event = context.getRacingEventService().getEvent(eventId); return getEventStateDependentTTL(event, liveTTL); } @@ -73,7 +73,7 @@ public final class EventActionUtil { return calculateTtlForNonLiveEvent(event, eventState); } - public static ResultWithTTL withLiveRaceOrDefaultSchedule(DispatchContext context, UUID eventId, CalculationWithEvent callback) { + public static ResultWithTTL withLiveRaceOrDefaultSchedule(SailingDispatchContext context, UUID eventId, CalculationWithEvent callback) { Event event = context.getRacingEventService().getEvent(eventId); EventState eventState = HomeServiceUtil.calculateEventState(event); if(eventState != EventState.RUNNING) { @@ -103,7 +103,7 @@ public final class EventActionUtil { return Duration.NULL; } - public static void forLeaderboardsOfEvent(DispatchContext context, UUID eventId, LeaderboardCallback callback) { + public static void forLeaderboardsOfEvent(SailingDispatchContext context, UUID eventId, LeaderboardCallback callback) { RacingEventService service = context.getRacingEventService(); Event event = service.getEvent(eventId); if (event == null) { @@ -112,7 +112,7 @@ public final class EventActionUtil { forLeaderboardsOfEvent(context, event, callback); } - public static void forLeaderboardsOfEvent(DispatchContext context, Event event, LeaderboardCallback callback) { + public static void forLeaderboardsOfEvent(SailingDispatchContext context, Event event, LeaderboardCallback callback) { for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { callback.doForLeaderboard(new LeaderboardContext(context, event, leaderboardGroup, leaderboard)); @@ -120,7 +120,7 @@ public final class EventActionUtil { } } - public static void forRacesOfEvent(final DispatchContext context, UUID eventId, final RaceCallback callback) { + public static void forRacesOfEvent(final SailingDispatchContext context, UUID eventId, final RaceCallback callback) { forLeaderboardsOfEvent(context, eventId, new LeaderboardCallback() { @Override public void doForLeaderboard(LeaderboardContext leaderboardContext) { @@ -129,7 +129,7 @@ public final class EventActionUtil { }); } - public static void forRacesOfRegatta(DispatchContext context, UUID eventId, String regattaName, RaceCallback callback) { + public static void forRacesOfRegatta(SailingDispatchContext context, UUID eventId, String regattaName, RaceCallback callback) { getLeaderboardContext(context, eventId, regattaName).forRaces(callback); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LeaderboardContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LeaderboardContext.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LeaderboardContext.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LeaderboardContext.java index c4634e96be4..d2a2f7654b5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LeaderboardContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LeaderboardContext.java @@ -1,7 +1,9 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.Collections; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -18,15 +20,18 @@ import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.GetMiniLeaderboardDTO; +import com.sap.sailing.gwt.home.communication.event.minileaderboard.MiniLeaderboardItemDTO; +import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata.RegattaState; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaWithProgressDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; -import com.sap.sailing.gwt.ui.shared.eventview.HasRegattaMetadata.RegattaState; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; import com.sap.sailing.server.RacingEventService; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -41,8 +46,9 @@ public class LeaderboardContext { private final LeaderboardGroup leaderboardGroup; private final Leaderboard leaderboard; private final RacingEventService service; + private Boolean hasMultipleFleets = null; - public LeaderboardContext(DispatchContext dispatchContext, Event event, LeaderboardGroup leaderboardGroup, Leaderboard leaderboard) { + public LeaderboardContext(SailingDispatchContext dispatchContext, Event event, LeaderboardGroup leaderboardGroup, Leaderboard leaderboard) { this.service = dispatchContext.getRacingEventService(); this.event = event; this.leaderboardGroup = leaderboardGroup; @@ -53,7 +59,7 @@ public class LeaderboardContext { for(RaceColumn raceColumn : leaderboard.getRaceColumns()) { if(!raceColumn.isCarryForward()) { for(Fleet fleet : raceColumn.getFleets()) { - callback.doForRace(new RaceContext(service, event, leaderboard, raceColumn, fleet, service)); + callback.doForRace(new RaceContext(service, event, this, raceColumn, fleet, service)); } } } @@ -195,6 +201,10 @@ public class LeaderboardContext { public String getLeaderboardName() { return leaderboard.getName(); } + + public String getLeaderboardGroupName() { + return leaderboardGroup.getName(); + } public RegattaMetadataDTO asRegattaMetadataDTO() { RegattaMetadataDTO regattaDTO = new RegattaMetadataDTO(); @@ -233,4 +243,22 @@ public class LeaderboardContext { public Leaderboard getLeaderboard() { return leaderboard; } + + private boolean calculateHasMultipleFleets() { + Set fleets = new HashSet(); + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + Util.addAll(raceColumn.getFleets(), fleets); + if (fleets.size() > 1) { + return true; + } + } + return false; + } + + public boolean hasMultipleFleets() { + if (hasMultipleFleets == null) { + hasMultipleFleets = calculateHasMultipleFleets(); + } + return hasMultipleFleets; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LiveRaceCalculator.java similarity index 60% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LiveRaceCalculator.java index a19ad88cc19..1b6433358c1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/LiveRaceCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/LiveRaceCalculator.java @@ -1,12 +1,13 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.SortedSetResult; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.dispatch.client.SortedSetResult; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; @GwtIncompatible -final class LiveRaceCalculator implements RaceCallback { +public final class LiveRaceCalculator implements RaceCallback { private final RaceRefreshCalculator refreshCalculator = new RaceRefreshCalculator(); private final SortedSetResult result = new SortedSetResult(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/NextRaceFinder.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/NextRaceFinder.java similarity index 81% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/NextRaceFinder.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/NextRaceFinder.java index a651026dddf..2aa6bda0884 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/NextRaceFinder.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/NextRaceFinder.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/OverallRacesStateCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/OverallRacesStateCalculator.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/OverallRacesStateCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/OverallRacesStateCalculator.java index e8e443bd54f..0d7dd1987db 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/OverallRacesStateCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/OverallRacesStateCalculator.java @@ -1,7 +1,7 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; public class OverallRacesStateCalculator implements RaceCallback { private boolean hasLiveRace = false; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatDataCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceCompetitionFormatDataCalculator.java similarity index 87% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatDataCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceCompetitionFormatDataCalculator.java index 4401472e710..8b23fafaf32 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceCompetitionFormatDataCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceCompetitionFormatDataCalculator.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.Collection; import java.util.HashSet; @@ -9,9 +9,12 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; public class RaceCompetitionFormatDataCalculator implements RaceCallback { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceContext.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceContext.java index 0f6e00bcad2..628e9b61bcd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceContext.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.Arrays; import java.util.Collection; @@ -48,16 +48,20 @@ import com.sap.sailing.domain.leaderboard.ScoreCorrection; import com.sap.sailing.domain.tracking.RaceLogWindFixDeclinationHelper; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindWithConfidence; +import com.sap.sailing.gwt.home.communication.event.LiveRaceDTO; +import com.sap.sailing.gwt.home.communication.event.RaceListRaceDTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.race.FlagStateDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.RaceProgressDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.communication.race.wind.SimpleWindDTO; +import com.sap.sailing.gwt.home.communication.race.wind.WindStatisticsDTO; +import com.sap.sailing.gwt.home.shared.ExperimentalFeatures; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.RaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.RaceProgressDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceTrackingState; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceViewState; -import com.sap.sailing.gwt.ui.shared.race.wind.SimpleWindDTO; -import com.sap.sailing.gwt.ui.shared.race.wind.WindStatisticsDTO; import com.sap.sailing.server.RacingEventService; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; @@ -71,6 +75,7 @@ public class RaceContext { private static final long TIME_BEFORE_START_TO_SHOW_RACES_AS_LIVE = 60 * 60 * 1000; // 1 hour private static final long TIME_TO_SHOW_CANCELED_RACES_AS_LIVE = 5 * 60 * 1000; // 5 min private final TimePoint now = MillisecondsTimePoint.now(); + private final LeaderboardContext leaderboardContext; private final Leaderboard leaderboard; private final RaceColumn raceColumn; private final Fleet fleet; @@ -85,13 +90,13 @@ public class RaceContext { private TimePoint finishTime; private boolean finishTimeCalculated = false; private RaceViewState raceViewState; - private List competitors; - public RaceContext(RacingEventService service, Event event, Leaderboard leaderboard, RaceColumn raceColumn, - Fleet fleet, RaceLogResolver raceLogResolver) { + public RaceContext(RacingEventService service, Event event, LeaderboardContext leaderboardContext, + RaceColumn raceColumn, Fleet fleet, RaceLogResolver raceLogResolver) { this.service = service; this.event = event; - this.leaderboard = leaderboard; + this.leaderboardContext = leaderboardContext; + this.leaderboard = leaderboardContext.getLeaderboard(); this.raceColumn = raceColumn; this.raceDefinition = raceColumn.getRaceDefinition(fleet); this.fleet = fleet; @@ -436,22 +441,15 @@ public class RaceContext { if(finishTime == null) { finishTime = HomeServiceUtil.getLiveTimePoint(); } - competitors = leaderboard.getCompetitorsFromBestToWorst(raceColumn, finishTime); + List competitors = leaderboard.getCompetitorsFromBestToWorst(raceColumn, finishTime); if (competitors == null || competitors.isEmpty()) { return null; } if (Util.size(raceColumn.getFleets()) == 1) { return new SimpleCompetitorDTO(competitors.get(0)); } - if (trackedRace == null) { - return null; - } for (Competitor competitor : competitors) { - Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); - if (fleetOfCompetitor == null) { - continue; - } - if (Util.equalsWithNull(fleet.getName(), fleetOfCompetitor.getName())) { + if (isCompetitorInFleet(competitor)) { return new SimpleCompetitorDTO(competitor); } } @@ -471,9 +469,13 @@ public class RaceContext { } private void fillSimpleRaceMetadata(SimpleRaceMetadataDTO dto) { + dto.setLeaderboardGroupName(leaderboardContext.getLeaderboardGroupName()); dto.setStart(getStartTimeAsDate()); dto.setViewState(getLiveRaceViewState()); dto.setTrackingState(getRaceTrackingState()); + if (ExperimentalFeatures.SHOW_RACES_BY_COMPETITOR_FILTER) { + dto.setCompetitors(getCompetitors()); + } } private void fillRaceMetadata(RaceMetadataDTO dto) { @@ -634,11 +636,19 @@ public class RaceContext { public Collection getCompetitors() { Set compotitorDTOs = new HashSet<>(); - if (raceDefinition != null) { - for (Competitor competitor : raceDefinition.getCompetitors()) { - compotitorDTOs.add(new SimpleCompetitorDTO(competitor)); + if (leaderboardContext.hasMultipleFleets()) { + boolean isFleetRacing = Util.size(raceColumn.getFleets()) > 1; + for (Competitor competitor : leaderboard.getCompetitors()) { + if (!isFleetRacing || isCompetitorInFleet(competitor)) { + compotitorDTOs.add(new SimpleCompetitorDTO(competitor)); + } } } return compotitorDTOs; } + + private boolean isCompetitorInFleet(Competitor competitor) { + Fleet fleetOfCompetitor = raceColumn.getFleetOfCompetitor(competitor); + return fleetOfCompetitor != null && Util.equalsWithNull(fleet.getName(), fleetOfCompetitor.getName()); + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListDataCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceListDataCalculator.java similarity index 76% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListDataCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceListDataCalculator.java index e305a16ffde..74851af70e6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceListDataCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceListDataCalculator.java @@ -1,10 +1,11 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.Collection; import java.util.TreeSet; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; +import com.sap.sailing.gwt.home.communication.event.RaceListRaceDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; @GwtIncompatible public class RaceListDataCalculator implements RaceCallback { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceRefreshCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceRefreshCalculator.java similarity index 83% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceRefreshCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceRefreshCalculator.java index 3999ea047f2..6d659526c74 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RaceRefreshCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RaceRefreshCalculator.java @@ -1,8 +1,8 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.RaceCallback; -import com.sap.sailing.gwt.ui.shared.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.server.EventActionUtil.RaceCallback; import com.sap.sse.common.Duration; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattaProgressCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RegattaProgressCalculator.java similarity index 88% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattaProgressCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RegattaProgressCalculator.java index fe80646e8d4..d85f8d8b707 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/RegattaProgressCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/RegattaProgressCalculator.java @@ -1,14 +1,14 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressFleetDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaProgressSeriesDTO; -import com.sap.sailing.gwt.ui.shared.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaProgressDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaProgressFleetDTO; +import com.sap.sailing.gwt.home.communication.regatta.RegattaProgressSeriesDTO; public class RegattaProgressCalculator implements EventActionUtil.RaceCallback { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContextImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/SailingDispatchContextImpl.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContextImpl.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/SailingDispatchContextImpl.java index ad2a06c5611..f899c91716b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DispatchContextImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/SailingDispatchContextImpl.java @@ -1,16 +1,20 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; +package com.sap.sailing.gwt.home.server; +import java.net.URL; import java.util.Date; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import com.google.gwt.core.shared.GwtIncompatible; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.server.HomeServiceUtil; import com.sap.sailing.news.EventNewsService; import com.sap.sailing.server.RacingEventService; @GwtIncompatible -public class DispatchContextImpl implements DispatchContext { +public class SailingDispatchContextImpl implements SailingDispatchContext { private final RacingEventService racingEventService; private final EventNewsService eventNewsService; private final Date currentClientTime; @@ -18,7 +22,7 @@ public class DispatchContextImpl implements DispatchContext { private String clientLocaleName; private final HttpServletRequest request; - public DispatchContextImpl(Date currentClientTime, RacingEventService racingEventService, EventNewsService eventNewsService, String clientLocaleName, HttpServletRequest request) { + public SailingDispatchContextImpl(Date currentClientTime, RacingEventService racingEventService, EventNewsService eventNewsService, String clientLocaleName, HttpServletRequest request) { this.currentClientTime = currentClientTime; this.racingEventService = racingEventService; this.eventNewsService = eventNewsService; @@ -58,4 +62,10 @@ public class DispatchContextImpl implements DispatchContext { public HttpServletRequest getRequest() { return request; } + + @Override + public URL getRequestBaseURL() throws DispatchException { + return HomeServiceUtil.getRequestBaseURL(request); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/StatisticsCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/StatisticsCalculator.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/StatisticsCalculator.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/StatisticsCalculator.java index 14dc4a56363..129f21fc258 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/StatisticsCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/StatisticsCalculator.java @@ -1,7 +1,9 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; +package com.sap.sailing.gwt.home.server; +import java.util.HashSet; import java.util.Iterator; import java.util.NavigableSet; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -17,9 +19,10 @@ import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.MarkPassing; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.home.communication.event.statistics.EventStatisticsDTO; +import com.sap.sailing.gwt.home.server.EventActionUtil.LeaderboardCallback; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventActionUtil.LeaderboardCallback; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -33,7 +36,8 @@ public class StatisticsCalculator implements LeaderboardCallback { private static final boolean CALCULATE_MAX_SPEED = false; private static final boolean CALCULATE_SAILED_MILES = true; - private int competitors, races, trackedRaces, regattas; + private Set competitors = new HashSet<>(); + private int races, trackedRaces, regattas; private long numberOfGPSFixes, numberOfWindFixes; private Distance totalDistanceTraveled = Distance.NULL; private Triple maxSpeed = null; @@ -41,7 +45,6 @@ public class StatisticsCalculator implements LeaderboardCallback { @Override public void doForLeaderboard(LeaderboardContext context) { - competitors += HomeServiceUtil.calculateCompetitorsCount(context.getLeaderboard()); races += HomeServiceUtil.calculateRaceCount(context.getLeaderboard()); trackedRaces += HomeServiceUtil.calculateTrackedRaceCount(context.getLeaderboard()); regattas++; @@ -59,6 +62,7 @@ public class StatisticsCalculator implements LeaderboardCallback { private void doForTrackedRace(TrackedRace trackedRace) { for (Competitor competitor : trackedRace.getRace().getCompetitors()) { + competitors.add(competitor); doForCompetitor(trackedRace, competitor); } for (Mark mark : trackedRace.getMarks()) { @@ -136,7 +140,7 @@ public class StatisticsCalculator implements LeaderboardCallback { public ResultWithTTL getResult() { totalDistanceTraveled = totalDistanceTraveled == Distance.NULL ? null : totalDistanceTraveled; return new ResultWithTTL(Duration.ONE_MINUTE.times(5), new EventStatisticsDTO(regattas, - competitors, races, trackedRaces, numberOfGPSFixes, numberOfWindFixes, maxSpeed, totalDistanceTraveled)); + competitors.size(), races, trackedRaces, numberOfGPSFixes, numberOfWindFixes, maxSpeed, totalDistanceTraveled)); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/dispatch/DispatchRPCImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/servlets/DispatchRPCServletImpl.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/dispatch/DispatchRPCImpl.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/servlets/DispatchRPCServletImpl.java index 63f9f1de4fb..5bdc5bbf0d1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/dispatch/DispatchRPCImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/server/servlets/DispatchRPCServletImpl.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.ui.server.dispatch; +package com.sap.sailing.gwt.home.server.servlets; import java.util.UUID; import java.util.logging.Level; @@ -7,28 +7,29 @@ import java.util.logging.Logger; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; +import com.sap.sailing.gwt.dispatch.client.Action; +import com.sap.sailing.gwt.dispatch.client.Result; +import com.sap.sailing.gwt.dispatch.client.ResultWrapper; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.dispatch.client.exceptions.ServerDispatchException; +import com.sap.sailing.gwt.dispatch.client.rpcimpl.DispatchRPC; +import com.sap.sailing.gwt.dispatch.client.rpcimpl.RequestWrapper; +import com.sap.sailing.gwt.home.communication.SailingDispatchContext; +import com.sap.sailing.gwt.home.server.SailingDispatchContextImpl; import com.sap.sailing.gwt.ui.server.Activator; import com.sap.sailing.gwt.ui.server.ProxiedRemoteServiceServlet; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContextImpl; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.RequestWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.ServerDispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.rpc.DispatchRPC; import com.sap.sailing.news.EventNewsService; import com.sap.sailing.server.RacingEventService; import com.sap.sse.util.ServiceTrackerFactory; -public class DispatchRPCImpl extends ProxiedRemoteServiceServlet implements DispatchRPC { +public class DispatchRPCServletImpl extends ProxiedRemoteServiceServlet implements DispatchRPC { private static final long serialVersionUID = -245230476512348999L; - private static final Logger logger = Logger.getLogger(DispatchRPCImpl.class.getName()); + private static final Logger logger = Logger.getLogger(DispatchRPCServletImpl.class.getName()); private final ServiceTracker racingEventServiceTracker; private final ServiceTracker eventNewsServiceTracker; - public DispatchRPCImpl() { + public DispatchRPCServletImpl() { final BundleContext context = Activator.getDefault(); racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class); @@ -36,13 +37,14 @@ public class DispatchRPCImpl extends ProxiedRemoteServiceServlet implements Disp } @Override - public > ResultWrapper execute(RequestWrapper request) throws DispatchException { + public > ResultWrapper execute( + RequestWrapper request) throws DispatchException { A action = request.getAction(); long start = System.currentTimeMillis(); try { R executionResult = action.execute( - new DispatchContextImpl(request.getCurrentClientTime(), + new SailingDispatchContextImpl(request.getCurrentClientTime(), racingEventServiceTracker.getService(), eventNewsServiceTracker.getService(), request .getClientLocaleName(), getThreadLocalRequest())); return new ResultWrapper(executionResult); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/ExperimentalFeatures.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/ExperimentalFeatures.java index a3869602e27..dcfbd043171 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/ExperimentalFeatures.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/ExperimentalFeatures.java @@ -9,6 +9,11 @@ public class ExperimentalFeatures { * Show overview tab for single-regatta events and series events. */ public static final boolean SHOW_SINGLE_REGATTA_OVERVIEW = true; + + /** + * Show overview tab for regattas in multiregatta events. + */ + public static final boolean SHOW_MULTIREGATTAEVENT_REGATTA_OVERVIEW = true; /** * Provide option to show races in competition format */ @@ -34,4 +39,32 @@ public class ExperimentalFeatures { * Provide button to show the competitor analytics in fullscreen view (work in progress) */ public static final boolean SHOW_COMPETITOR_ANALYTICS_FULLSCREEN_VIEWER = false; + /** + * Provide textbox to filter races by competitor in desktop regatta races tab + */ + public static final boolean SHOW_RACES_BY_COMPETITOR_FILTER = true; + /** + * Using {@link com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay} to generically render the breadcrumbs in desktop UI (currently causes styling problems). + */ + public static final boolean USE_NAVIGATION_PATH_DISPLAY_ON_DESKTOP = true; + /** + * Using {@link com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay} to generically render navigation menu extensions. + */ + public static final boolean USE_NAVIGATION_PATH_DISPLAY_ON_MOBILE = true; + /** + * Enables/disables the link to the race board on mobile races view (competition format), in case of a tracked race + */ + public static final boolean ENABLE_RACE_VIEWER_LINK_ON_MOBILE = false; + /** + * Provide selection to filter regattas by boat category on mobile multiregatta event overview + */ + public static final boolean SHOW_BOAT_CATEGORY_FILTER_ON_MOBILE = true; + /** + * Provide a button to toogle autoplay in desktop fullscreen image gallery viewer. + */ + public static final boolean SHOW_AUTOPLAY_IMAGES_ON_DESKTOP = true; + /** + * Provide a button to toogle autoplay in mobile fullscreen image gallery viewer. + */ + public static final boolean SHOW_AUTOPLAY_IMAGES_ON_MOBILE = true; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/SwitchingEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/SwitchingEntryPoint.java index 5d162e39111..5de6daf8c97 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/SwitchingEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/SwitchingEntryPoint.java @@ -1,5 +1,11 @@ package com.sap.sailing.gwt.home.shared; +import static com.sap.sailing.gwt.common.client.formfactor.MetaTagUtil.SCALE_VALUE_LARGE; +import static com.sap.sailing.gwt.common.client.formfactor.MetaTagUtil.SCALE_VALUE_NORMAL; +import static com.sap.sailing.gwt.common.client.formfactor.MetaTagUtil.SCALE_VALUE_SMALL; +import static com.sap.sailing.gwt.common.client.formfactor.MetaTagUtil.SCALE_VALUE_SMALLER; +import static com.sap.sailing.gwt.common.client.formfactor.MetaTagUtil.setViewportToDeviceWidth; + import java.util.logging.Logger; import com.google.gwt.core.client.EntryPoint; @@ -8,15 +14,14 @@ import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Document; -import com.google.gwt.dom.client.MetaElement; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceHistoryMapper; -import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.user.client.Cookies; import com.google.gwt.user.client.Window; -import com.google.gwt.user.client.Window.Navigator; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; +import com.sap.sailing.gwt.common.client.SharedResources; +import com.sap.sailing.gwt.common.client.formfactor.DeviceDetector; import com.sap.sailing.gwt.home.desktop.DesktopEntryPoint; import com.sap.sailing.gwt.home.mobile.MobileEntryPoint; import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper; @@ -27,21 +32,18 @@ import com.sap.sailing.gwt.home.shared.app.MobileSupport; public class SwitchingEntryPoint implements EntryPoint { private static Logger LOG = Logger.getLogger(SwitchingEntryPoint.class.getName()); private static final String SAPSAILING_MOBILE = "sapsailing_mobile"; - private static final RegExp isMobileRegExp = RegExp.compile( - "Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini|Mobile Safari", "i"); - private static final RegExp tabletBlacklistRegExp = RegExp.compile( - "iPad|" // Apple ;-) - + "Nexus 7|Nexus 10|Nexus 9|" // Google Tablets - + "PlayBook|" // Blackberry - + "KFAPWI|" // Kindle Fire HD - + "GT-P|SM-T|SM-P" // Galaxy Tab (https://en.wikipedia.org/wiki/Samsung_Galaxy ; http://forum.xda-developers.com/wiki/Samsung/Model_naming_scheme) - , "i"); + private final PlaceHistoryMapper hisMap = GWT.create(ApplicationHistoryMapper.class); private final ApplicationPlaceUpdater placeUpdater = new ApplicationPlaceUpdater(); @Override public void onModuleLoad() { + Document.get().getElementById("loading").removeFromParent(); LOG.info("Start switching entry point"); + + SharedResources.INSTANCE.mediaCss().ensureInjected(); + SharedResources.INSTANCE.mainCss().ensureInjected(); + String hash = Window.Location.getHash(); if (hash != null && hash.startsWith("#")) { hash = hash.substring(1); @@ -62,11 +64,11 @@ public class SwitchingEntryPoint implements EntryPoint { startDesktop(); } } else { - if (isMobile()) { - LOG.info("Identified mobile browser by user agent"); + if (DeviceDetector.isMobile()) { + LOG.info("Identified mobile (smartphone) browser by user agent"); startMobile(); } else { - LOG.info("Using desktop browser"); + LOG.info("Using desktop version"); startDesktop(); } } @@ -86,47 +88,13 @@ public class SwitchingEntryPoint implements EntryPoint { || (place instanceof MobileSupport && ((MobileSupport) place).hasMobileVersion()); } - /** - * Uses regular expression and user agent to detect mobile device. - * - * @return - */ - public static boolean isMobile() { - boolean isMobile = isMobileRegExp.test(Navigator.getUserAgent()); - LOG.info("Navigator user agent matched mobile regex: " + isMobile); - if(!isMobile) { - return false; - } - return !isTablet(); - } - - /** - * Uses regular expression and user agent to detect tablet device. - * - * @return - */ - public static boolean isTablet() { - boolean isTablet = tabletBlacklistRegExp.test(Navigator.getUserAgent()); - LOG.info("Navigator user agent matched tablet regex: " + isTablet); - return isTablet; - } - - /** - * Convinience method - * - * @return - */ - public static boolean isDesktop() { - return !isMobile(); - } - public static boolean viewIsLockedToDesktop() { String userWantsMobileUi = Cookies.getCookie(SAPSAILING_MOBILE); return (userWantsMobileUi != null && !Boolean.parseBoolean(userWantsMobileUi)); } public static void switchToDesktop() { - if (isDesktop()) { + if (DeviceDetector.isDesktop()) { Cookies.removeCookie(SAPSAILING_MOBILE); } else { // only force "not mobile" on mobile devices @@ -141,7 +109,7 @@ public class SwitchingEntryPoint implements EntryPoint { } public static void switchToMobile() { - if (isMobile()) { + if (DeviceDetector.isMobile()) { Cookies.removeCookie(SAPSAILING_MOBILE); } else { // only force mobile version on desktop @@ -188,22 +156,11 @@ public class SwitchingEntryPoint implements EntryPoint { } private void configureDesktopHeader() { - if(isTablet()) { - metaElement("viewport", "width=device-width=900,initial-scale=0.75,maximum-scale=2"); - } else { - metaElement("viewport", "width=device-width,initial-scale=0.5,maximum-scale=2"); - } + setViewportToDeviceWidth(DeviceDetector.isTablet() ? SCALE_VALUE_SMALLER : SCALE_VALUE_SMALL, SCALE_VALUE_LARGE); } private void configureMobileHeader() { - metaElement("viewport", "width=device-width,initial-scale=1,maximum-scale=1"); - } - - private void metaElement(String name, String content) { - MetaElement metaElement = Document.get().createMetaElement(); - metaElement.setName(name); - metaElement.setContent(content); - Document.get().getHead().appendChild(metaElement); + setViewportToDeviceWidth(SCALE_VALUE_NORMAL, SCALE_VALUE_NORMAL); } public static void reloadApp() { @@ -215,4 +172,4 @@ public class SwitchingEntryPoint implements EntryPoint { }); } -} \ No newline at end of file +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/AbstractPlaceNavigator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/AbstractPlaceNavigator.java index 3abf1f75cae..675b8c831d2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/AbstractPlaceNavigator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/AbstractPlaceNavigator.java @@ -5,6 +5,7 @@ import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceController; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Window; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultPlace; public abstract class AbstractPlaceNavigator implements PlaceNavigator { protected final PlaceController placeController; @@ -48,6 +49,10 @@ public abstract class AbstractPlaceNavigator implements PlaceNavigator { String placeHistoryToken = mapper.getToken(destinationPlace); History.newItem(placeHistoryToken, false); } + + public PlaceNavigation getSearchResultNavigation(String searchQuery) { + return createGlobalPlaceNavigation(new SearchResultPlace(searchQuery)); + } @Override public boolean isStandaloneServer() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityCallback.java new file mode 100644 index 00000000000..338253d9178 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityCallback.java @@ -0,0 +1,27 @@ +package com.sap.sailing.gwt.home.shared.app; + +import com.google.gwt.activity.shared.Activity; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; + +/** + * Convenience implementation of {@link AsyncCallback} interface to use in {@link Activity} subclasses. + * It implements {@link AsyncCallback#onFailure(Throwable)} method for a consistent error handling. + */ +public abstract class ActivityCallback implements AsyncCallback { + + private final ErrorAndBusyClientFactory clientFactory; + private final AcceptsOneWidget contentPanel; + + public ActivityCallback(ErrorAndBusyClientFactory clientFactory, AcceptsOneWidget contentPanel) { + this.clientFactory = clientFactory; + this.contentPanel = contentPanel; + } + + @Override + public final void onFailure(Throwable caught) { + contentPanel.setWidget(clientFactory.createErrorView("Error while loading data!", caught)); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityProxyCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityProxyCallback.java new file mode 100644 index 00000000000..36e8e09a935 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ActivityProxyCallback.java @@ -0,0 +1,32 @@ +package com.sap.sailing.gwt.home.shared.app; + +import com.google.gwt.place.shared.Place; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; +import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; +import com.sap.sse.gwt.client.mvp.ClientFactory; + +/** + * Convenience implementation of {@link AsyncCallback} interface to use in {@link AbstractActivityProxy} subclasses. + * It implements {@link AsyncCallback#onFailure(Throwable)} method for a consistent error handling. + */ +public abstract class ActivityProxyCallback implements AsyncCallback { + + private final ClientFactory clientFactory; + private final Place comingFromPlace; + + public ActivityProxyCallback(ClientFactory clientFactory, Place comingFromPlace) { + this.clientFactory = clientFactory; + this.comingFromPlace = comingFromPlace; + } + + @Override + public final void onFailure(Throwable caught) { + // TODO @FM: extract text? + ErrorPlace errorPlace = new ErrorPlace("Error while loading page: " + comingFromPlace.getClass().getSimpleName() + "!"); + // TODO @FM: reload sinnvoll hier? + errorPlace.setComingFrom(comingFromPlace); + clientFactory.getPlaceController().goTo(errorPlace); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationHistoryMapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationHistoryMapper.java index 365d73020b8..614edb7551d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationHistoryMapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationHistoryMapper.java @@ -19,15 +19,16 @@ import com.sap.sailing.gwt.home.desktop.places.fakeseries.analyticstab.EventSeri import com.sap.sailing.gwt.home.desktop.places.fakeseries.eventstab.SeriesEventsPlace; import com.sap.sailing.gwt.home.desktop.places.fakeseries.leaderboardstab.EventSeriesLeaderboardsPlace; import com.sap.sailing.gwt.home.desktop.places.fakeseries.overallleaderboardtab.EventSeriesOverallLeaderboardPlace; -import com.sap.sailing.gwt.home.desktop.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.desktop.places.sponsoring.SponsoringPlace; import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace; import com.sap.sailing.gwt.home.mobile.places.event.latestnews.LatestNewsPlace; import com.sap.sailing.gwt.home.mobile.places.event.minileaderboard.MiniLeaderboardPlace; import com.sap.sailing.gwt.home.mobile.places.series.minileaderboard.SeriesMiniOverallLeaderboardPlace; +import com.sap.sailing.gwt.home.shared.places.error.ErrorPlace; import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace; import com.sap.sailing.gwt.home.shared.places.events.EventsPlace; import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace; +import com.sap.sailing.gwt.home.shared.places.searchresult.SearchResultPlace; import com.sap.sailing.gwt.home.shared.places.solutions.SolutionsPlace; import com.sap.sailing.gwt.home.shared.places.start.StartPlace; @@ -56,7 +57,8 @@ import com.sap.sailing.gwt.home.shared.places.start.StartPlace; // Mobile only places: LatestNewsPlace.Tokenizer.class, MiniLeaderboardPlace.Tokenizer.class, - SeriesMiniOverallLeaderboardPlace.Tokenizer.class + SeriesMiniOverallLeaderboardPlace.Tokenizer.class, + ErrorPlace.Tokenizer.class }) public interface ApplicationHistoryMapper extends PlaceHistoryMapper { } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationPlaceUpdater.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationPlaceUpdater.java index 08ac1a0ff54..a9bce22ac0f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationPlaceUpdater.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ApplicationPlaceUpdater.java @@ -98,7 +98,7 @@ public class ApplicationPlaceUpdater { private Place getRealSeriesPlace(SeriesPlace place) { String seriesId = place.getEventUuidAsString(); - SeriesContext context = new SeriesContext().withId(seriesId); + SeriesContext context = new SeriesContext(seriesId); // TODO evaluate additional parameters diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ClientFactoryWithDispatch.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ClientFactoryWithDispatch.java new file mode 100644 index 00000000000..60873539a5d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ClientFactoryWithDispatch.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.shared.app; + +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; + +public interface ClientFactoryWithDispatch { + SailingDispatchSystem getDispatch(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/NavigationPathDisplay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/NavigationPathDisplay.java new file mode 100644 index 00000000000..a93ff9eeef9 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/NavigationPathDisplay.java @@ -0,0 +1,30 @@ +package com.sap.sailing.gwt.home.shared.app; + +public interface NavigationPathDisplay { + + void showNavigationPath(NavigationItem... navigationPath); + + public class NavigationItem implements Runnable { + private final String displayName; + private final PlaceNavigation destination; + public NavigationItem(String displayName, PlaceNavigation destination) { + super(); + this.displayName = displayName; + this.destination = destination; + } + + public String getDisplayName() { + return displayName; + } + + public String getTargetUrl() { + return destination.getTargetUrl(); + } + + @Override + public void run() { + destination.goToPlace(); + } + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ProvidesNavigationPath.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ProvidesNavigationPath.java new file mode 100644 index 00000000000..9f1fd13e059 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ProvidesNavigationPath.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.shared.app; + +public interface ProvidesNavigationPath { + + void setNavigationPathDisplay(NavigationPathDisplay display); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ResettableNavigationPathDisplay.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ResettableNavigationPathDisplay.java new file mode 100644 index 00000000000..e6f39c027aa --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/ResettableNavigationPathDisplay.java @@ -0,0 +1,7 @@ +package com.sap.sailing.gwt.home.shared.app; + +public interface ResettableNavigationPathDisplay extends NavigationPathDisplay { + + void reset(); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/SailingActivityManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/SailingActivityManager.java new file mode 100644 index 00000000000..fb7e03f84a7 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/app/SailingActivityManager.java @@ -0,0 +1,60 @@ +package com.sap.sailing.gwt.home.shared.app; + +import com.google.gwt.activity.shared.Activity; +import com.google.gwt.activity.shared.ActivityMapper; +import com.google.web.bindery.event.shared.EventBus; +import com.sap.sse.gwt.client.mvp.CustomActivityManager; + +public class SailingActivityManager extends CustomActivityManager { + + private NPD navigationPathDisplay; + private Activity currentActivity; + + public SailingActivityManager(ActivityMapper mapper, EventBus eventBus) { + super(mapper, eventBus); + } + + public void setNavigationPathDisplay(NPD navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } + + protected NPD getNavigationPathDisplay() { + return navigationPathDisplay; + } + + @Override + protected void beforeActivityStart(Activity activity) { + this.currentActivity = activity; + super.beforeActivityStart(activity); + if(navigationPathDisplay != null) { + navigationPathDisplay.reset(); + if(activity instanceof ProvidesNavigationPath) { + ProvidesNavigationPath providesNavigationPath = (ProvidesNavigationPath) activity; + providesNavigationPath.setNavigationPathDisplay(new NavigationPathDisplayDelegate(activity, navigationPathDisplay)); + afterNavigationPathIsSetToActivity(activity); + } + } + } + + protected void afterNavigationPathIsSetToActivity(Activity activity) { + } + + private class NavigationPathDisplayDelegate implements NavigationPathDisplay { + + private final Activity associatedActivity; + private final NavigationPathDisplay realNavigationPathDisplay; + + public NavigationPathDisplayDelegate(Activity associatedActivity, NavigationPathDisplay realNavigationPathDisplay) { + this.associatedActivity = associatedActivity; + this.realNavigationPathDisplay = realNavigationPathDisplay; + } + + @Override + public void showNavigationPath(NavigationItem... navigationPath) { + if(associatedActivity == currentActivity) { + realNavigationPathDisplay.showNavigationPath(navigationPath); + } + } + + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchAsync.java deleted file mode 100644 index 8f9bbe91410..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchAsync.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sap.sailing.gwt.home.shared.dispatch; - -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; - -public interface DispatchAsync { - - > void execute(A action, AsyncCallback callback); - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystem.java deleted file mode 100644 index 102b5b3c2a0..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/dispatch/DispatchSystem.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sailing.gwt.home.shared.dispatch; - -import java.util.Date; - -public interface DispatchSystem extends DispatchAsync { - Date getCurrentServerTime(); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyView.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyView.gss new file mode 100644 index 00000000000..f4d234a5a3f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyView.gss @@ -0,0 +1,4 @@ +.busy { + margin: 2em auto 10em; + display: block; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewImpl.java new file mode 100644 index 00000000000..27c28089e2c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewImpl.java @@ -0,0 +1,14 @@ +package com.sap.sailing.gwt.home.shared.partials.busy; + +import com.google.gwt.user.client.ui.Composite; +import com.sap.sailing.gwt.ui.client.refresh.BusyView; +import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator; + +public class BusyViewImpl extends Composite implements BusyView { + + public BusyViewImpl() { + BusyViewResources.INSTANCE.css().ensureInjected(); + initWidget(new SimpleBusyIndicator(true, 1.0f, "", BusyViewResources.INSTANCE.css().busy())); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewResources.java new file mode 100644 index 00000000000..f029320561d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/busy/BusyViewResources.java @@ -0,0 +1,16 @@ +package com.sap.sailing.gwt.home.shared.partials.busy; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; + +public interface BusyViewResources extends ClientBundle { + public static final BusyViewResources INSTANCE = GWT.create(BusyViewResources.class); + + @Source("BusyView.gss") + LocalCss css(); + + public interface LocalCss extends CssResource { + String busy(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/countdown/Countdown.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/countdown/Countdown.java index 79c607355de..1b320204199 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/countdown/Countdown.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/countdown/Countdown.java @@ -17,14 +17,14 @@ import com.sap.sailing.gwt.common.client.LinkUtil; import com.sap.sailing.gwt.common.client.SharedResources; import com.sap.sailing.gwt.common.client.SharedResources.MainCss; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewRaceTickerStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewRegattaTickerStageDTO; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewTickerStageDTO; import com.sap.sailing.gwt.home.desktop.partials.stage.StageResources; import com.sap.sailing.gwt.home.shared.app.PlaceNavigation; import com.sap.sailing.gwt.home.shared.partials.countdown.CountdownResources.LocalCss; import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewRaceTickerStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewRegattaTickerStageDTO; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewTickerStageDTO; public class Countdown extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.css b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.css similarity index 80% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.css rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.css index b5ccb421b93..085222b66fd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.css +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.css @@ -15,3 +15,7 @@ margin-right: 20px; margin-bottom: 20px; } +.reload_page_button { + text-align: center; + margin-bottom: 3em; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.java similarity index 91% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.java index e7e84f6455c..0b47912f1d2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.home.desktop.partials.error; +package com.sap.sailing.gwt.home.shared.partials.error; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.DivElement; @@ -28,14 +28,12 @@ public class ErrorMessage extends Composite { public ErrorMessage(String errorMessageDetail, Throwable errorReason, Command reloadCommand) { this(TextMessages.INSTANCE.errorMessageLoadingData(), errorMessageDetail, errorReason, reloadCommand); - } public ErrorMessage(String errorMessage, String errorMessageDetail, Throwable errorReason, Command reloadCommand) { ErrorMessageResources.INSTANCE.css().ensureInjected(); initWidget(uiBinder.createAndBindUi(this)); this.reloadCommand = reloadCommand; - this.setHeight(Window.getClientHeight() + "px"); if (errorMessage != null && !errorMessage.isEmpty()) { this.errorMessage.setInnerText(errorMessage); @@ -47,6 +45,10 @@ public class ErrorMessage extends Composite { Window.setStatus(errorMessageDetail); } + public void addReloadPageButtonStyleNames(String styleNames) { + reloadPageAnchor.addStyleName(styleNames); + } + @UiHandler("reloadPageAnchor") void reloadPage(ClickEvent e) { if (reloadCommand != null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.ui.xml b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.ui.xml new file mode 100644 index 00000000000..4b50dbd5417 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessage.ui.xml @@ -0,0 +1,20 @@ + + + + + + +
+
+
+
+
+
+ +
+ + + +
+
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessageResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessageResources.java similarity index 85% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessageResources.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessageResources.java index 82f7a2e4c1f..d84a5e46815 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/partials/error/ErrorMessageResources.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/error/ErrorMessageResources.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.home.desktop.partials.error; +package com.sap.sailing.gwt.home.shared.partials.error; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; @@ -15,5 +15,6 @@ public interface ErrorMessageResources extends ClientBundle { String error_message(); String error_message_detail(); String reload_page_message(); + String reload_page_button(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractFilterWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractFilterWidget.java new file mode 100644 index 00000000000..7ff11dd700d --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractFilterWidget.java @@ -0,0 +1,33 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.Composite; +import com.sap.sse.common.filter.Filter; + +public abstract class AbstractFilterWidget extends Composite implements FilterWidget { + + private final List> valueChangeHandlers = new ArrayList<>(); + + @Override + public HandlerRegistration addFilterValueChangeHandler(final FilterValueChangeHandler handler) { + valueChangeHandlers.add(handler); + handler.onFilterValueChanged(getFilter()); + return new HandlerRegistration() { + @Override + public void removeHandler() { + valueChangeHandlers.remove(handler); + } + }; + } + + protected void notifyValueChangeHandlers() { + Filter filter = getFilter(); + for(FilterValueChangeHandler valueChangeHandler : valueChangeHandlers) { + valueChangeHandler.onFilterValueChanged(filter); + } + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSelectionFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSelectionFilter.java new file mode 100644 index 00000000000..1145d778826 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSelectionFilter.java @@ -0,0 +1,67 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; +import com.google.gwt.text.shared.AbstractRenderer; +import com.google.gwt.user.client.ui.ValueListBox; +import com.sap.sse.common.filter.Filter; + +public abstract class AbstractSelectionFilter extends AbstractFilterWidget { + + private final ValueListBox valueListBox = new ValueListBox<>(new AbstractRenderer() { + @Override + public String render(C object) { + return getFilterItemLabel(object); + } + }); + + protected AbstractSelectionFilter() { + valueListBox.addValueChangeHandler(new ValueChangeHandler() { + @Override + public void onValueChange(ValueChangeEvent event) { + valueListBox.getElement().blur(); + notifyValueChangeHandlers(); + } + }); + initWidget(valueListBox); + } + + @Override + public void setSelectableValues(Collection selectableValues) { + List acceptableValues = new ArrayList<>(selectableValues); + acceptableValues.add(0, null); + C previouslySelectedValue = valueListBox.getValue(); + valueListBox.setValue(null); + valueListBox.setAcceptableValues(acceptableValues); + if (previouslySelectedValue != null && selectableValues.contains(previouslySelectedValue)) { + valueListBox.setValue(previouslySelectedValue); + } + } + + @Override + public Filter getFilter() { + return new SelectionFilter(); + } + + protected abstract C getFilterCriteria(T object); + + protected abstract String getFilterItemLabel(C item); + + private class SelectionFilter implements Filter { + @Override + public boolean matches(T object) { + C selectedFilterItem = valueListBox.getValue(); + return selectedFilterItem == null || selectedFilterItem.equals(getFilterCriteria(object)); + } + + @Override + public String getName() { + return getClass().getSimpleName(); + } + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSuggestBoxFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSuggestBoxFilter.java new file mode 100644 index 00000000000..304329b4b88 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractSuggestBoxFilter.java @@ -0,0 +1,156 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.logical.shared.SelectionEvent; +import com.google.gwt.event.logical.shared.SelectionHandler; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay; +import com.google.gwt.user.client.ui.SuggestBox.SuggestionCallback; +import com.google.gwt.user.client.ui.SuggestOracle; +import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; +import com.google.gwt.user.client.ui.TextBox; +import com.sap.sse.common.Util; +import com.sap.sse.common.filter.AbstractListFilter; + +public abstract class AbstractSuggestBoxFilter extends AbstractTextInputFilter { + + private final ContainsSuggestOracle suggestOracle = new ContainsSuggestOracle(); + private final List suggestionObjectList = new ArrayList<>(); + protected final AbstractListFilter suggestionMatchingFilter = new AbstractListFilter() { + @Override + public Iterable getStrings(C value) { + return getMatchingStrings(value); + } + }; + + protected AbstractSuggestBoxFilter(String placeholderText) { + final SuggestBox suggestBox = new SuggestBox(suggestOracle, new TextBox(), new CustomSuggestionDisplay()); + initWidgets(suggestBox, placeholderText); + suggestBox.addSelectionHandler(new SelectionHandler() { + @Override + public void onSelection(SelectionEvent event) { + AbstractSuggestBoxFilter.super.update(); + } + }); + } + + @Override + public void setSelectableValues(Collection selectableValues) { + suggestionObjectList.clear(); + suggestionObjectList.addAll(selectableValues); + } + + protected abstract String createSuggestionKeyString(C value); + + protected abstract String createSuggestionAdditionalDisplayString(C value); + + protected abstract Iterable getMatchingStrings(C value); + + private class CustomSuggestionDisplay extends DefaultSuggestionDisplay { + @Override + protected void showSuggestions(SuggestBox suggestBox, Collection suggestions, + boolean isDisplayStringHTML, boolean isAutoSelectEnabled, SuggestionCallback callback) { + super.showSuggestions(suggestBox, suggestions, isDisplayStringHTML, isAutoSelectEnabled, callback); + getPopupPanel().getElement().getStyle().setProperty("maxWidth", suggestBox.getOffsetWidth(), Unit.PX); + } + } + + private class ContainsSuggestOracle extends SuggestOracle { + + @Override + public void requestDefaultSuggestions(Request request, Callback callback) { + setSuggestions(request, callback, suggestionObjectList, Collections.emptyList()); + } + + @Override + public void requestSuggestions(Request request, Callback callback) { + Iterable queryTokens = Collections.singleton(request.getQuery().trim()); + setSuggestions(request, callback, suggestionMatchingFilter.applyFilter(queryTokens, suggestionObjectList), queryTokens); + } + + private void setSuggestions(Request request, Callback callback, Iterable suggestionObjects, Iterable queryTokens) { + List suggestions = new ArrayList<>(); + List normalizedQueryTokens = new ArrayList<>(); + for (String token : queryTokens) { + normalizedQueryTokens.add(token.toLowerCase()); + } + int count = 0; + for (C match : suggestionObjects) { + suggestions.add(new SimpleSuggestion(match, normalizedQueryTokens)); + if (++count >= request.getLimit()) { + break; + } + } + Response response = new Response(suggestions); + response.setMoreSuggestionsCount(Util.size(suggestionObjects) - count); + callback.onSuggestionsReady(request, response); + } + + @Override + public boolean isDisplayStringHTML() { + return true; + } + } + + private class SimpleSuggestion implements Suggestion { + + private static final String STRONG_TAG_OPEN = "", STRONG_TAG_CLOSE = ""; + private static final String ITALIC_TAG_OPEN = "", ITALIC_TAG_CLOSE = ""; + private final C suggestObject; + private final Iterable queryTokens; + + private SimpleSuggestion(C suggestObject, Iterable queryTokens) { + this.suggestObject = suggestObject; + this.queryTokens = queryTokens; + } + + @Override + public String getDisplayString() { + SafeHtmlBuilder builder = new SafeHtmlBuilder(); + appendHighlighted(builder, createSuggestionKeyString(suggestObject)); + builder.append(SafeHtmlUtils.fromTrustedString(ITALIC_TAG_OPEN)); + builder.append(SafeHtmlUtils.fromSafeConstant(" - ")); + appendHighlighted(builder, createSuggestionAdditionalDisplayString(suggestObject)); + builder.append(SafeHtmlUtils.fromTrustedString(ITALIC_TAG_CLOSE)); + return builder.toSafeHtml().asString(); + } + + private void appendHighlighted(SafeHtmlBuilder builder, String displayString) { + String normalizedString = displayString.toLowerCase(); + int cursor = 0; + while(true) { + int index = displayString.length(); + String matchToken = null; + for (String token : queryTokens) { + int matchIndex = normalizedString.indexOf(token, cursor); + if (matchIndex >= 0 && matchIndex < index) { + index = matchIndex; + matchToken = token; + } + } + if (matchToken != null) { + builder.appendEscaped(displayString.substring(cursor, index)); + builder.append(SafeHtmlUtils.fromTrustedString(STRONG_TAG_OPEN)); + builder.appendEscaped(displayString.substring(index, index + matchToken.length())); + builder.append(SafeHtmlUtils.fromTrustedString(STRONG_TAG_CLOSE)); + cursor = index + matchToken.length(); + } else { + builder.appendEscaped(displayString.substring(cursor)); + break; + } + } + } + + @Override + public String getReplacementString() { + return createSuggestionKeyString(suggestObject); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextBoxFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextBoxFilter.java new file mode 100644 index 00000000000..3550eca5e68 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextBoxFilter.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.Collection; + +import com.google.gwt.user.client.ui.TextBox; + +public abstract class AbstractTextBoxFilter extends AbstractTextInputFilter { + + protected AbstractTextBoxFilter(String placeholderText) { + initWidgets(new TextBox(), placeholderText); + } + + @Override + public void setSelectableValues(Collection selectableValues) { + // Nothing to do in a free text filter + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextInputFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextInputFilter.java new file mode 100644 index 00000000000..0eb71be8c0e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/AbstractTextInputFilter.java @@ -0,0 +1,75 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HasValue; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sse.common.filter.Filter; + +public abstract class AbstractTextInputFilter extends AbstractFilterWidget { + + private final FlowPanel containerUi = new FlowPanel(); + private final Button clearButtonUi = new Button("X"); + private HasValue textInputUi; + + protected > AbstractTextInputFilter() { + FilterWidgetResources.INSTANCE.css().ensureInjected(); + containerUi.addStyleName(FilterWidgetResources.INSTANCE.css().input_filter_container()); + initWidget(containerUi); + } + + private void initTextInputWidget(Widget textInputWidget, String placeholderText, KeyUpHandler handler) { + textInputWidget.getElement().setAttribute("placeholder", placeholderText); + textInputWidget.addStyleName(FilterWidgetResources.INSTANCE.css().input_filter_text_input()); + textInputWidget.addHandler(handler, KeyUpEvent.getType()); + containerUi.add(textInputWidget); + } + + private void initClearButtonWidget(ClickHandler handler) { + clearButtonUi.addStyleName(FilterWidgetResources.INSTANCE.css().input_filter_clear_button()); + clearButtonUi.addClickHandler(handler); + containerUi.add(clearButtonUi); + clearButtonUi.setEnabled(false); + } + + private String getTextInputValue() { + return textInputUi == null ? "" : textInputUi.getValue(); + } + + protected > void initWidgets(W textInputWidget, String placeholderText) { + this.textInputUi = textInputWidget; + TextInputFilterHandler handler = new TextInputFilterHandler(); + initTextInputWidget(textInputWidget.asWidget(), placeholderText, handler); + initClearButtonWidget(handler); + } + + @Override + public final Filter getFilter() { + return getFilter(getTextInputValue().trim()); + } + + protected void update() { + clearButtonUi.setEnabled(!getTextInputValue().isEmpty()); + notifyValueChangeHandlers(); + } + + protected abstract Filter getFilter(String searchString); + + private class TextInputFilterHandler implements ClickHandler, KeyUpHandler { + @Override + public void onKeyUp(KeyUpEvent event) { + update(); + } + @Override + public void onClick(ClickEvent event) { + textInputUi.setValue(null); + update(); + } + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterPresenter.java new file mode 100644 index 00000000000..3e9a7e0da16 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterPresenter.java @@ -0,0 +1,59 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; +import com.sap.sse.common.filter.Filter; + +public abstract class FilterPresenter> { + private final Filter alwaysMatchingFilter = new Filter() { + @Override + public boolean matches(T object) { + return true; + } + + @Override + public String getName() { + return "alwaysMatchingFilter"; + } + }; + private final FilterWidget filterWidget; + + public FilterPresenter(FilterWidget filterWidget) { + this.filterWidget = filterWidget; + this.filterWidget.asWidget().setVisible(false); + } + + protected abstract List> getCurrentValueChangeHandlers(); + + protected void addHandler(FilterValueChangeHandler handler) { + this.filterWidget.addFilterValueChangeHandler(handler); + } + + public void update() { + Set filterableValues = new TreeSet<>(); + for (FilterValueChangeHandler valueChangeHandler : getCurrentValueChangeHandlers()) { + filterableValues.addAll(valueChangeHandler.getFilterableValues()); + } + this.filterWidget.asWidget().setVisible(!filterableValues.isEmpty()); + this.filterWidget.setSelectableValues(filterableValues); + Filter filter = filterableValues.isEmpty() ? alwaysMatchingFilter : this.filterWidget.getFilter(); + for (FilterValueChangeHandler valueChangeHandler : getCurrentValueChangeHandlers()) { + valueChangeHandler.onFilterValueChanged(filter); + } + } + + public RefreshableWidget getRefreshableWidgetWrapper(final RefreshableWidget wrappedWidget) { + return new RefreshableWidget() { + @Override + public void setData(D data) { + wrappedWidget.setData(data); + FilterPresenter.this.update(); + } + }; + } + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterValueChangeHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterValueChangeHandler.java new file mode 100644 index 00000000000..df4e5701a0b --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterValueChangeHandler.java @@ -0,0 +1,13 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.Collection; + +import com.sap.sse.common.filter.Filter; + +public interface FilterValueChangeHandler { + + void onFilterValueChanged(Filter filter); + + Collection getFilterableValues(); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.gss new file mode 100644 index 00000000000..69357763538 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.gss @@ -0,0 +1,44 @@ +@external gwt-SuggestBoxPopup, item, item-selected; +.gwt-SuggestBoxPopup { + text-align: left; + cursor: pointer; + border: .066666666666667rem solid #dedede; +/* border: 1px solid #666; */ + border-top: 0; + background-color: #f2f2f2; + z-index: 999; +} +.gwt-SuggestBoxPopup .item { +/* border: 1px dotted #aaa; */ + border: .066666666666667rem solid #dedede; + padding: 0 .666666666666667rem; + line-height: 2em; + white-space: normal !important; +} +.gwt-SuggestBoxPopup .item-selected { + background-color: #efaa00; +} +.input_filter_container { + text-align: right; + font-weight: 600; + position: relative; +} +.input_filter_text_input { + display: inline-block; + padding: .333333333333333em 3.066666666666667em .333333333333333em .666666666666667em; + line-height: 1.333333333333333em; + color: #666; + background-color: #f2f2f2; + border: .066666666666667em solid #dedede; + width: 100%; +} +.input_filter_clear_button { + position: absolute; + top: .066666666666667em; + bottom: .066666666666667em; + right: .066666666666667em; + border-radius: 0; + display: inline-block; + padding: .333333333333333em .666666666666667em; + line-height: 1.333333333333333em; +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.java new file mode 100644 index 00000000000..d3065250d31 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidget.java @@ -0,0 +1,16 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.Collection; + +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.IsWidget; +import com.sap.sse.common.filter.Filter; + +public interface FilterWidget extends IsWidget { + + HandlerRegistration addFilterValueChangeHandler(FilterValueChangeHandler handler); + + Filter getFilter(); + + void setSelectableValues(Collection selectableValues); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidgetResources.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidgetResources.java new file mode 100644 index 00000000000..25403ae5466 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/FilterWidgetResources.java @@ -0,0 +1,19 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; + +public interface FilterWidgetResources extends ClientBundle { + + public static final FilterWidgetResources INSTANCE = GWT.create(FilterWidgetResources.class); + + @Source("FilterWidget.gss") + LocalCss css(); + + public interface LocalCss extends CssResource { + String input_filter_container(); + String input_filter_text_input(); + String input_filter_clear_button(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RacesByCompetitorTextBoxFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RacesByCompetitorTextBoxFilter.java new file mode 100644 index 00000000000..dfdbdcc98e5 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RacesByCompetitorTextBoxFilter.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Util; +import com.sap.sse.common.filter.Filter; + +public class RacesByCompetitorTextBoxFilter extends AbstractSuggestBoxFilter { + + private final RacesByCompetitorFilter filter = new RacesByCompetitorFilter(); + + public RacesByCompetitorTextBoxFilter() { + super(StringMessages.INSTANCE.competitorsFilter()); + } + + @Override + protected Filter getFilter(String searchValue) { + this.filter.keywords.clear(); + if (searchValue != null && !searchValue.isEmpty()) { + this.filter.keywords.add(searchValue.trim()); + } + return filter; + } + + @Override + protected String createSuggestionAdditionalDisplayString(SimpleCompetitorDTO value) { + return value.getName(); + } + + @Override + protected String createSuggestionKeyString(SimpleCompetitorDTO value) { + return value.getSailID(); + } + + @Override + protected Iterable getMatchingStrings(SimpleCompetitorDTO value) { + return Arrays.asList(value.getName(), value.getSailID()); + } + + private class RacesByCompetitorFilter implements Filter { + + private final List keywords = new ArrayList<>(); + + @Override + public boolean matches(SimpleRaceMetadataDTO object) { + return keywords.isEmpty() || !Util.isEmpty(suggestionMatchingFilter.applyFilter(keywords, object.getCompetitors())); + } + + @Override + public String getName() { + return getClass().getSimpleName(); + } + + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RegattaByBootCategoryFilter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RegattaByBootCategoryFilter.java new file mode 100644 index 00000000000..69cf703fd4a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/filter/RegattaByBootCategoryFilter.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.home.shared.partials.filter; + +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public class RegattaByBootCategoryFilter extends AbstractSelectionFilter { + + @Override + protected String getFilterCriteria(RegattaMetadataDTO object) { + return object.getBoatCategory(); + } + + @Override + protected String getFilterItemLabel(String item) { + return item == null ? StringMessages.INSTANCE.all() : item; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/lowerthird/LowerThird.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/lowerthird/LowerThird.java index da9c16b9412..b8a74830cf0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/lowerthird/LowerThird.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/lowerthird/LowerThird.java @@ -14,10 +14,10 @@ import com.google.gwt.user.client.EventListener; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.client.LinkUtil; import com.sap.sailing.gwt.common.client.SharedResources; +import com.sap.sailing.gwt.home.communication.event.LabelType; import com.sap.sailing.gwt.home.shared.utils.ButtonUtil; import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil; import com.sap.sailing.gwt.home.shared.utils.ButtonUtil.ButtonType; -import com.sap.sailing.gwt.ui.shared.general.LabelType; public class LowerThird extends Widget { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleet.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleet.java new file mode 100644 index 00000000000..6ffc2ea473e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleet.java @@ -0,0 +1,42 @@ +package com.sap.sailing.gwt.home.shared.partials.regattacompetition; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO; +import com.sap.sailing.gwt.home.communication.race.FleetMetadataDTO; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionFleetView; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.impl.RGBColor; + +public abstract class AbstractRegattaCompetitionFleet extends Widget implements RegattaCompetitionFleetView { + + protected AbstractRegattaCompetitionFleet(RaceCompetitionFormatFleetDTO fleet) { + setElement(getMainUiElement()); + getFleetNameUiElement().setInnerText(fleet.getFleet().getFleetName()); + getFleetCornerUiElement().getStyle().setProperty("borderTopColor", fleet.getFleet().getFleetColor()); + if (fleet.getFleet().isDefaultFleet()) { + onDefaultFleetName(); + } else { + getElement().getStyle().setBackgroundColor(getBackgroundColor(fleet.getFleet())); + } + } + + private String getBackgroundColor(FleetMetadataDTO fleet) { + Triple rgbValues = new RGBColor(fleet.getFleetColor()).getAsRGB(); + return "rgba(" + rgbValues.getA() + "," + rgbValues.getB() + "," + rgbValues.getC() + ", 0.1)"; + } + + @Override + public void doFilter(boolean filter) { + setVisible(!filter); + } + + protected abstract void onDefaultFleetName(); + + protected abstract Element getMainUiElement(); + + protected abstract Element getFleetNameUiElement(); + + protected abstract Element getFleetCornerUiElement(); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleetRace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleetRace.java new file mode 100644 index 00000000000..e4c1047f198 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionFleetRace.java @@ -0,0 +1,80 @@ +package com.sap.sailing.gwt.home.shared.partials.regattacompetition; + +import static com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil.shortTimeFormatter; +import static com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil.weekdayMonthAbbrDayDateFormatter; +import static com.sap.sse.common.impl.MillisecondsTimePoint.now; + +import java.util.Date; + +import com.google.gwt.dom.client.AnchorElement; +import com.google.gwt.dom.client.Element; +import com.google.gwt.text.client.DateTimeFormatRenderer; +import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.gwt.common.client.DateUtil; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceViewState; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public abstract class AbstractRegattaCompetitionFleetRace extends UIObject implements RegattaCompetitionRaceView { + + private static final StringMessages I18N = StringMessages.INSTANCE; + protected final AnchorElement anchorUiElement; + + protected AbstractRegattaCompetitionFleetRace(SimpleRaceMetadataDTO race, String raceViewerUrl) { + this.anchorUiElement = getMainUiElement(); + if (raceViewerUrl != null) { + anchorUiElement.setTarget("_blank"); + anchorUiElement.setHref(raceViewerUrl); + } + setupRaceState(race.getTrackingState(), race.getViewState()); + getRaceNameUiElement().setInnerText(race.getRaceName()); + setupRaceStart(race.getStart()); + setElement(anchorUiElement); + } + + private void setupRaceState(RaceTrackingState trackingState, RaceViewState viewState) { + // boolean isUntrackedRace = trackingState != RaceTrackingState.TRACKED_VALID_DATA; + boolean isUntrackedRace = isUntrackedRace(trackingState); + if (viewState == RaceViewState.RUNNING) { + anchorUiElement.addClassName(getRaceLiveStyleName()); + getRaceStateUiElement().setInnerText(isUntrackedRace ? I18N.live() : I18N.actionWatch()); + } else if (viewState == RaceViewState.FINISHED) { + getRaceStateUiElement().setInnerText(isUntrackedRace ? I18N.raceIsFinished() : I18N.actionAnalyze()); + } else { + anchorUiElement.addClassName(getRacePlannedStyleName()); + if (viewState == RaceViewState.SCHEDULED) getRaceStateUiElement().setInnerText(I18N.raceIsPlanned()); + else getRaceStateUiElement().setInnerText(viewState.getLabel()); + } + setStyleName(anchorUiElement, getRaceUntrackedStyleName(), isUntrackedRace); + } + + private void setupRaceStart(Date startDate) { + if (startDate != null) { + boolean showTime = DateUtil.isSameDayOfMonth(now().asDate(), startDate); + DateTimeFormatRenderer renderer = showTime ? shortTimeFormatter : weekdayMonthAbbrDayDateFormatter; + getRaceDateUiElement().setInnerText(renderer.render(startDate)); + } + } + + protected abstract AnchorElement getMainUiElement(); + + protected abstract Element getRaceNameUiElement(); + + protected abstract Element getRaceStateUiElement(); + + protected abstract Element getRaceDateUiElement(); + + protected abstract String getRaceLiveStyleName(); + + protected abstract String getRacePlannedStyleName(); + + protected abstract String getRaceUntrackedStyleName(); + + // TODO: As long as there is no mobile race viewer, show all races as untracked + // This is a temporary method to be able to fulfill this requirement + protected boolean isUntrackedRace(RaceTrackingState trackingState) { + return trackingState != RaceTrackingState.TRACKED_VALID_DATA; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionSeries.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionSeries.java new file mode 100644 index 00000000000..f4ab5ffb7f0 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/AbstractRegattaCompetitionSeries.java @@ -0,0 +1,35 @@ +package com.sap.sailing.gwt.home.shared.partials.regattacompetition; + +import static com.sap.sailing.domain.common.LeaderboardNameConstants.DEFAULT_SERIES_NAME; + +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionSeriesView; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public abstract class AbstractRegattaCompetitionSeries extends Composite implements RegattaCompetitionSeriesView { + + private static final StringMessages I18N = StringMessages.INSTANCE; + + protected AbstractRegattaCompetitionSeries(RaceCompetitionFormatSeriesDTO series) { + initWidget(getMainUiWidget()); + setSeriesName(DEFAULT_SERIES_NAME.equals(series.getSeriesName()) ? I18N.races() : series.getSeriesName()); + String flightInfoText = series.getFlightCount() != series.getRaceCount() ? I18N.flightsCount(series.getFlightCount()) : ""; + String raceInfoText = series.getRaceCount() > 0 ? I18N.racesCount(series.getRaceCount()) : ""; + String competitorInfoText = series.getCompetitorCount() > 0 ? I18N.competitorsCount(series.getCompetitorCount()) : ""; + setRacesFlightAndCompetitorInfo(flightInfoText, raceInfoText, competitorInfoText); + } + + @Override + public void doFilter(boolean filter) { + setVisible(!filter); + } + + protected abstract Widget getMainUiWidget(); + + protected abstract void setSeriesName(String seriesName); + + protected abstract void setRacesFlightAndCompetitorInfo(String flightInfoText, String raceInfoText, String competitorInfoText); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionPresenter.java new file mode 100644 index 00000000000..1544761f633 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionPresenter.java @@ -0,0 +1,105 @@ +package com.sap.sailing.gwt.home.shared.partials.regattacompetition; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO.RaceTrackingState; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionFleetView; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionRaceView; +import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompetitionView.RegattaCompetitionSeriesView; +import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; +import com.sap.sse.common.filter.Filter; + +public abstract class RegattaCompetitionPresenter implements + RefreshableWidget>, + FilterValueChangeHandler { + + private final RegattaCompetitionView view; + private Filter latestRacesByCompetitorFilter; + + private Map>> structure = new HashMap<>(); + + public RegattaCompetitionPresenter(RegattaCompetitionView view) { + this.view = view; + } + + @Override + public void setData(ListResult data) { + view.clearContent(); + structure.clear(); + for (RaceCompetitionFormatSeriesDTO series : data.getValues()) { + RegattaCompetitionSeriesView seriesView = view.addSeriesView(series); + Map> fleetMap = new HashMap<>(); + structure.put(seriesView, fleetMap); + for (RaceCompetitionFormatFleetDTO fleet : series.getFleets()) { + RegattaCompetitionFleetView fleetView = seriesView.addFleetView(fleet); + fleetView.setNumberOfFleetsInSeries(series.getFleets().size()); + Map raceMap = new HashMap<>(); + fleetMap.put(fleetView, raceMap); + for (SimpleRaceMetadataDTO race : fleet.getRaces()) { + boolean tracked = race.getTrackingState() == RaceTrackingState.TRACKED_VALID_DATA; + String raceViewerUrl = tracked ? getRaceViewerURL(race) : null; + RegattaCompetitionRaceView raceView = fleetView.addRaceView(race, raceViewerUrl); + raceMap.put(raceView, race); + } + } + if (latestRacesByCompetitorFilter != null) { + applyFilter(seriesView, latestRacesByCompetitorFilter); + } + } + } + + @Override + public void onFilterValueChanged(Filter filter) { + latestRacesByCompetitorFilter = filter; + for (RegattaCompetitionSeriesView seriesView : structure.keySet()) { + applyFilter(seriesView, latestRacesByCompetitorFilter); + } + } + + @Override + public Collection getFilterableValues() { + Set filterableValues = new HashSet<>(); + for (Map> series : structure.values()) { + for (Map fleet : series.values()) { + for (SimpleRaceMetadataDTO raceMetadata : fleet.values()) { + filterableValues.addAll(raceMetadata.getCompetitors()); + } + } + } + return filterableValues; + } + + private void applyFilter(RegattaCompetitionSeriesView seriesView, Filter filter) { + int unfilteredFleetCount = 0; + Map> fleetMap = structure.get(seriesView); + for (Entry> fleetEntry : fleetMap.entrySet()) { + boolean filterFleet = true; + for (Entry raceEntry : fleetEntry.getValue().entrySet()) { + boolean filterRace = !filter.matches(raceEntry.getValue()); + raceEntry.getKey().doFilter(filterRace); + filterFleet &= filterRace; + } + fleetEntry.getKey().doFilter(filterFleet); + unfilteredFleetCount = unfilteredFleetCount + (filterFleet ? 0 : 1); + } + for (RegattaCompetitionFleetView fleetView : fleetMap.keySet()) { + fleetView.setNumberOfFleetsInSeries(unfilteredFleetCount); + } + seriesView.doFilter(unfilteredFleetCount == 0); + } + + protected abstract String getRaceViewerURL(SimpleRaceMetadataDTO raceMetadata); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionView.java new file mode 100644 index 00000000000..1093c4a9350 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattacompetition/RegattaCompetitionView.java @@ -0,0 +1,28 @@ +package com.sap.sailing.gwt.home.shared.partials.regattacompetition; + +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatFleetDTO; +import com.sap.sailing.gwt.home.communication.event.RaceCompetitionFormatSeriesDTO; +import com.sap.sailing.gwt.home.communication.race.SimpleRaceMetadataDTO; + + +public interface RegattaCompetitionView { + + void clearContent(); + RegattaCompetitionSeriesView addSeriesView(RaceCompetitionFormatSeriesDTO series); + + public interface RegattaCompetitionSeriesView { + RegattaCompetitionFleetView addFleetView(RaceCompetitionFormatFleetDTO fleet); + void doFilter(boolean filter); + } + + public interface RegattaCompetitionFleetView { + RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, String raceViewerUrl); + void setNumberOfFleetsInSeries(int fleetCount); + void doFilter(boolean filter); + } + + public interface RegattaCompetitionRaceView { + void doFilter(boolean filter); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListPresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListPresenter.java new file mode 100644 index 00000000000..59b5a593246 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListPresenter.java @@ -0,0 +1,61 @@ +package com.sap.sailing.gwt.home.shared.partials.regattalist; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; +import com.sap.sailing.gwt.home.shared.partials.filter.FilterValueChangeHandler; +import com.sap.sailing.gwt.home.shared.partials.regattalist.RegattaListView.RegattaListItem; +import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; +import com.sap.sse.common.filter.Filter; + +public class RegattaListPresenter implements FilterValueChangeHandler{ + + private final RegattaListView view; + private final Map stucture = new HashMap<>(); + private Filter latestBoatCategoryFilter; + + public > RegattaListPresenter(V view) { + this.view = view; + } + + @Override + public void onFilterValueChanged(Filter filter) { + this.latestBoatCategoryFilter = filter; + for (Entry entry : stucture.entrySet()) { + entry.getKey().doFilter(!filter.matches(entry.getValue())); + } + } + + @Override + public Collection getFilterableValues() { + Set filterableValues = new HashSet<>(); + for (RegattaMetadataDTO regattaMetadata : stucture.values()) { + if (regattaMetadata.getBoatCategory() != null) { + filterableValues.add(regattaMetadata.getBoatCategory()); + } + } + return filterableValues.size() > 1 ? filterableValues : Collections.emptySet(); + } + + public RefreshableWidget getRefreshableWidgetWrapper(final RefreshableWidget wrappedWidget) { + return new RefreshableWidget() { + @Override + public void setData(D data) { + stucture.clear(); + wrappedWidget.setData(data); + stucture.putAll(view.getItemMap()); + if (latestBoatCategoryFilter != null) { + RegattaListPresenter.this.onFilterValueChanged(latestBoatCategoryFilter); + } + } + }; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListView.java new file mode 100644 index 00000000000..d75e8eb0ca2 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/regattalist/RegattaListView.java @@ -0,0 +1,14 @@ +package com.sap.sailing.gwt.home.shared.partials.regattalist; + +import java.util.Map; + +import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO; + +public interface RegattaListView { + + Map getItemMap(); + + public interface RegattaListItem { + void doFilter(boolean filter); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResult.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResult.java new file mode 100644 index 00000000000..3e5be22b3b3 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResult.java @@ -0,0 +1,77 @@ +package com.sap.sailing.gwt.home.shared.partials.searchresult; + +import java.util.Collection; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.KeyPressEvent; +import com.google.gwt.event.dom.client.KeyPressHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HasWidgets; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.shared.app.AbstractPlaceNavigator; +import com.sap.sailing.gwt.ui.client.StringMessages; + +public abstract class AbstractSearchResult extends Composite { + + private int resultsCount = 0; + + protected final void init(final AbstractPlaceNavigator navigator, Widget widget) { + super.initWidget(widget); + getSearchTextInputUi().getElement().setAttribute("placeholder", TextMessages.INSTANCE.searchResultHeaderPlaceholder()); + getSearchTextInputUi().addKeyPressHandler(new KeyPressHandler() { + @Override + public void onKeyPress(KeyPressEvent event) { + if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) { + search(navigator); + } + } + }); + getSearchButtonUi().addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + search(navigator); + } + }); + } + + private void search(AbstractPlaceNavigator navigator) { + navigator.getSearchResultNavigation(getSearchTextInputUi().getValue()).goToPlace(); + } + + public void setSearchText(String searchText) { + getSearchTextInputUi().setValue(searchText); + } + + public void updateSearchResult(String searchText, Collection searchResultItems) { + for (SearchResultDTO searchResult : searchResultItems) { + addSearchResultItem(searchResult); + resultsCount++; + } + getSearchResultAmountUi().setInnerText(StringMessages.INSTANCE.resultsFoundForSearch(resultsCount, searchText)); + } + + @Override + protected void onLoad() { + super.onLoad(); + if (getSearchTextInputUi().getValue().isEmpty()) { + getSearchTextInputUi().setFocus(true); + } + } + + protected abstract TextBox getSearchTextInputUi(); + + protected abstract Button getSearchButtonUi(); + + protected abstract Element getSearchResultAmountUi(); + + protected abstract HasWidgets getSearchResultContainerUi(); + + protected abstract void addSearchResultItem(SearchResultDTO searchResult); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItem.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItem.java new file mode 100644 index 00000000000..dce43ac1a5a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItem.java @@ -0,0 +1,22 @@ +package com.sap.sailing.gwt.home.shared.partials.searchresult; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; + +public abstract class AbstractSearchResultItem extends Widget { + + protected final void init(Element element, SearchResultDTO item) { + setElement(element); + getResultTitleUi().setInnerText(item.getDisplayName()); + for (SearchResultEventInfoDTO event : item.getEvents()) { + addEventInfo(event); + } + } + + protected abstract Element getResultTitleUi(); + + protected abstract void addEventInfo(SearchResultEventInfoDTO event); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItemEventInfo.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItemEventInfo.java new file mode 100644 index 00000000000..91b1ba4e7b9 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/searchresult/AbstractSearchResultItemEventInfo.java @@ -0,0 +1,26 @@ +package com.sap.sailing.gwt.home.shared.partials.searchresult; + +import static com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil.formatDateRangeWithYear; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.user.client.ui.UIObject; +import com.sap.sailing.gwt.home.communication.search.SearchResultEventInfoDTO; + +public abstract class AbstractSearchResultItemEventInfo extends UIObject { + + protected final void init(Element element, SearchResultEventInfoDTO event) { + setElement(element); + getEventNameUi().setInnerText(event.getName()); + getEventVenueUi().setInnerText(event.getVenueName()); + if (event.getStartDate() != null && event.getEndDate() != null) { + getEventDateUi().setInnerText(formatDateRangeWithYear(event.getStartDate(), event.getEndDate())); + } + } + + protected abstract Element getEventNameUi(); + + protected abstract Element getEventVenueUi(); + + protected abstract Element getEventDateUi(); + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/statistics/AbstractStatisticsBox.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/statistics/AbstractStatisticsBox.java index e6553d45173..01ef8fc7bb4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/statistics/AbstractStatisticsBox.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/statistics/AbstractStatisticsBox.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.shared.partials.statistics; import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.user.client.ui.Composite; +import com.sap.sailing.gwt.home.communication.event.statistics.EventStatisticsDTO; import com.sap.sailing.gwt.home.shared.refresh.RefreshableWidget; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventStatisticsDTO; public abstract class AbstractStatisticsBox extends Composite implements RefreshableWidget { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/video/Video.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/video/Video.java index cbffeb7a514..be93dfb3939 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/video/Video.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/video/Video.java @@ -5,8 +5,8 @@ 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.Widget; +import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewVideoStageDTO; import com.sap.sailing.gwt.home.shared.partials.videoplayer.VideoWithLowerThird; -import com.sap.sailing.gwt.ui.shared.dispatch.event.EventOverviewVideoStageDTO; public class Video extends Composite { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/videoplayer/VideoWithLowerThird.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/videoplayer/VideoWithLowerThird.java index bdd589ead0c..77275ab7b09 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/videoplayer/VideoWithLowerThird.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/partials/videoplayer/VideoWithLowerThird.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.home.shared.partials.videoplayer; +import com.sap.sailing.gwt.home.communication.event.LabelType; import com.sap.sailing.gwt.home.shared.partials.lowerthird.LowerThird; -import com.sap.sailing.gwt.ui.shared.general.LabelType; import com.sap.sse.gwt.client.media.VideoDTO; public class VideoWithLowerThird extends VideoPlayer { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/AbstractErrorActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/AbstractErrorActivity.java new file mode 100644 index 00000000000..942aa0177be --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/AbstractErrorActivity.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.home.shared.places.error; + +import com.google.gwt.activity.shared.AbstractActivity; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.place.shared.PlaceController; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sse.gwt.client.mvp.ErrorView; + +public abstract class AbstractErrorActivity extends AbstractActivity { + + private final ErrorPlace currentPlace; + private final PlaceController placeController; + + public AbstractErrorActivity(ErrorPlace place, PlaceController placeController) { + this.currentPlace = place; + this.placeController = placeController; + } + + @Override + public final void start(AcceptsOneWidget panel, EventBus eventBus) { + Command reloadCommand = currentPlace.getComingFrom() == null ? null : new Command() { + @Override + public void execute() { + placeController.goTo(currentPlace.getComingFrom()); + } + }; + String message = currentPlace.getErrorMessage(), details = currentPlace.getErrorMessageDetail(); + panel.setWidget(currentPlace.hasCustomErrorMessages() ? + createView(message, details, currentPlace.getException(), reloadCommand) + : createView(message, currentPlace.getException(), reloadCommand)); + } + + protected abstract ErrorView createView(String errorMsg, Throwable reason, Command reloadCommand); + + protected abstract ErrorView createView(String customMsg, String errorMsg, Throwable reason, Command reloadCommand); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorClientFactory.java new file mode 100644 index 00000000000..c1abc5fa56a --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorClientFactory.java @@ -0,0 +1,8 @@ +package com.sap.sailing.gwt.home.shared.places.error; + +import com.sap.sailing.gwt.ui.client.SailingClientFactory; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; + +public interface ErrorClientFactory extends ErrorAndBusyClientFactory, SailingClientFactory { + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorPlace.java similarity index 89% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorPlace.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorPlace.java index 1041d7e1f24..f4109479478 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/error/ErrorPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/error/ErrorPlace.java @@ -1,10 +1,11 @@ -package com.sap.sailing.gwt.home.desktop.places.error; +package com.sap.sailing.gwt.home.shared.places.error; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceTokenizer; import com.sap.sailing.gwt.common.client.AbstractBasePlace; +import com.sap.sailing.gwt.home.shared.app.HasMobileVersion; -public class ErrorPlace extends AbstractBasePlace { +public class ErrorPlace extends AbstractBasePlace implements HasMobileVersion { /** * Place provided for reload action diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventActivityProxy.java new file mode 100644 index 00000000000..a9e4223a6d1 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventActivityProxy.java @@ -0,0 +1,112 @@ +package com.sap.sailing.gwt.home.shared.places.event; + +import java.util.UUID; + +import com.google.gwt.activity.shared.Activity; +import com.sap.sailing.gwt.home.communication.event.GetEventViewAction; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.AbstractMultiregattaEventPlace; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.mediatab.MultiregattaMediaPlace; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.overviewtab.MultiregattaOverviewPlace; +import com.sap.sailing.gwt.home.desktop.places.event.multiregatta.regattastab.MultiregattaRegattasPlace; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.AbstractEventRegattaPlace; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.mediatab.RegattaMediaPlace; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace; +import com.sap.sailing.gwt.home.desktop.places.event.regatta.racestab.RegattaRacesPlace; +import com.sap.sailing.gwt.home.shared.app.ActivityProxyCallback; +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; +import com.sap.sailing.gwt.home.shared.app.NavigationPathDisplay; +import com.sap.sailing.gwt.home.shared.app.ProvidesNavigationPath; +import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; +import com.sap.sse.gwt.client.mvp.ClientFactory; + +public abstract class AbstractEventActivityProxy extends AbstractActivityProxy implements ProvidesNavigationPath { + + private final C clientFactory; + private AbstractEventPlace place; + private NavigationPathDisplay navigationPathDisplay; + + public AbstractEventActivityProxy(C clientFactory, AbstractEventPlace place) { + this.clientFactory = clientFactory; + this.place = place; + } + + @Override + protected final void startAsync() { + GetEventViewAction action = new GetEventViewAction(UUID.fromString(place.getEventUuidAsString())); + clientFactory.getDispatch().execute(action, new ActivityProxyCallback(clientFactory, place) { + @Override + public void onSuccess(EventViewDTO event) { + if(place instanceof EventDefaultPlace) { + place = getRealPlace(event.getType()); + } + afterEventLoad(clientFactory, event, verifyAndAdjustPlace(event)); + } + }); + } + + @Override + public void setNavigationPathDisplay(NavigationPathDisplay navigationPathDisplay) { + this.navigationPathDisplay = navigationPathDisplay; + } + + protected NavigationPathDisplay getNavigationPathDisplay() { + return navigationPathDisplay; + } + + /** + * This method is called after loading the event an verifying the {@link AbstractEventPlace}. + * Subclasses can start an {@link Activity} based on the given {@link AbstractEventPlace}. + * + * @param clientFactory the {@link ClientFactoryWithDispatch} needed in {@link Activity} + * @param event event object + * @param place the verified {@link AbstractEventPlace} + */ + protected abstract void afterEventLoad(C clientFactory, EventViewDTO event, AbstractEventPlace place); + + private AbstractEventPlace getRealPlace(EventType eventType) { + if(eventType == EventType.SERIES_EVENT || eventType == EventType.SINGLE_REGATTA) { + return new RegattaOverviewPlace(new EventContext(place.getCtx()).withRegattaId(null)); + } + return new MultiregattaOverviewPlace(place.getCtx()); + } + + /** + * Checks if the place is valid for the given event. If not, the place is automatically being adjusted. + * + * @param event + */ + protected AbstractEventPlace verifyAndAdjustPlace(EventViewDTO event) { + EventContext contextWithoutRegatta = new EventContext(place.getCtx()).withRegattaId(null); + // TODO check if regatta ID is valid + if(place instanceof AbstractMultiregattaEventPlace && event.getType() != EventType.MULTI_REGATTA) { + // Events with a type other than multi regatta only have regatta level pages + if(place instanceof MultiregattaRegattasPlace) { + return new RegattaRacesPlace(contextWithoutRegatta); + } + if(place instanceof MultiregattaMediaPlace) { + return new RegattaMediaPlace(contextWithoutRegatta); + } + return new RegattaOverviewPlace(contextWithoutRegatta); + } + + if(place instanceof AbstractEventRegattaPlace) { + boolean regattaKnown = event.isRegattaIDKnown(place.getCtx().getRegattaId()); + if(event.getType() != EventType.MULTI_REGATTA && place.getCtx().getRegattaId() != null && !regattaKnown) { + // Regatta ID unknown but unnecessary ... + place.getCtx().withRegattaId(null); + } else if(event.getType() == EventType.MULTI_REGATTA && !regattaKnown) { + return new MultiregattaRegattasPlace(contextWithoutRegatta); + } + } + + if(place instanceof RegattaMediaPlace && event.getType() == EventType.MULTI_REGATTA) { + // The media page for multi regatta events is on event level only but not on regatta level + return new MultiregattaMediaPlace(contextWithoutRegatta); + } + + return place; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventPlace.java index 18fc7986ae7..425c2df08c8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/AbstractEventPlace.java @@ -7,7 +7,6 @@ import com.google.gwt.place.shared.Place; import com.sap.sailing.gwt.common.client.AbstractMapTokenizer; import com.sap.sailing.gwt.common.client.i18n.TextMessages; import com.sap.sailing.gwt.home.shared.app.HasLocationTitle; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; public abstract class AbstractEventPlace extends Place implements HasLocationTitle { private final EventContext ctx; @@ -53,7 +52,8 @@ public abstract class AbstractEventPlace extends Place implements HasLocationTit Map parameters = new HashMap<>(); EventContext context = place.getCtx(); parameters.put(PARAM_EVENTID, context.getEventId()); - if(context.getEventDTO() == null || context.getEventDTO().getType() == EventType.MULTI_REGATTA) { + String regattaId = context.getRegattaId(); + if(regattaId != null && !regattaId.isEmpty()) { parameters.put(PARAM_REGATTAID, context.getRegattaId()); } return parameters; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/EventContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/EventContext.java index 6ac78610dfe..b6e94405235 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/EventContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/event/EventContext.java @@ -1,10 +1,6 @@ package com.sap.sailing.gwt.home.shared.places.event; import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaAnalyticsDataManager; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO.EventType; -import com.sap.sailing.gwt.ui.shared.eventview.RegattaMetadataDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; /** * Common context used by the different tabs in the event place. @@ -17,18 +13,11 @@ public class EventContext { private String regattaId; private RegattaAnalyticsDataManager regattaAnalyticsManager; - /** - * Common state required by all tabs/ places in event - */ - private EventViewDTO eventDTO; - private MediaDTO media; - public EventContext() { } public EventContext(EventContext ctx) { - updateContext(ctx.getEventDTO()); - withMedia(ctx.media); + withId(ctx.eventId); withRegattaId(ctx.regattaId); withRegattaAnalyticsManager(ctx.regattaAnalyticsManager); } @@ -43,48 +32,12 @@ public class EventContext { return this; } - /** - * Used to update context with dto instance - */ - public EventContext updateContext(EventViewDTO dto) { - this.eventDTO = dto; - if (eventDTO == null) { - withId(null); - } else { - withId(dto.getId().toString()); - } - return this; - } - - public EventViewDTO getEventDTO() { - return eventDTO; - } - public String getEventId() { return eventId; } public String getRegattaId() { - if(regattaId != null) { - return regattaId; - } - if(eventDTO != null && !eventDTO.getRegattas().isEmpty() && (eventDTO.getType() == EventType.SINGLE_REGATTA || eventDTO.getType() == EventType.SERIES_EVENT)) { - return eventDTO.getRegattas().iterator().next().getId(); - } - return null; - } - - public RegattaMetadataDTO getRegatta() { - String regattaId = getRegattaId(); - if(regattaId == null || eventDTO == null) { - return null; - } - for (RegattaMetadataDTO regatta : eventDTO.getRegattas()) { - if(regattaId.equals(regatta.getId())) { - return regatta; - } - } - return null; + return regattaId; } public RegattaAnalyticsDataManager getRegattaAnalyticsManager() { @@ -95,13 +48,4 @@ public class EventContext { this.regattaAnalyticsManager = regattaAnalyticsManager; return this; } - - public MediaDTO getMedia() { - return media; - } - - public EventContext withMedia(MediaDTO mediaDTO) { - this.media = mediaDTO; - return this; - } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/AbstractSeriesPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/AbstractSeriesPlace.java index 0e61c2b1cc3..4ba2a932b35 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/AbstractSeriesPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/AbstractSeriesPlace.java @@ -19,8 +19,7 @@ public abstract class AbstractSeriesPlace extends Place { } public AbstractSeriesPlace(String eventUuidAsString) { - this.ctx = new SeriesContext(); - ctx.withId(eventUuidAsString); + this.ctx = new SeriesContext(eventUuidAsString); } public String getTitle(String eventName) { @@ -34,7 +33,7 @@ public abstract class AbstractSeriesPlace extends Place { public static abstract class Tokenizer extends AbstractMapTokenizer { private final static String PARAM_EVENTID = "seriesId"; protected PLACE getPlaceFromParameters(Map parameters) { - return getRealPlace(new SeriesContext().withId(parameters.get(PARAM_EVENTID))); + return getRealPlace(new SeriesContext(parameters.get(PARAM_EVENTID))); } protected Map getParameters(PLACE place) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/SeriesContext.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/SeriesContext.java index 1827c8fce95..624bc518d76 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/SeriesContext.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/fakeseries/SeriesContext.java @@ -1,66 +1,37 @@ package com.sap.sailing.gwt.home.shared.places.fakeseries; +import java.util.UUID; + import com.sap.sailing.gwt.home.desktop.places.fakeseries.EventSeriesAnalyticsDataManager; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; /** * Common context used by the different tabs in the series place. * - * @author pgtaboada */ public class SeriesContext { - private String seriesId; - private EventSeriesViewDTO seriesDTO; - private MediaDTO media; + private final String seriesId; private EventSeriesAnalyticsDataManager analyticsManager; - public SeriesContext() { + public SeriesContext(String seriesId) { + this.seriesId = seriesId; } public SeriesContext(SeriesContext ctx) { - updateContext(ctx.getSeriesDTO()); - withMedia(ctx.media); + this.seriesId = ctx.seriesId; withAnalyticsManager(ctx.analyticsManager); } - public SeriesContext withId(String eventId) { - this.seriesId = eventId; - return this; - } - - /** - * Used to update context with dto instance - * - * @param dto - * @return - */ - public SeriesContext updateContext(EventSeriesViewDTO dto) { - this.seriesDTO = dto; - if (seriesDTO == null) { - withId(null); - } else { - withId(dto.getId().toString()); - } - return this; - } - - public EventSeriesViewDTO getSeriesDTO() { - return seriesDTO; - } - public String getSeriesId() { return seriesId; } - public MediaDTO getMedia() { - return media; - } - - public SeriesContext withMedia(MediaDTO media) { - this.media = media; - return this; + public UUID getSeriesUUID() { + if(seriesId == null) { + // TODO assert because seriesId is required + return null; + } + return UUID.fromString(seriesId); } public EventSeriesAnalyticsDataManager getAnalyticsManager() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivity.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivity.java new file mode 100644 index 00000000000..bbf7411467f --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivity.java @@ -0,0 +1,54 @@ +package com.sap.sailing.gwt.home.shared.places.searchresult; + +import com.google.gwt.activity.shared.AbstractActivity; +import com.google.gwt.event.shared.EventBus; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.sap.sailing.gwt.dispatch.client.ListResult; +import com.sap.sailing.gwt.dispatch.client.StringsResult; +import com.sap.sailing.gwt.home.communication.search.GetSearchResultsAction; +import com.sap.sailing.gwt.home.communication.search.GetSearchServerNamesAction; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; +import com.sap.sailing.gwt.home.shared.app.ActivityCallback; + +public class SearchResultActivity extends AbstractActivity { + + private final SearchResultClientFactory clientFactory; + private final SearchResultPlace searchResultPlace; + + public SearchResultActivity(SearchResultPlace place, SearchResultClientFactory clientFactory) { + this.clientFactory = clientFactory; + this.searchResultPlace = place; + } + + @Override + public void start(final AcceptsOneWidget panel, final EventBus eventBus) { + Window.setTitle(searchResultPlace.getTitle()); + final SearchResultView view = clientFactory.createSearchResultView(); + if (searchResultPlace.getSearchText() != null && !searchResultPlace.getSearchText().isEmpty()) { + final String searchText = searchResultPlace.getSearchText(); + view.setSearchText(searchText); + GetSearchServerNamesAction action = new GetSearchServerNamesAction(); + searchOnServer(panel, view, new GetSearchResultsAction(searchText)); + clientFactory.getDispatch().execute(action, new ActivityCallback(clientFactory, panel) { + @Override + public void onSuccess(StringsResult result) { + for (String serverName : result.getValues()) { + searchOnServer(panel, view, new GetSearchResultsAction(searchText, serverName)); + } + } + }); + } + panel.setWidget(view); + } + + private void searchOnServer(AcceptsOneWidget panel, final SearchResultView view, GetSearchResultsAction action) { + clientFactory.getDispatch().execute(action, new ActivityCallback>(clientFactory, panel) { + @Override + public void onSuccess(ListResult result) { + view.updateSearchResult(searchResultPlace.getSearchText(), result.getValues()); + } + }); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivityProxy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivityProxy.java similarity index 92% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivityProxy.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivityProxy.java index 6db3dc260d7..3614712e2cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultActivityProxy.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultActivityProxy.java @@ -1,4 +1,4 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; +package com.sap.sailing.gwt.home.shared.places.searchresult; import com.google.gwt.core.client.GWT; import com.sap.sse.gwt.client.mvp.AbstractActivityProxy; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultClientFactory.java new file mode 100644 index 00000000000..9666426df78 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultClientFactory.java @@ -0,0 +1,8 @@ +package com.sap.sailing.gwt.home.shared.places.searchresult; + +import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; + +public interface SearchResultClientFactory extends ErrorAndBusyClientFactory, ClientFactoryWithDispatch { + SearchResultView createSearchResultView(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultPlace.java similarity index 69% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultPlace.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultPlace.java index 83f160838a9..0a59b44dfbb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/searchresult/SearchResultPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultPlace.java @@ -1,16 +1,23 @@ -package com.sap.sailing.gwt.home.desktop.places.searchresult; +package com.sap.sailing.gwt.home.shared.places.searchresult; import com.google.gwt.place.shared.Place; import com.google.gwt.place.shared.PlaceTokenizer; import com.sap.sailing.gwt.common.client.i18n.TextMessages; +import com.sap.sailing.gwt.home.shared.app.HasLocationTitle; +import com.sap.sailing.gwt.home.shared.app.HasMobileVersion; -public class SearchResultPlace extends Place { +public class SearchResultPlace extends Place implements HasLocationTitle, HasMobileVersion { private final String searchText; public SearchResultPlace(String searchText) { super(); this.searchText = searchText; } + + @Override + public String getLocationTitle() { + return TextMessages.INSTANCE.search(); + } public String getTitle() { return TextMessages.INSTANCE.sapSailing() + " - " + TextMessages.INSTANCE.search(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultView.java new file mode 100644 index 00000000000..41675d1215e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/searchresult/SearchResultView.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.home.shared.places.searchresult; + +import java.util.Collection; + +import com.google.gwt.user.client.ui.IsWidget; +import com.sap.sailing.gwt.home.communication.search.SearchResultDTO; + +public interface SearchResultView extends IsWidget { + + void setSearchText(String searchText); + + void updateSearchResult(String searchText, Collection searchResultItems); + + public interface Presenter { + + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/solutions/SolutionsPlace.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/solutions/SolutionsPlace.java index 712ed407c0f..00f4642fcc2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/solutions/SolutionsPlace.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/places/solutions/SolutionsPlace.java @@ -1,5 +1,11 @@ package com.sap.sailing.gwt.home.shared.places.solutions; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.http.client.Request; +import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.http.client.RequestCallback; +import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.Response; import com.google.gwt.place.shared.PlaceTokenizer; import com.sap.sailing.gwt.common.client.AbstractBasePlace; import com.sap.sailing.gwt.common.client.i18n.TextMessages; @@ -8,19 +14,62 @@ import com.sap.sailing.gwt.home.shared.app.HasMobileVersion; public class SolutionsPlace extends AbstractBasePlace implements HasLocationTitle, HasMobileVersion { - public enum SolutionsNavigationTabs { SailingAnalytics, RaceCommiteeApp, PostRaceAnalytics, TrainingDiary, SailingSimulator }; + public enum SolutionsNavigationTabs { + SapInSailing, SailingAnalytics, RaceCommitteeApp, PostRaceAnalytics, TrainingDiary, SailingSimulator + }; private final SolutionsNavigationTabs navigationTab; - private final static String PARAM_NAVIGATION_TAB = "navigationTab"; + private final static String PARAM_NAVIGATION_TAB = "navigationTab"; + private final static String CALENDAR_ACCESS_COUNT_URL = "/gwt/Calendar.html"; + private final boolean invokedFromCalendar; public SolutionsPlace(String url) { - super(url); - String paramNavTab = getParameter(PARAM_NAVIGATION_TAB); - navigationTab = paramNavTab != null ? SolutionsNavigationTabs.valueOf(paramNavTab) : null; + super(url.split("\\?")[0]); // if the fragment holds another "?" check if it's the "Calendar marker" c=1 + final String[] splitUrl = url.split("\\?"); + if (splitUrl.length > 1) { + final String calendarMarker = splitUrl[1]; + invokedFromCalendar = calendarMarker.equals("c=1"); + } else { + invokedFromCalendar = false; + } + if (invokedFromCalendar) { + navigationTab = SolutionsNavigationTabs.SapInSailing; + makeLoggedCountableCalendarRequest(); + } else { + final String paramNavTab = getParameter(PARAM_NAVIGATION_TAB); + SolutionsNavigationTabs preliminaryNavTab; + try { + preliminaryNavTab = paramNavTab != null ? SolutionsNavigationTabs.valueOf(paramNavTab) : null; + } catch (IllegalArgumentException e) { + preliminaryNavTab = SolutionsNavigationTabs.SapInSailing; + } + navigationTab = preliminaryNavTab; + } + } + + private void makeLoggedCountableCalendarRequest() { + final RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, CALENDAR_ACCESS_COUNT_URL); + try { + requestBuilder.sendRequest(/* requestData */ null, new RequestCallback() { + @Override + public void onResponseReceived(Request request, Response response) { + // nothing to do; it's just to make calendar-based access server-countable + } + + @Override + public void onError(Request request, Throwable exception) { + // nothing to do; it's just to make calendar-based access server-countable; it failed... + GWT.log("Warning: couldn't access calendar link counter", exception); + } + }); + } catch (RequestException e) { + GWT.log("Warning: couldn't access calendar link counter", e); + } } public SolutionsPlace(SolutionsNavigationTabs navigationTab) { super(PARAM_NAVIGATION_TAB, navigationTab.name()); this.navigationTab = navigationTab; + this.invokedFromCalendar = false; } public SolutionsNavigationTabs getNavigationTab() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/ActionProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/ActionProvider.java index 6649ca5ac6c..7e376726874 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/ActionProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/ActionProvider.java @@ -1,14 +1,14 @@ package com.sap.sailing.gwt.home.shared.refresh; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; +import com.sap.sailing.gwt.home.communication.SailingAction; -public interface ActionProvider> { +public interface ActionProvider> { A getAction(); boolean isActive(); - public abstract class AbstractActionProvider> implements ActionProvider { + public abstract class AbstractActionProvider> implements ActionProvider { private final A action; public AbstractActionProvider(A action) { @@ -21,7 +21,7 @@ public interface ActionProvider> { } } - public class DefaultActionProvider> extends AbstractActionProvider { + public class DefaultActionProvider> extends AbstractActionProvider { public DefaultActionProvider(A action) { super(action); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/AutoAttachingRefreshManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/AutoAttachingRefreshManager.java new file mode 100644 index 00000000000..8392adea261 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/AutoAttachingRefreshManager.java @@ -0,0 +1,37 @@ +package com.sap.sailing.gwt.home.shared.refresh; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.google.gwt.event.logical.shared.HasAttachHandlers; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; + +public class AutoAttachingRefreshManager extends LifecycleRefreshManager { + private static final Logger LOG = Logger.getLogger(AutoAttachingRefreshManager.class.getName()); + + private final Widget content; + + private AcceptsOneWidget container; + + public AutoAttachingRefreshManager(Widget content, AcceptsOneWidget container, SailingDispatchSystem actionExecutor) { + super((container instanceof HasAttachHandlers) ? ((HasAttachHandlers) container) : content, actionExecutor); + this.content = content; + this.container = container; + } + + @Override + protected boolean canExecute() { + return super.canExecute() || container != null; + } + + @Override + protected void onSuccessfulUpdate() { + if(container != null) { + LOG.log(Level.FINE, "Attaching refreshable content to container"); + container.setWidget(content); + container = null; + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/LifecycleRefreshManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/LifecycleRefreshManager.java new file mode 100644 index 00000000000..6ae8c579121 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/LifecycleRefreshManager.java @@ -0,0 +1,41 @@ +package com.sap.sailing.gwt.home.shared.refresh; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.logical.shared.AttachEvent; +import com.google.gwt.event.logical.shared.AttachEvent.Handler; +import com.google.gwt.event.logical.shared.HasAttachHandlers; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; + +public class LifecycleRefreshManager extends RefreshManager { + private final HasAttachHandlers lifecycleWidget; + + public LifecycleRefreshManager(HasAttachHandlers lifecycleWidget, SailingDispatchSystem actionExecutor) { + super(actionExecutor); + this.lifecycleWidget = lifecycleWidget; + lifecycleWidget.addAttachHandler(new Handler() { + @Override + public void onAttachOrDetach(AttachEvent event) { + if (event.isAttached()) { + start(); + } else { + cancel(); + } + } + }); + + Scheduler.get().scheduleFinally(new ScheduledCommand() { + @Override + public void execute() { + if(canExecute()) { + start(); + } + } + }); + } + + @Override + protected boolean canExecute() { + return lifecycleWidget.isAttached(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManager.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManager.java index dd1f61caf86..907ffdcd98f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManager.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManager.java @@ -7,25 +7,22 @@ import java.util.logging.Logger; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.logical.shared.AttachEvent; -import com.google.gwt.event.logical.shared.AttachEvent.Handler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.AcceptsOneWidget; -import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.home.shared.dispatch.DispatchSystem; +import com.sap.sailing.gwt.dispatch.client.DTO; +import com.sap.sailing.gwt.dispatch.client.ResultWithTTL; +import com.sap.sailing.gwt.home.communication.SailingAction; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; import com.sap.sailing.gwt.home.shared.refresh.ActionProvider.DefaultActionProvider; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; import com.sap.sse.common.Duration; -public class RefreshManager { +public abstract class RefreshManager { private static final Logger LOG = Logger.getLogger(RefreshManager.class.getName()); private static final long PAUSE_ON_ERROR = Duration.ONE_SECOND.times(30).asMillis(); - private List>>> refreshables = new ArrayList<>(); + private List>>> refreshables = new ArrayList<>(); + private boolean scheduled; private final Timer timer = new Timer() { @Override public void run() { @@ -33,48 +30,51 @@ public class RefreshManager { } }; - private final DispatchSystem actionExecutor; + private final SailingDispatchSystem actionExecutor; + + boolean started = false; - private final Widget content; - - private AcceptsOneWidget container; - - public RefreshManager(Widget content, DispatchSystem actionExecutor) { - this(content, null, actionExecutor); + public RefreshManager(SailingDispatchSystem actionExecutor) { + this.actionExecutor = actionExecutor; } - public RefreshManager(Widget content, AcceptsOneWidget container, DispatchSystem actionExecutor) { - this.content = content; - this.container = container; - this.actionExecutor = actionExecutor; - content.addAttachHandler(new Handler() { - @Override - public void onAttachOrDetach(AttachEvent event) { - if (event.isAttached()) { - reschedule(); - } else { - timer.cancel(); - } - } - }); - if(container != null) { - reschedule(); - } + protected void start() { + LOG.log(Level.FINE, "Starting auto refresh"); + started = true; + reschedule(); + } + + protected void cancel() { + LOG.log(Level.FINE, "Cancelling auto refresh"); + started = false; + timer.cancel(); + } + + protected abstract boolean canExecute(); + + protected void onSuccessfulUpdate() { + } + + protected void onFailedUpdate(Throwable errorCause) { } private void update() { - for (final RefreshHolder>> refreshable : refreshables) { + + for (final RefreshHolder>> refreshable : refreshables) { // Everything that needs refresh within the next 5000ms will be refreshed now. // This makes it possible to use batching resulting in less requests. - if (refreshable.provider.isActive() && !refreshable.callRunning && refreshable.timeout < System.currentTimeMillis() + 5000) { + if (refreshable.provider.isActive() && !refreshable.callRunning + && refreshable.timeout < System.currentTimeMillis() + ResultWithTTL.MAX_TIME_TO_LOAD_EARLIER.asMillis()) { refreshable.callRunning = true; - final Action> action = refreshable.provider.getAction(); + final SailingAction> action = refreshable.provider.getAction(); actionExecutor.execute(action, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { + LOG.log(Level.FINE, "Error on auto refresh"); refreshable.callRunning = false; refreshable.timeout = System.currentTimeMillis() + PAUSE_ON_ERROR; reschedule(); + onFailedUpdate(caught); } @Override @@ -83,7 +83,7 @@ public class RefreshManager { refreshable.timeout = System.currentTimeMillis() + result.getTtlMillis(); try { refreshable.widget.setData(result.getDto()); - initContentIfNecessary(); + onSuccessfulUpdate(); } catch(Throwable error) { LOG.log(Level.SEVERE, "Error while refreshing content with action " + action.getClass().getName(), error); } @@ -94,8 +94,6 @@ public class RefreshManager { } } - boolean scheduled; - private void reschedule() { if (scheduled) { return; @@ -106,59 +104,69 @@ public class RefreshManager { public void execute() { scheduled = false; - if (refreshables.isEmpty() || (!content.isAttached() && container == null)) { + if (refreshables.isEmpty()) { + LOG.log(Level.FINE, "No refreshables found -> skipping refresh"); + return; + } + if (!started) { + LOG.log(Level.FINE, "Refresh not started yet -> skipping refresh"); + return; + } + if (!canExecute()) { + LOG.log(Level.FINE, "Refresh not allowed to execute -> skipping refresh"); return; } - long nextUpdate = 0; - for (final RefreshHolder>> refreshable : refreshables) { - if (refreshable.callRunning) { + Long nextUpdate = null; + for (final RefreshHolder>> refreshable : refreshables) { + if (refreshable.callRunning || !refreshable.provider.isActive()) { continue; } - if (nextUpdate == 0) { + if (nextUpdate == null) { nextUpdate = refreshable.timeout; } else { nextUpdate = Math.min(nextUpdate, refreshable.timeout); } } - int delayMillis = Math.max(0, (int) (nextUpdate - System.currentTimeMillis())); - if (delayMillis == 0) { - update(); + if(nextUpdate == null) { + LOG.log(Level.FINE, "Nothing to auto update"); } else { - timer.schedule(delayMillis); + int delayMillis = (int) (nextUpdate - System.currentTimeMillis()); + if (delayMillis <= 0) { + LOG.log(Level.FINE, "Auto updating immediately"); + update(); + } else { + LOG.log(Level.FINE, "Scheduling auto refresh in " + delayMillis + "ms"); + timer.schedule(delayMillis); + } + } } }); } - private void initContentIfNecessary() { - if(container != null) { - container.setWidget(content); - container = null; - } - } - - public void forceReschule() { + public void forceReschedule() { + scheduled = false; timer.cancel(); reschedule(); } @SuppressWarnings({ "rawtypes", "unchecked" }) - public >> void add(RefreshableWidget widget, + public >> void add(RefreshableWidget widget, ActionProvider provider) { refreshables.add(new RefreshHolder(widget, provider)); reschedule(); } - public >> void add(RefreshableWidget widget, A action) { + public >> void add(RefreshableWidget widget, A action) { add(widget, new DefaultActionProvider<>(action)); } - public DispatchSystem getDispatchSystem() { + public SailingDispatchSystem getDispatchSystem() { return actionExecutor; } - private static class RefreshHolder>> { + private static class RefreshHolder>> { private final RefreshableWidget widget; private final ActionProvider provider; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManagerWithErrorAndBusy.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManagerWithErrorAndBusy.java new file mode 100644 index 00000000000..c22b5967e9c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshManagerWithErrorAndBusy.java @@ -0,0 +1,39 @@ +package com.sap.sailing.gwt.home.shared.refresh; + +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory; + +public class RefreshManagerWithErrorAndBusy extends AutoAttachingRefreshManager { + private final AcceptsOneWidget container; + + private final ErrorAndBusyClientFactory errorAndBusyViewFactory; + + private boolean hadSuccess = false; + private boolean hadFailure = false; + + public RefreshManagerWithErrorAndBusy(Widget content, AcceptsOneWidget container, + SailingDispatchSystem actionExecutor, ErrorAndBusyClientFactory errorAndBusyViewFactory) { + super(content, container, actionExecutor); + this.container = container; + this.errorAndBusyViewFactory = errorAndBusyViewFactory; + container.setWidget(errorAndBusyViewFactory.createBusyView()); + } + + @Override + protected void onFailedUpdate(Throwable errorCause) { + super.onFailedUpdate(errorCause); + if(!hadSuccess && !hadFailure) { + container.setWidget(errorAndBusyViewFactory.createErrorView(StringMessages.INSTANCE.errorLoadingDataWithTryAgain(), errorCause)); + } + hadFailure = true; + } + + @Override + protected void onSuccessfulUpdate() { + super.onSuccessfulUpdate(); + hadSuccess = true; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshableWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshableWidget.java index 3e8d6ee968c..3ca5fc760f1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshableWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/refresh/RefreshableWidget.java @@ -1,6 +1,6 @@ package com.sap.sailing.gwt.home.shared.refresh; -import com.sap.sailing.gwt.ui.shared.dispatch.DTO; +import com.sap.sailing.gwt.dispatch.client.DTO; public interface RefreshableWidget { void setData(D data); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/EventDatesFormatterUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/EventDatesFormatterUtil.java index fd9d2d8b22f..ea3b39f0ff6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/EventDatesFormatterUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/EventDatesFormatterUtil.java @@ -15,42 +15,45 @@ public class EventDatesFormatterUtil { private final static DateTimeFormat monthFormat = DateTimeFormat.getFormat("MMMM"); private final static DateTimeFormat yearFormat = DateTimeFormat.getFormat("yyyy"); - private final static int ONE_DAY = 24 * 60 * 60 * 1000; - - @SuppressWarnings("deprecation") public static String formatDateRangeWithYear(Date from, Date to) { - String result = ""; - if(from.getMonth() == to.getMonth()) { + final String result; + final String fromMonth = monthFormat.format(from); + final String toMonth = monthFormat.format(to); + if (fromMonth.equals(toMonth)) { // same month - if(from.getDay() == to.getDay() && to.getTime() - to.getTime() <= ONE_DAY) { + final String fromDay = dayFormat.format(from); + final String toDay = dayFormat.format(to); + if (fromDay.equals(toDay)) { // same day - result = monthFormat.format(from) + " " + dayFormat.format(from) + ", " + yearFormat.format(from); + result = fromMonth + " " + fromDay + ", " + yearFormat.format(from); } else { - result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to) + ", " + yearFormat.format(from); + result = fromMonth + " " + fromDay + " - " + toDay + ", " + + yearFormat.format(from); } } else { - result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to) + ", " + yearFormat.format(from); + result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to) + ", " + + yearFormat.format(from); } - return result; } - @SuppressWarnings("deprecation") public static String formatDateRangeWithoutYear(Date from, Date to) { - String result = ""; - if(from.getMonth() == to.getMonth()) { + final String result; + final String fromMonth = monthFormat.format(from); + final String toMonth = monthFormat.format(to); + if (fromMonth.equals(toMonth)) { // same month - if(from.getDay() == to.getDay() && to.getTime() - to.getTime() <= ONE_DAY) { + final String fromDay = dayFormat.format(from); + final String toDay = dayFormat.format(to); + if (fromDay.equals(toDay)) { // same day - result = monthFormat.format(from) + " " + dayFormat.format(from); + result = fromMonth + " " + fromDay; } else { - result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to); + result = fromMonth + " " + fromDay + " - " + toDay; } } else { result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to); } - return result; } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/HomeSailingFlagsBuilder.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/HomeSailingFlagsBuilder.java new file mode 100644 index 00000000000..3ef8eba00fd --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/HomeSailingFlagsBuilder.java @@ -0,0 +1,14 @@ +package com.sap.sailing.gwt.home.shared.utils; + +import com.google.gwt.safehtml.shared.SafeHtml; +import com.sap.sailing.gwt.home.communication.race.FlagStateDTO; +import com.sap.sailing.gwt.regattaoverview.client.SailingFlagsBuilder; + +public class HomeSailingFlagsBuilder { + + public static SafeHtml render(FlagStateDTO flagState, double scale, String tooltip) { + return SailingFlagsBuilder.render(flagState.getLastUpperFlag(), flagState.getLastLowerFlag(), + flagState.isLastFlagsAreDisplayed(), flagState.isLastFlagsDisplayedStateChanged(), scale, tooltip); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LabelTypeUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LabelTypeUtil.java index 197bec849b1..a92e6666674 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LabelTypeUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LabelTypeUtil.java @@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.shared.utils; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Display; -import com.sap.sailing.gwt.ui.shared.general.LabelType; +import com.sap.sailing.gwt.home.communication.event.LabelType; public final class LabelTypeUtil { private LabelTypeUtil() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LogoUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LogoUtil.java index 84600497dca..d640011d86c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LogoUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/shared/utils/LogoUtil.java @@ -2,9 +2,9 @@ package com.sap.sailing.gwt.home.shared.utils; import com.google.gwt.dom.client.Element; import com.google.gwt.safehtml.shared.SafeUri; +import com.sap.sailing.gwt.home.communication.event.HasLogo; +import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO; import com.sap.sailing.gwt.home.desktop.partials.eventheader.EventHeaderResources; -import com.sap.sailing.gwt.ui.shared.eventview.EventViewDTO; -import com.sap.sailing.gwt.ui.shared.general.HasLogo; /** * Utility class to set logo url on UI elements using a default logo as fallback if no logo is provided. diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverview.gss b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverview.gss index 714cc872837..4cab45e2376 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverview.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverview.gss @@ -163,7 +163,7 @@ body { background-position: center center; } .refreshButton_live { - background-color: #f0ab00; + background-color: red; } .refreshButton_playing { background-color: #f0ab00; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java index 66bfacb9f73..d392a59ee35 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java @@ -164,6 +164,7 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint { String debugParam = Window.Location.getParameter("gwt.codesvr"); String showOnlyCurrentlyRunningRaces = "&" + PARAM_ONLY_RUNNING_RACES + "=" + (settings.isShowOnlyCurrentlyRunningRaces() ? "true" : "false"); String showOnlyRacesOfSameDay = "&" + PARAM_ONLY_RACES_OF_SAME_DAY + "=" + (settings.isShowOnlyRacesOfSameDay() ? "true" : "false"); + String ignoreLocalSettings = "&" + PARAM_IGNORE_LOCAL_SETTINGS + "=true"; StringBuilder visibleCourseAreas = new StringBuilder(); if (isSetVisibleCourseAreasInUrl) { @@ -188,6 +189,7 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint { + visibleRegattas.toString() + showOnlyCurrentlyRunningRaces + showOnlyRacesOfSameDay + + ignoreLocalSettings + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); return link; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java index 093d88c5f7a..dc150dff671 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java @@ -113,7 +113,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component private TextColumn boatClass; private TextColumn startTimeColumn; private SimplePanel tableHolder = new SimplePanel(); - private final long _1_HOUR = 60 /* seconds */* 60 /* minutes */* 60 /* hour */; + private final long _1_HOUR = 60 /* seconds */* 60 /* minutes */* 1 /* hour */; private final long HIDE_COL_TIME_THRESHOLD = _1_HOUR; private TextColumn lastUpdateColumn; private TextColumn endOfProtestTime; @@ -260,6 +260,8 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component while (table.getColumnCount() > 0) { table.removeColumn(0); } + } else { + sortInfos.add(new ColumnSortInfo(lastUpdateColumn, false)); } table = new CellTable(/* pageSize */10000, tableRes); tableHolder.setWidget(table); @@ -618,6 +620,9 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component @Override public String getValue(RegattaOverviewEntryDTO entryDTO) { + if (entryDTO.raceInfo.lastUpdateTime == null) { + return "-"; + } final long lastUpdateInSeconds = timePassedInSeconds(entryDTO.raceInfo.lastUpdateTime); if (lastUpdateInSeconds > HIDE_COL_TIME_THRESHOLD) { return timeFormatter.format(entryDTO.raceInfo.lastUpdateTime); @@ -628,8 +633,8 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component } else if (lastUpdateInSeconds < _1_HOUR) { sb.append(lastUpdateInSeconds / 60).append("m"); } else { - long hours = lastUpdateInSeconds / 3600; - long minutes = (lastUpdateInSeconds - (hours * 3600)) / 60; + long hours = lastUpdateInSeconds / _1_HOUR; + long minutes = (lastUpdateInSeconds - (hours * _1_HOUR)) / 60; if (hours > HIDE_COL_TIME_THRESHOLD) { return ""; } @@ -638,6 +643,7 @@ public class RegattaRaceStatesComponent extends SimplePanel implements Component return sb.toString(); } }; + lastUpdateColumn.setDefaultSortAscending(false); lastUpdateColumn.setSortable(true); regattaOverviewListHandler.setComparator(lastUpdateColumn, new Comparator() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/SailingFlagsBuilder.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/SailingFlagsBuilder.java index 97eff4cb9d5..89a7ce9ab48 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/SailingFlagsBuilder.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/SailingFlagsBuilder.java @@ -12,7 +12,6 @@ import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.gwt.ui.shared.race.FlagStateDTO; public class SailingFlagsBuilder { @@ -49,12 +48,6 @@ public class SailingFlagsBuilder { return imageTemplate.cell(tooltip, contentBuilder.toSafeHtml()); } - public static SafeHtml render(FlagStateDTO flagState, double scale, String tooltip) { - return render(flagState.getLastUpperFlag(), flagState.getLastLowerFlag(), flagState.isLastFlagsAreDisplayed(), - flagState.isLastFlagsDisplayedStateChanged(), scale, tooltip); - // return render(Flags.AP, Flags.ALPHA, true, true, scale, tooltip); - } - private static SafeHtml getFlagBackgroundImage(Flags flag, boolean displayed, boolean displayedChanged, Scales scales) { ImageResource flagImage = flagImageResolver.resolveFlagToImage(flag, displayed, displayedChanged); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventListDataCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventListDataCalculator.java index e43c08aa9bb..9d1b2734efb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventListDataCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventListDataCalculator.java @@ -8,11 +8,11 @@ import java.util.Map; import java.util.Map.Entry; import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO; +import com.sap.sailing.gwt.home.communication.eventlist.EventListViewDTO; import com.sap.sailing.gwt.server.HomeServiceUtil.EventVisitor; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventSeriesDTO; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; import com.sap.sailing.server.RacingEventService; public class EventListDataCalculator implements EventVisitor { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventStageCandidateCalculator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventStageCandidateCalculator.java index 41f36011c12..4da03d6776a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventStageCandidateCalculator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/EventStageCandidateCalculator.java @@ -6,14 +6,16 @@ import java.util.SortedSet; import java.util.TreeSet; import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.gwt.home.communication.start.StageEventType; import com.sap.sailing.gwt.server.HomeServiceUtil.EventVisitor; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; public class EventStageCandidateCalculator implements EventVisitor { + public static final int MAX_STAGE_EVENTS = 5; + private final TimePoint now = MillisecondsTimePoint.now(); private final SortedSet> featuredEvents = new TreeSet<>(new FeaturedEventsComparator()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/FeaturedEventsComparator.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/FeaturedEventsComparator.java index 655503bdfbe..3858e0c672b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/FeaturedEventsComparator.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/FeaturedEventsComparator.java @@ -6,7 +6,7 @@ import java.util.Map; import java.util.Random; import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; +import com.sap.sailing.gwt.home.communication.start.StageEventType; import com.sap.sse.common.TimePoint; import com.sap.sse.common.TimeRange; import com.sap.sse.common.Util.Pair; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceImpl.java deleted file mode 100644 index 5bb6e3f4f86..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceImpl.java +++ /dev/null @@ -1,264 +0,0 @@ -package com.sap.sailing.gwt.server; - -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Random; -import java.util.Set; -import java.util.UUID; - -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; - -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.gwt.ui.client.HomeService; -import com.sap.sailing.gwt.ui.server.Activator; -import com.sap.sailing.gwt.ui.server.ProxiedRemoteServiceServlet; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO.EventSeriesState; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaConstants; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; -import com.sap.sailing.server.RacingEventService; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.util.ServiceTrackerFactory; - -/** - * The server side implementation of the RPC service. - */ -public class HomeServiceImpl extends ProxiedRemoteServiceServlet implements HomeService { - private static final long serialVersionUID = 3947782997746039939L; - - public static final int MAX_STAGE_EVENTS = 5; - private static final int MAX_RECENT_EVENTS = 3; - private static final int MAX_VIDEO_COUNT = 3; - - private final ServiceTracker racingEventServiceTracker; - - public HomeServiceImpl() { - BundleContext context = Activator.getDefault(); - - racingEventServiceTracker = ServiceTrackerFactory.createAndOpen(context, RacingEventService.class); - } - - protected RacingEventService getService() { - return racingEventServiceTracker.getService(); - } - - @Override - public StartViewDTO getStartView() throws MalformedURLException { - EventStageCandidateCalculator stageCandidateCalculator = new EventStageCandidateCalculator(); - RecentEventsCalculator recentEventsCalculator = new RecentEventsCalculator(); - - HomeServiceUtil.forAllPublicEvents(getService(), getThreadLocalRequest(), stageCandidateCalculator, recentEventsCalculator); - - StartViewDTO result = new StartViewDTO(); - - int count = 0; - for(Pair pair : stageCandidateCalculator.getFeaturedEvents()) { - StageEventType stageType = pair.getA(); - EventHolder holder = pair.getB(); - - count++; - if(count > MAX_STAGE_EVENTS && stageType != StageEventType.RUNNING) { - break; - } - - result.addStageEvent(HomeServiceUtil.convertToEventStageDTO(holder.event, holder.baseURL, holder.onRemoteServer, stageType, getService(), false)); - - EventReferenceDTO eventRef = new EventReferenceDTO(holder.event); - - Iterable videosOfEvent = holder.event.getVideos(); - if (!Util.isEmpty(videosOfEvent) && result.getVideos().size() < MAX_VIDEO_COUNT) { - VideoDescriptor youTubeRandomUrl = HomeServiceUtil.getRandomVideo(videosOfEvent); - - MimeType type = youTubeRandomUrl.getMimeType(); - if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { - SailingVideoDTO candidate = new SailingVideoDTO(eventRef, youTubeRandomUrl.getURL().toString(), type, // - youTubeRandomUrl.getCreatedAtDate().asDate() - ); - candidate.setTitle(holder.event.getName()); - result.addVideo(candidate); - } - } - } - - final Set photoGalleryUrls = new HashSet<>(); // using a HashSet here leads to a reasonable - // amount of shuffling - final List videoCandidates = new ArrayList<>(); - - for(EventHolder holder : recentEventsCalculator.getRecentEventsOfLast12Month()) { - if(result.getRecentEvents().size() < MAX_RECENT_EVENTS) { - result.addRecentEvent(HomeServiceUtil.convertToEventListDTO(holder.event, holder.baseURL, holder.onRemoteServer, getService())); - } - - EventBase event = holder.event; - EventReferenceDTO eventRef = new EventReferenceDTO(holder.event); - - for (ImageDescriptor url : HomeServiceUtil.getSailingLovesPhotographyImages(event)) { - if(url.hasSize()) { - SailingImageDTO sailingImageDTO = new SailingImageDTO(eventRef, url.getURL().toString(), null); - sailingImageDTO.setSizeInPx(url.getWidthInPx(), url.getHeightInPx()); - photoGalleryUrls.add(sailingImageDTO); - } - } - for (VideoDescriptor videoUrl : event.getVideos()) { - MimeType type = videoUrl.getMimeType(); - if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { - SailingVideoDTO candidate = new SailingVideoDTO(eventRef, videoUrl.getURL().toString(), type, // - videoUrl.getCreatedAtDate().asDate() - ); - candidate.setTitle(holder.event.getName()); - videoCandidates.add(candidate); - } - } - } - - final int numberOfCandidatesAvailable = videoCandidates.size(); - if (numberOfCandidatesAvailable <= (MAX_VIDEO_COUNT - result.getVideos().size())) { - // add all we have, no randomize - for (SailingVideoDTO video : videoCandidates) { - result.addVideo(video); - } - } else { - // fill up the list randomly from videoCandidates - final Random videosRandomizer = new Random(numberOfCandidatesAvailable); - randomlyPick: for (int i = 0; i < numberOfCandidatesAvailable; i++) { - int nextVideoindex = videosRandomizer.nextInt(numberOfCandidatesAvailable); - final SailingVideoDTO video = videoCandidates.get(nextVideoindex); - result.addVideo(video); - if (result.getVideos().size() == MAX_VIDEO_COUNT) { - break randomlyPick; - } - } - } - Random random = new Random(); - List shuffledPhotoGallery = new ArrayList<>(photoGalleryUrls); - final int gallerySize = photoGalleryUrls.size(); - for (int i = 0; i < gallerySize; i++) { - Collections.swap(shuffledPhotoGallery, i, random.nextInt(gallerySize)); - } - for (SailingImageDTO holder : shuffledPhotoGallery) { - result.addPhoto(holder); - } - // TODO media - return result; - } - - @Override - public EventSeriesViewDTO getEventSeriesViewById(UUID id) { - Event o = getService().getEvent(id); - if (o == null) { - throw new RuntimeException("Series not found"); - } - - EventSeriesViewDTO dto = new EventSeriesViewDTO(); - dto.setId(id); - ImageDescriptor logoImage = o.findImageWithTag(MediaTagConstants.LOGO); - dto.setLogoImage(logoImage != null ? HomeServiceUtil.convertToImageDTO(logoImage) : null); - // TODO implement correctly. We currently do not show media for series. - dto.setHasMedia(false); - - boolean oneEventStarted = false; - boolean oneEventLive = false; - boolean allFinished = true; - if (HomeServiceUtil.isFakeSeries(o)) { - LeaderboardGroup overallLeaderboardGroup = o.getLeaderboardGroups().iterator().next(); - dto.setDisplayName(overallLeaderboardGroup.getDisplayName() != null ? overallLeaderboardGroup.getDisplayName() : overallLeaderboardGroup.getName()); - - if (overallLeaderboardGroup.getOverallLeaderboard() != null) { - dto.setLeaderboardId(overallLeaderboardGroup.getOverallLeaderboard().getName()); - } - - List fakeSeriesEvents = new ArrayList(); - for (Event event : getService().getAllEvents()) { - for (LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { - if (overallLeaderboardGroup.equals(leaderboardGroup)) { - fakeSeriesEvents.add(event); - } - } - } - Collections.sort(fakeSeriesEvents, new Comparator() { - public int compare(Event e1, Event e2) { - return e1.getStartDate().compareTo(e2.getEndDate()); - } - }); - for(Event eventInSeries: fakeSeriesEvents) { - EventMetadataDTO eventOfSeries = HomeServiceUtil.convertToMetadataDTO(eventInSeries, getService()); - dto.addEvent(eventOfSeries); - - oneEventStarted |= eventOfSeries.isStarted(); - oneEventLive |= (eventOfSeries.isStarted() && !eventOfSeries.isFinished()); - allFinished &= eventOfSeries.isFinished(); - } - } - if(oneEventLive) { - dto.setState(EventSeriesState.RUNNING); - } else if(!oneEventStarted) { - dto.setState(EventSeriesState.UPCOMING); - } else if(allFinished) { - dto.setState(EventSeriesState.FINISHED); - } else { - dto.setState(EventSeriesState.IN_PROGRESS); - } - - dto.setHasAnalytics(oneEventStarted); - return dto; - } - - @Override - public MediaDTO getMediaForEvent(UUID eventId) { - Event event = getService().getEvent(eventId); - EventReferenceDTO eventRef = new EventReferenceDTO(event); - - String eventName = event.getName(); - MediaDTO media = new MediaDTO(); - for(ImageDescriptor image : HomeServiceUtil.getPhotoGalleryImages(event)) { - SailingImageDTO imageDTO = new SailingImageDTO(eventRef, image.getURL().toString(), image.getCreatedAtDate().asDate()); - imageDTO.setSizeInPx(image.getWidthInPx(), image.getHeightInPx()); - imageDTO.setTitle(image.getTitle() != null ? image.getTitle(): eventName); - imageDTO.setSubtitle(image.getSubtitle()); - imageDTO.setTags(image.getTags()); - imageDTO.setCopyright(image.getCopyright()); - imageDTO.setLocale(image.getLocale() != null ? image.getLocale().toString() : null); - media.addPhoto(imageDTO); - } - for(VideoDescriptor video : event.getVideos()) { - MimeType type = video.getMimeType(); - if (MediaConstants.SUPPORTED_VIDEO_TYPES.contains(type)) { - SailingVideoDTO videoDTO = HomeServiceUtil.toSailingVideoDTO(eventRef, video); - media.addVideo(videoDTO); - } - } - return media; - } - - @Override - public MediaDTO getMediaForEventSeries(UUID seriesId) { - // TODO implement correctly. We currently do not show media for series. - return getMediaForEvent(seriesId); - } - - @Override - public EventListViewDTO getEventListView() throws MalformedURLException { - EventListDataCalculator eventListDataCalculator = new EventListDataCalculator(getService()); - HomeServiceUtil.forAllPublicEvents(getService(), getThreadLocalRequest(), eventListDataCalculator); - return eventListDataCalculator.getResult(); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceUtil.java index 9f91cc689ae..d6e1ab0216b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/server/HomeServiceUtil.java @@ -29,25 +29,27 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListEventDTO; -import com.sap.sailing.gwt.ui.shared.general.EventMetadataDTO; -import com.sap.sailing.gwt.ui.shared.general.EventReferenceDTO; -import com.sap.sailing.gwt.ui.shared.general.EventState; +import com.sap.sailing.gwt.dispatch.client.exceptions.DispatchException; +import com.sap.sailing.gwt.dispatch.client.exceptions.ServerDispatchException; +import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO; +import com.sap.sailing.gwt.home.communication.event.EventReferenceDTO; +import com.sap.sailing.gwt.home.communication.event.EventState; +import com.sap.sailing.gwt.home.communication.eventlist.EventListEventDTO; +import com.sap.sailing.gwt.home.communication.media.SailingVideoDTO; +import com.sap.sailing.gwt.home.communication.start.EventStageDTO; +import com.sap.sailing.gwt.home.communication.start.StageEventType; import com.sap.sailing.gwt.ui.shared.media.MediaConstants; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; import com.sap.sailing.server.RacingEventService; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.MediaDescriptor; import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.common.media.VideoDescriptor; import com.sap.sse.gwt.client.media.ImageDTO; import com.sap.sse.gwt.client.media.VideoDTO; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.MediaDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public final class HomeServiceUtil { public interface EventVisitor { @@ -491,7 +493,8 @@ public final class HomeServiceUtil { return courseArea == null ? null : courseArea.getId().toString(); } - public static void forAllPublicEvents(RacingEventService service, HttpServletRequest request, EventVisitor... visitors) throws MalformedURLException { + public static void forAllPublicEvents(RacingEventService service, HttpServletRequest request, + EventVisitor... visitors) throws DispatchException { URL requestedBaseURL = getRequestBaseURL(request); for (Event event : service.getAllEvents()) { if(event.isPublic()) { @@ -523,14 +526,23 @@ public final class HomeServiceUtil { * to http://sapsailing.com. * @throws MalformedURLException */ - private static URL getRequestBaseURL(HttpServletRequest request) throws MalformedURLException { - final URL url = new URL(request.getRequestURL().toString()); - final URL baseURL = getBaseURL(url); - return baseURL; + public static URL getRequestBaseURL(HttpServletRequest request) throws DispatchException { + URL url; + try { + url = new URL(request.getRequestURL().toString()); + final URL baseURL = getBaseURL(url); + return baseURL; + } catch (MalformedURLException e) { + throw new ServerDispatchException(e); + } } - private static URL getBaseURL(URL url) throws MalformedURLException { - return new URL(url.getProtocol(), url.getHost(), url.getPort(), /* file */ ""); + private static URL getBaseURL(URL url) throws DispatchException { + try { + return new URL(url.getProtocol(), url.getHost(), url.getPort(), /* file */""); + } catch (MalformedURLException e) { + throw new ServerDispatchException(e); + } } public static boolean hasRegattaData(EventBase event) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationsDialog.java index 2f9512b9a72..406415114dc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationsDialog.java @@ -34,21 +34,33 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia protected final SailingServiceAsync sailingService; final ErrorReporter errorReporter; private boolean editable; + private String boatClass; + + protected String leaderboardName; + /** + * @param boatClass + * The boatClass parameter describes the default shown boat class for new competitors. The + * boatClass parameter is null, if you want to edit a competitor or there is no + * boat class for the new competitor. + */ public AbstractCompetitorRegistrationsDialog(final SailingServiceAsync sailingService, final StringMessages stringMessages, final ErrorReporter errorReporter, boolean editable, - DialogCallback> callback) { - super(stringMessages.registerCompetitors(), /*messsage*/ null, stringMessages.save(), stringMessages.cancel(), /*validator*/ null, callback); + DialogCallback> callback, String leaderboardName, String boatClass) { + super(stringMessages.registerCompetitors(), /* messsage */null, stringMessages.save(), stringMessages.cancel(), /* validator */ + null, callback); this.stringMessages = stringMessages; this.sailingService = sailingService; - this.errorReporter = errorReporter; + this.errorReporter = errorReporter; this.editable = editable; + this.leaderboardName = leaderboardName; + this.boatClass = boatClass; } - + @Override protected Widget getAdditionalWidget() { FlowPanel mainPanel = new FlowPanel(); - + Button addCompetitorButton = new Button(stringMessages.add(stringMessages.competitor())); addCompetitorButton.addClickHandler(new ClickHandler() { @Override @@ -56,7 +68,7 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia openAddCompetitorDialog(); } }); - + Button editCompetitorButton = new Button(stringMessages.edit(stringMessages.competitor())); editCompetitorButton.addClickHandler(new ClickHandler() { @Override @@ -65,11 +77,25 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia } }); + final Button inviteCompetitorsButton = new Button(stringMessages.inviteSelectedCompetitors()); + inviteCompetitorsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + Set competitors = registeredCompetitorsTable.getSelectionModel().getSelectedSet(); + + CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingService, stringMessages, + errorReporter); + helper.inviteCompetitors(competitors, leaderboardName); + } + }); + HorizontalPanel competitorRegistrationPanel = new HorizontalPanel(); CaptionPanel allCompetitorsPanel = new CaptionPanel(stringMessages.competitorPool()); CaptionPanel registeredCompetitorsPanel = new CaptionPanel(stringMessages.registeredCompetitors()); - allCompetitorsTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true); - registeredCompetitorsTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true); + allCompetitorsTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ + true, /* enablePager */true); + registeredCompetitorsTable = new CompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ + true, /* enablePager */true); allCompetitorsPanel.add(allCompetitorsTable); registeredCompetitorsPanel.add(registeredCompetitorsTable); VerticalPanel movePanel = new VerticalPanel(); @@ -95,16 +121,17 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia competitorRegistrationPanel.add(movePanel); competitorRegistrationPanel.setCellVerticalAlignment(movePanel, HasVerticalAlignment.ALIGN_MIDDLE); competitorRegistrationPanel.add(allCompetitorsPanel); - + refreshCompetitors(); - + mainPanel.add(addCompetitorButton); mainPanel.add(editCompetitorButton); + mainPanel.add(inviteCompetitorsButton); mainPanel.add(competitorRegistrationPanel); return mainPanel; } - + void move(CompetitorTableWrapper from, CompetitorTableWrapper to, Collection toMove) { if (!toMove.isEmpty()) { List newFromList = new ArrayList<>(); @@ -123,7 +150,6 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia move(from, to, from.getSelectionModel().getSelectedSet()); } - private void openAddCompetitorDialog() { new CompetitorEditDialog(stringMessages, new CompetitorDTOImpl(), new DataEntryDialog.DialogCallback() { @@ -145,39 +171,42 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia @Override public void cancel() { } - }).show(); + }, boatClass).show(); } - + private void openEditCompetitorDialog() { - //get currently selected competitor - if (registeredCompetitorsTable.getSelectionModel().getSelectedSet().size() != 1){ + // get currently selected competitor + if (registeredCompetitorsTable.getSelectionModel().getSelectedSet().size() != 1) { // show some warning } else { - final CompetitorDTO competitorToEdit = registeredCompetitorsTable.getSelectionModel().getSelectedSet().iterator().next(); + final CompetitorDTO competitorToEdit = registeredCompetitorsTable.getSelectionModel().getSelectedSet() + .iterator().next(); new CompetitorEditDialog(stringMessages, competitorToEdit, new DataEntryDialog.DialogCallback() { - @Override - public void ok(CompetitorDTO competitor) { - sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Error trying to add competitor: " + caught.getMessage()); + public void ok(CompetitorDTO competitor) { + sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to add competitor: " + caught.getMessage()); + } + + @Override + public void onSuccess(CompetitorDTO updatedCompetitor) { + int editedCompetitorIndex = registeredCompetitorsTable.getDataProvider().getList() + .indexOf(competitorToEdit); + registeredCompetitorsTable.getDataProvider().getList().remove(competitorToEdit); + registeredCompetitorsTable.getDataProvider().getList() + .add(editedCompetitorIndex, updatedCompetitor); + registeredCompetitorsTable.getDataProvider().refresh(); + } + }); } @Override - public void onSuccess(CompetitorDTO updatedCompetitor) { - int editedCompetitorIndex = registeredCompetitorsTable.getDataProvider().getList().indexOf(competitorToEdit); - registeredCompetitorsTable.getDataProvider().getList().remove(competitorToEdit); - registeredCompetitorsTable.getDataProvider().getList().add(editedCompetitorIndex, updatedCompetitor); - registeredCompetitorsTable.getDataProvider().refresh(); + public void cancel() { } - }); - } - - @Override - public void cancel() { - } - }).show(); + }, /* boatClass */null).show(); } } @@ -188,13 +217,13 @@ public abstract class AbstractCompetitorRegistrationsDialog extends DataEntryDia public void onSuccess(Iterable result) { setRegisteredCompetitors(); } - + @Override public void onFailure(Throwable reason) { } }); } - + protected abstract void setRegisteredCompetitors(); @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java index aa340f49a3f..26586556dbb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java @@ -25,7 +25,7 @@ public abstract class AbstractLeaderboardDialog extends DataEntryDialog(competitorPanel) { @Override public void refreshAfterBecomingVisible() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index b17da901891..d2d337e1787 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -14,6 +14,7 @@ import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -49,8 +50,17 @@ public class CompetitorEditDialog extends DataEntryDialog { private final DoubleBox timeOnTimeFactor; private final DoubleBox timeOnDistanceAllowanceInSecondsPerNauticalMile; + /** + * The class creates the UI-dialog to type in the Data about a competitor. + * + * @param competitorToEdit + * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. + * @param boatClass + * The boat class is the default shown boat class for new competitors. Set null if your competitor is + * already initialized or you don´t want a default boat class. + */ public CompetitorEditDialog(final StringMessages stringMessages, CompetitorDTO competitorToEdit, - DialogCallback callback) { + DialogCallback callback, String boatClass) { super(stringMessages.editCompetitor(), null, stringMessages.ok(), stringMessages .cancel(), new Validator() { @Override @@ -71,10 +81,12 @@ public class CompetitorEditDialog extends DataEntryDialog { return result; } }, /* animationEnabled */true, callback); + this.ensureDebugId("CompetitorEditDialog"); this.stringMessages = stringMessages; this.competitorToEdit = competitorToEdit; - + this.boatClassName = createSuggestBox(BoatClassMasterdata.getAllBoatClassNames(/* includeAlternativeNames */ true)); + boatClassName.ensureDebugId("BoatClassNameSuggestBox"); int i=0; List boatClassNamesList = new ArrayList(); for (BoatClassMasterdata t : BoatClassMasterdata.values()) { @@ -83,8 +95,11 @@ public class CompetitorEditDialog extends DataEntryDialog { if (competitorToEdit.getBoatClass() != null) { boatClassName.setValue(competitorToEdit.getBoatClass().getName()); boatClassName.setEnabled(false); + } else { + boatClassName.setValue(boatClass); // widgets have to accept null values here } this.name = createTextBox(competitorToEdit.getName()); + name.ensureDebugId("NameTextBox"); this.email = createTextBox(competitorToEdit.getEmail()); this.displayColorTextBox = createTextBox(competitorToEdit.getColor() == null ? "" : competitorToEdit.getColor().getAsHtml()); this.threeLetterIocCountryCode = createListBox(/* isMultipleSelect */ false); @@ -115,6 +130,7 @@ public class CompetitorEditDialog extends DataEntryDialog { } } this.sailId = createTextBox(competitorToEdit.getSailID()); + sailId.ensureDebugId("SailIdTextBox"); this.flagImageURL = new URLFieldWithFileUpload(stringMessages); this.flagImageURL.setURL(competitorToEdit.getFlagImageURL()); this.imageUrlAndUploadComposite = new URLFieldWithFileUpload(stringMessages); @@ -174,11 +190,12 @@ public class CompetitorEditDialog extends DataEntryDialog { } } BoatClassDTO boatClass = new BoatClassDTO(boatClassName.getValue(), 0); + BoatDTO boat = new BoatDTO(name.getText(), sailId.getText()); CompetitorDTO result = new CompetitorDTOImpl(name.getText(), color, email.getText(), /* twoLetterIsoCountryCode */ null, threeLetterIocCountryCode.getValue(threeLetterIocCountryCode.getSelectedIndex()), - /* countryName */ null, sailId.getText(), competitorToEdit.getIdAsString(), - imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boatClass, + /* countryName */ null, competitorToEdit.getIdAsString(), + imageUrlAndUploadComposite.getURL(), flagImageURL.getURL(), boat, boatClass, timeOnTimeFactor.getValue(), timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue() == null ? null : new MillisecondsDurationImpl((long) (timeOnDistanceAllowanceInSecondsPerNauticalMile.getValue()*1000))); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java new file mode 100644 index 00000000000..a138108574c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java @@ -0,0 +1,83 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.Set; + +import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; + +public class CompetitorInvitationHelper { + + private StringMessages stringMessages; + private SailingServiceAsync sailingService; + private ErrorReporter errorReporter; + + public CompetitorInvitationHelper(SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter) { + this.stringMessages = stringMessages; + this.sailingService = sailingService; + this.errorReporter = errorReporter; + } + + public void inviteCompetitors(Set competitors, String leaderboardName) { + if (competitors.size() == 0){ + Window.alert(stringMessages.selectAtLeastOneCompetitorForInvitation()); + } else { + boolean emailProvidedForAll = isEmailProvidedForAll(competitors); + + if (emailProvidedForAll) { + openChooseEventDialogAndSendMails(competitors, leaderboardName); + } else { + Window.alert(stringMessages.notAllCompetitorsProvideEmail()); + } + } + } + + private boolean isEmailProvidedForAll(Iterable allCompetitors) { + for (CompetitorDTO competitor : allCompetitors) { + if (!competitor.hasEmail()) { + return false; + } + } + + return true; + } + + private void openChooseEventDialogAndSendMails(final Set competitors, final String leaderboardName) { + new SelectEventAndHostnameDialog(sailingService, stringMessages, errorReporter, leaderboardName, new DialogCallback>() { + + @Override + public void ok(Pair result) { + sailingService.inviteCompetitorsForTrackingViaEmail(result.getB(), result.getA(), leaderboardName, + competitors, getLocaleInfo(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert(stringMessages.sendingMailsFailed() + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + Window.alert(stringMessages.sendingMailsSuccessful()); + } + }); + } + + @Override + public void cancel() { + + } + }).show(); + } + + + private String getLocaleInfo() { + return LocaleInfo.getCurrentLocale().getLocaleName(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java index 40400c7600f..245273a3680 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java @@ -8,7 +8,6 @@ import java.util.Set; import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; @@ -22,9 +21,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorDTOImpl; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -81,6 +78,7 @@ public class CompetitorPanel extends SimplePanel { }); buttonPanel.add(allowReloadButton); Button addCompetitorButton = new Button(stringMessages.add()); + addCompetitorButton.ensureDebugId("AddCompetitorButton"); addCompetitorButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -108,27 +106,8 @@ public class CompetitorPanel extends SimplePanel { public void onClick(ClickEvent event) { Set competitors = competitorSelectionModel.getSelectedSet(); - if (competitors.size() == 0){ - Window.alert(stringMessages.selectAtLeastOneCompetitorForInvitation()); - } else { - boolean emailProvidedForAll = isEmailProvidedForAll(competitors); - - if (emailProvidedForAll) { - openChooseEventDialogAndSendMails(competitors); - } else { - Window.alert(stringMessages.notAllCompetitorsProvideEmail()); - } - } - } - - private boolean isEmailProvidedForAll(Iterable allCompetitors) { - for (CompetitorDTO competitor : allCompetitors) { - if (!competitor.hasEmail()) { - return false; - } - } - - return true; + CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingService, stringMessages, errorReporter); + helper.inviteCompetitors(competitors, leaderboardName); } }); buttonPanel.add(inviteCompetitorsButton); @@ -188,7 +167,7 @@ public class CompetitorPanel extends SimplePanel { } private void openEditCompetitorDialog(CompetitorDTO competitor) { - new CompetitorEditDialog(stringMessages, competitor, new DialogCallback() { + final CompetitorEditDialog dialog = new CompetitorEditDialog(stringMessages, competitor, new DialogCallback() { @Override public void ok(CompetitorDTO competitor) { sailingService.addOrUpdateCompetitor(competitor, new AsyncCallback() { @@ -207,38 +186,9 @@ public class CompetitorPanel extends SimplePanel { @Override public void cancel() { } - }).show(); - } - - private String getLocaleInfo() { - return LocaleInfo.getCurrentLocale().getLocaleName(); - } - - private void openChooseEventDialogAndSendMails(final Set competitors) { - new SelectEventAndHostnameDialog(sailingService, stringMessages, errorReporter, leaderboardName, new DialogCallback>() { - - @Override - public void ok(Pair result) { - sailingService.inviteCompetitorsForTrackingViaEmail(result.getB(), result.getA(), leaderboardName, - competitors, getLocaleInfo(), new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - Window.alert(stringMessages.sendingMailsFailed() + caught.getMessage()); - } - - @Override - public void onSuccess(Void result) { - Window.alert(stringMessages.sendingMailsSuccessful()); - } - }); - } - - @Override - public void cancel() { - - } - }).show(); + }, /* boat class to be used from CompetitorDTO */ null); + dialog.ensureDebugId("CompetitorEditDialog"); + dialog.show(); } public void refreshCompetitorList() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index 17a598fa13e..9b74a2a56cb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -209,6 +209,7 @@ public class CompetitorTableWrapper> ext table.addColumn(imageColumn, stringMessages.image()); table.addColumn(competitorEMailColumn, stringMessages.email()); table.addColumn(competitorIdColumn, stringMessages.id()); + table.ensureDebugId("CompetitorsTable"); } public Iterable getAllCompetitors() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index 87b3e70d64c..51bd281f3dd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -145,7 +145,7 @@ public abstract class EventDialog extends DataEntryDialogWithBootstrap } leaderboardGroupList = new StringConstantsListEditorComposite(Collections. emptyList(), new StringConstantsListEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(), - leaderboardGroupNames, "Select a leaderboard group...")); + leaderboardGroupNames, stringMessages.selectALeaderboardGroup())); leaderboardGroupList.addValueChangeHandler(valueChangeHandler); imagesListComposite = new ImagesListComposite(sailingService, stringMessages); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageCreateDialog.java index 5d5a4a6acb9..141a3f74a45 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageCreateDialog.java @@ -25,7 +25,7 @@ public class ImageCreateDialog extends ImageDialog { heightInPxBox = createIntegerBox(null, 10); heightInPxBox.setEnabled(false); List tags = new ArrayList<>(); - if(initialTag != null && !initialTag.isEmpty()) { + if (initialTag != null && !initialTag.isEmpty()) { tags.add(initialTag); } tagsListEditor.setValue(tags); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java index 1c366e76b7d..dd67a567fda 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImageDialog.java @@ -59,22 +59,31 @@ public abstract class ImageDialog extends DataEntryDialog { Integer imageWidth = imageToValidate.getWidthInPx(); Integer imageHeight = imageToValidate.getHeightInPx(); - if(imageToValidate.getSourceRef() == null || imageToValidate.getSourceRef().isEmpty()) { + if (imageToValidate.getSourceRef() == null || imageToValidate.getSourceRef().isEmpty()) { errorMessage = stringMessages.pleaseEnterNonEmptyUrl(); - } else if(imageWidth == null || imageHeight == null) { - errorMessage = "The width and height of the image could not retrieved yet."; - } else if(imageToValidate.hasTag(MediaTagConstants.LOGO) && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_LOGO_IMAGE_WIDTH, - MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, MediaConstants.MAX_LOGO_IMAGE_HEIGHT)) { + } else if (imageWidth == null || imageHeight == null) { + errorMessage = stringMessages.couldNotRetrieveImageSizeYet(); + } else if (imageToValidate.hasTag(MediaTagConstants.LOGO) + && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_LOGO_IMAGE_WIDTH, + MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, + MediaConstants.MAX_LOGO_IMAGE_HEIGHT)) { errorMessage = getSizeErrorMessage("Logo", MediaConstants.MIN_LOGO_IMAGE_WIDTH, - MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, MediaConstants.MAX_LOGO_IMAGE_HEIGHT); - } else if(imageToValidate.hasTag(MediaTagConstants.TEASER) && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_EVENTTEASER_IMAGE_WIDTH, - MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT)) { + MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, + MediaConstants.MAX_LOGO_IMAGE_HEIGHT, stringMessages); + } else if (imageToValidate.hasTag(MediaTagConstants.TEASER) + && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_EVENTTEASER_IMAGE_WIDTH, + MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, + MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT)) { errorMessage = getSizeErrorMessage("Event-Teaser", MediaConstants.MIN_EVENTTEASER_IMAGE_WIDTH, - MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT); - } else if(imageToValidate.hasTag(MediaTagConstants.STAGE) && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_STAGE_IMAGE_WIDTH, - MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, MediaConstants.MAX_STAGE_IMAGE_HEIGHT)) { + MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, + MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT, stringMessages); + } else if (imageToValidate.hasTag(MediaTagConstants.STAGE) + && !isValidSize(imageWidth, imageHeight, MediaConstants.MIN_STAGE_IMAGE_WIDTH, + MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, + MediaConstants.MAX_STAGE_IMAGE_HEIGHT)) { errorMessage = getSizeErrorMessage("Stage", MediaConstants.MIN_STAGE_IMAGE_WIDTH, - MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, MediaConstants.MAX_STAGE_IMAGE_HEIGHT); + MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, + MediaConstants.MAX_STAGE_IMAGE_HEIGHT, stringMessages); } return errorMessage; } @@ -83,24 +92,19 @@ public abstract class ImageDialog extends DataEntryDialog { return width >= minWidth && width <= maxWidth && height >= minHeight && height <= maxHeight; } - private String getSizeErrorMessage(String imageType, int minWidth, int maxWidth, int minHeight, int maxHeight) { - String errorMessage = "The size of the " + imageType + " image does not fit. "; - errorMessage += "The width should be between " + minWidth + " and " + maxWidth + " px "; - errorMessage += " and the height between " + minHeight + " and " + maxHeight + " px."; + private String getSizeErrorMessage(String imageType, int minWidth, int maxWidth, int minHeight, int maxHeight, StringMessages stringMessages) { + String errorMessage = stringMessages.imageSizeError(imageType, minWidth, maxWidth, minHeight, maxHeight); return errorMessage; } } public ImageDialog(Date creationDate, ImageParameterValidator validator, SailingServiceAsync sailingService, StringMessages stringMessages, DialogCallback callback) { - super(stringMessages.image(), null, stringMessages.ok(), stringMessages.cancel(), validator, - callback); + super(stringMessages.image(), null, stringMessages.ok(), stringMessages.cancel(), validator, callback); this.sailingService = sailingService; this.stringMessages = stringMessages; this.creationDate = creationDate; getDialogBox().getWidget().setWidth("730px"); - busyIndicator = new SimpleBusyIndicator(); - imageURLAndUploadComposite = new URLFieldWithFileUpload(stringMessages); imageURLAndUploadComposite.addValueChangeHandler(new ValueChangeHandler() { @Override @@ -111,7 +115,7 @@ public abstract class ImageDialog extends DataEntryDialog { @Override public void onSuccess(Pair imageSize) { busyIndicator.setBusy(false); - if(imageSize != null) { + if (imageSize != null) { widthInPxBox.setValue(imageSize.getA()); heightInPxBox.setValue(imageSize.getB()); } @@ -138,7 +142,7 @@ public abstract class ImageDialog extends DataEntryDialog { result.setTitle(titleTextBox.getValue()); result.setSubtitle(subtitleTextBox.getValue()); result.setCopyright(copyrightTextBox.getValue()); - if(widthInPxBox.getValue() != null && heightInPxBox.getValue() != null) { + if (widthInPxBox.getValue() != null && heightInPxBox.getValue() != null) { result.setSizeInPx(widthInPxBox.getValue(), heightInPxBox.getValue()); } List tags = new ArrayList(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java index 059f0529a48..62b33738ced 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java @@ -78,7 +78,7 @@ public class ImagesListComposite extends Composite { imagesControlsPanel.setSpacing(5); panel.add(imagesControlsPanel); - Button addPhotoBtn = new Button("Add gallery photo"); + Button addPhotoBtn = new Button(stringMessages.addGalleryPhoto()); addPhotoBtn.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -87,7 +87,7 @@ public class ImagesListComposite extends Composite { }); imagesControlsPanel.add(addPhotoBtn); - Button addStateImageBtn = new Button("Add stage image"); + Button addStateImageBtn = new Button(stringMessages.addStageImage()); addStateImageBtn.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -96,7 +96,7 @@ public class ImagesListComposite extends Composite { }); imagesControlsPanel.add(addStateImageBtn); - Button addEventTeaseImageBtn = new Button("Add teaser image"); + Button addEventTeaseImageBtn = new Button(stringMessages.addTeaserImage()); addEventTeaseImageBtn.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -105,7 +105,7 @@ public class ImagesListComposite extends Composite { }); imagesControlsPanel.add(addEventTeaseImageBtn); - Button addLogoImageBtn = new Button("Add event logo"); + Button addLogoImageBtn = new Button(stringMessages.addEventLogo()); addLogoImageBtn.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { @@ -128,7 +128,7 @@ public class ImagesListComposite extends Composite { panel.add(imageTable); - noImagesLabel = new Label("No images defined yet."); + noImagesLabel = new Label(stringMessages.noImagesDefinedYet()); noImagesLabel.ensureDebugId("NoImagesLabel"); noImagesLabel.setWordWrap(false); panel.add(noImagesLabel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java index c9ffaffecd4..4e370e2e10d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java @@ -157,7 +157,8 @@ public class LeaderboardGroupDialog extends DataEntryDialog> callback) { - super(sailingService, stringMessages, errorReporter, editable, callback); - this.leaderboardName = leaderboardName; + super(sailingService, stringMessages, errorReporter, editable, callback, leaderboardName, boatClass); this.raceColumnName = raceColumnName; this.fleetName = fleetName; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java index 0790c403d34..623f5cf53f2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java @@ -126,6 +126,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { @Override public void onSuccess(RaceCourseDTO result) { updateWaypointsAndControlPoints(result); + marks.refresh(result.getMarks()); } @Override @@ -133,18 +134,5 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { errorReporter.reportError("Could not load course: " + caught.getMessage()); } }); - - sailingService.getMarksInRaceLog(leaderboardName, raceColumnName, fleetName, - new AsyncCallback>() { - @Override - public void onSuccess(Iterable result) { - marks.refresh(result); - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Could not load marks: " + caught.getMessage()); - } - }); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java index 8cf53ed4394..73cb1f1e157 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java @@ -11,13 +11,10 @@ import com.sap.sse.gwt.client.ErrorReporter; public class RegattaLogCompetitorRegistrationDialog extends AbstractCompetitorRegistrationsDialog { - private String leaderboardName; - - public RegattaLogCompetitorRegistrationDialog(SailingServiceAsync sailingService, StringMessages stringMessages, + public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback) { - super(sailingService, stringMessages, errorReporter, editable, callback); - this.leaderboardName = leaderboardName; + super(sailingService, stringMessages, errorReporter, editable, callback, leaderboardName, boatClass); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java index dc4db1d817f..5e0b95de21f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsDialog.java @@ -46,7 +46,7 @@ public abstract class RegattaWithSeriesAndFleetsDialog extends AbstractRegattaWi @Override protected RegattaDTO getResult() { RegattaDTO result = getRegattaDTO(); - result.setName(nameEntryField.getText().trim()); // trim to particularly avoid trailing slashes + result.setName(nameEntryField.getText().trim()); // trim to particularly avoid trailing blanks result.boatClass = new BoatClassDTO(boatClassEntryField.getText(), 0.0); return result; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java index d7c2c30cfa3..7d8bb340977 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.shared.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.LocaleInfo; @@ -34,7 +35,9 @@ import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO; +import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; import com.sap.sse.gwt.client.ErrorReporter; @@ -51,12 +54,12 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC private CheckBox trackWind; protected boolean regattaHasCompetitors = false; + public SmartphoneTrackingEventManagementPanel(SailingServiceAsync sailingService, RegattaRefresher regattaRefresher, LeaderboardsRefresher leaderboardsRefresher, ErrorReporter errorReporter, StringMessages stringMessages) { super(sailingService, regattaRefresher, leaderboardsRefresher, errorReporter, stringMessages, /* multiSelection */ true); - // add upload panel CaptionPanel importPanel = new CaptionPanel(stringMessages.importFixes()); VerticalPanel importContent = new VerticalPanel(); @@ -69,6 +72,10 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC importContent.add(deviceIdentifierTable); } + private static interface ShowWithBoatClass { + void showWithBoatClass(String boatClassName); + } + /** * When doing race log tracking, the Remove and Stop Tracking buttons are required. */ @@ -101,36 +108,42 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC @Override public void update(int index, StrippedLeaderboardDTO leaderboardDTO, String value) { final String leaderboardName = leaderboardDTO.name; -// final String eventIdAsString = leaderboardDTO. if (RaceLogTrackingEventManagementImagesBarCell.ACTION_DENOTE_FOR_RACELOG_TRACKING.equals(value)) { denoteForRaceLogTracking(leaderboardDTO); } else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_COMPETITOR_REGISTRATIONS.equals(value)) { - new RegattaLogCompetitorRegistrationDialog(sailingService, stringMessages, errorReporter, /*editable*/ true, - leaderboardName, new DialogCallback>() { + ShowWithBoatClass showWithBoatClass = new ShowWithBoatClass() { + @Override + public void showWithBoatClass(String boatClassName) { + new RegattaLogCompetitorRegistrationDialog(boatClassName, sailingService, stringMessages, + errorReporter, /* editable */true, leaderboardName, + new DialogCallback>() { + @Override + public void ok(Set registeredCompetitors) { + sailingService.setCompetitorRegistrationsInRegattaLog(leaderboardName, + registeredCompetitors, new AsyncCallback() { + @Override + public void onSuccess(Void result) { + // pass + } - @Override - public void ok(Set registeredCompetitors) { - sailingService.setCompetitorRegistrationsInRegattaLog(leaderboardName, registeredCompetitors, - new AsyncCallback() { - @Override - public void onSuccess(Void result) { - // pass - } + @Override + public void onFailure(Throwable caught) { + errorReporter + .reportError("Could not save competitor registrations: " + + caught.getMessage()); + } + }); + } - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Could not save competitor registrations: " - + caught.getMessage()); - } - }); - } + @Override + public void cancel() { - @Override - public void cancel() { - - } + } + }).show(); + } - }).show(); + }; + searchBoatClass(showWithBoatClass); } else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_MAP_DEVICES.equals(value)) { new RegattaLogTrackingDeviceMappingsDialog(sailingService, stringMessages, errorReporter, leaderboardName, new DialogCallback() { @@ -148,6 +161,8 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC showRegattaLog(); } } + + }); leaderboardTable.addColumn(selectionCheckboxColumn, selectionCheckboxColumn.getHeader()); leaderboardTable.addColumn(leaderboardNameColumn, stringMessages.name()); @@ -169,6 +184,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC return race.getA().getRaceLogTrackingInfo(race.getB()).competitorRegistrationsExists; } + @Override protected void addColumnsToRacesTable(CellTable racesTable) { TextColumn raceLogTrackingStateColumn = new TextColumn() { @@ -195,7 +211,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC final String leaderboardName = getSelectedLeaderboardName(); final String raceColumnName = raceColumnDTOAndFleetDTO.getA().getName(); final String fleetName = raceColumnDTOAndFleetDTO.getB().getName(); - boolean editable = ! (doesTrackerExist(raceColumnDTOAndFleetDTO) && + final boolean editable = ! (doesTrackerExist(raceColumnDTOAndFleetDTO) && getTrackingState(raceColumnDTOAndFleetDTO) == RaceLogTrackingState.TRACKING); if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_DENOTE_FOR_RACELOG_TRACKING.equals(value)) { denoteForRaceLogTracking(raceColumnDTOAndFleetDTO.getA(), raceColumnDTOAndFleetDTO.getB()); @@ -203,34 +219,41 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC removeDenotation(raceColumnDTOAndFleetDTO.getA(), raceColumnDTOAndFleetDTO.getB()); } else if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_COMPETITOR_REGISTRATIONS .equals(value)) { - new RaceLogCompetitorRegistrationDialog(sailingService, stringMessages, errorReporter, editable, leaderboardName, - raceColumnName, fleetName, new DialogCallback>() { - + ShowWithBoatClass showWithBoatClass = new ShowWithBoatClass() { @Override - public void ok(final Set registeredCompetitors) { - sailingService.setCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, - fleetName, registeredCompetitors, new AsyncCallback() { - @Override - public void onSuccess(Void result) { - } + public void showWithBoatClass(String boatClassName) { + new RaceLogCompetitorRegistrationDialog(boatClassName, sailingService, stringMessages, + errorReporter, editable, leaderboardName, raceColumnName, fleetName, + new DialogCallback>() { - @Override - public void onFailure(Throwable caught) { - errorReporter - .reportError("Could not save competitor registrations: " - + caught.getMessage()); - } - }); - } + @Override + public void ok(final Set registeredCompetitors) { + sailingService.setCompetitorRegistrationsInRaceLog(leaderboardName, + raceColumnName, fleetName, registeredCompetitors, + new AsyncCallback() { + @Override + public void onSuccess(Void result) { + } - @Override - public void cancel() { + @Override + public void onFailure(Throwable caught) { + errorReporter + .reportError("Could not save competitor registrations: " + + caught.getMessage()); + } + }); + } + + @Override + public void cancel() { + } + }).show(); } - }).show(); + }; + searchBoatClass(showWithBoatClass); } else if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_DEFINE_COURSE.equals(value)) { new RaceLogTrackingCourseDefinitionDialog(sailingService, stringMessages, errorReporter, leaderboardName, raceColumnName, fleetName, new DialogCallback>>() { - @Override public void cancel() { } @@ -548,6 +571,46 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC } }).show(); - + } + + private void searchBoatClass(final ShowWithBoatClass showWithBoatClass) { + final String result; + RegattaDTO regatta = null; + if (getSelectedLeaderboard().regattaName != null) { + if (allRegattas != null) { + for (RegattaDTO i : allRegattas) { + if (getSelectedLeaderboard().regattaName.equals(i.getName())) { + regatta = i; + break; + } + } + } + } + if (regatta != null) { + result = regatta.boatClass.getName(); + showWithBoatClass.showWithBoatClass(result); + } else { + sailingService.getCompetitorsOfLeaderboard(getSelectedLeaderboardName(), + new AsyncCallback>() { + @Override + public void onFailure(Throwable caught) { + GWT.log("Error while searching BoatClass."); + showWithBoatClass.showWithBoatClass(null); + } + + @Override + public void onSuccess(Iterable result) { + String boatClass = null; + if (result != null) { + List boatClassen = new ArrayList<>(); + for (CompetitorDTO comp : result) { + boatClassen.add(comp.getBoatClass().getName()); + } + boatClass = Util.getDominantObject(boatClassen); + } + showWithBoatClass.showWithBoatClass(boatClass); + } + }); + } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java index 7579a1bdff5..4c94d5512d6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java @@ -30,8 +30,8 @@ public class TrackedRacesManagementPanel extends AbstractRaceManagementPanel { private final Grid raceDataGrid; public TrackedRacesManagementPanel(final SailingServiceAsync sailingService, ErrorReporter errorReporter, - RegattaRefresher regattaRefresher, StringMessages stringConstants) { - super(sailingService, errorReporter, regattaRefresher, stringConstants); + RegattaRefresher regattaRefresher, final StringMessages stringMessages) { + super(sailingService, errorReporter, regattaRefresher, /* actionButtonsEnabled */ true, stringMessages); HorizontalPanel controlsPanel = new HorizontalPanel(); Button setStartTimeButton = new Button(stringMessages.setStartTimeReceived(), new ClickHandler() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProvider.java new file mode 100644 index 00000000000..295205c0df6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProvider.java @@ -0,0 +1,22 @@ +package com.sap.sailing.gwt.ui.client; + +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sse.common.Color; + +/** + * + * A color provider for a competitor. A color of a competitor can either be the same for all races of a regatta or it + * can be race specific. Race specific can make sense e.g. when a competitor is changing it's boat during a regatta. + * + * @author Frank Mittag + */ +public interface CompetitorColorProvider { + Color getColor(CompetitorDTO competitor); + + Color getColor(CompetitorDTO competitor, RegattaAndRaceIdentifier raceIdentfier); + + void addBlockedColor(Color color); + + void removeBlockedColor(Color color); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProviderImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProviderImpl.java new file mode 100644 index 00000000000..07afa3256b4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorColorProviderImpl.java @@ -0,0 +1,78 @@ +package com.sap.sailing.gwt.ui.client; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.sap.sailing.domain.common.ColorMap; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.impl.ColorMapImpl; +import com.sap.sse.common.Color; + +public class CompetitorColorProviderImpl implements CompetitorColorProvider { + private final ColorMap competitorsColorMap; + private final Map> competitorsBoatColorsPerRace; + + public CompetitorColorProviderImpl() { + this(null, Collections. emptyMap()); + } + + public CompetitorColorProviderImpl(RegattaAndRaceIdentifier raceIdentifier, + Map competitorsAndTheirBoats) { + this.competitorsColorMap = new ColorMapImpl(); + this.competitorsBoatColorsPerRace = new HashMap>(); + if (raceIdentifier != null) { + for (Entry competitorAndBoat : competitorsAndTheirBoats.entrySet()) { + if (competitorAndBoat.getValue() != null) { + Map raceColors = competitorsBoatColorsPerRace.get(raceIdentifier); + if (raceColors == null) { + raceColors = new HashMap(); + competitorsBoatColorsPerRace.put(raceIdentifier, raceColors); + } + Color boatColor = competitorAndBoat.getValue().getColor(); + if (boatColor != null) { + raceColors.put(competitorAndBoat.getKey(), boatColor); + addBlockedColor(boatColor); + } + } + } + } + } + + @Override + public Color getColor(CompetitorDTO competitor) { + return getColor(competitor, null); + } + + @Override + public Color getColor(CompetitorDTO competitor, RegattaAndRaceIdentifier raceIdentfier) { + Color result = null; + if (raceIdentfier != null) { + Map raceColors = competitorsBoatColorsPerRace.get(raceIdentfier); + if (raceColors != null) { + result = raceColors.get(competitor); + } + } + if (result == null && competitor.getColor() != null) { + result = competitor.getColor(); + } + // fallback + if (result == null) { + result = competitorsColorMap.getColorByID(competitor); + } + return result; + } + + @Override + public void addBlockedColor(Color color) { + competitorsColorMap.addBlockedColor(color); + } + + @Override + public void removeBlockedColor(Color color) { + competitorsColorMap.removeBlockedColor(color); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionModel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionModel.java index 42c9fc4642b..62793384452 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionModel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionModel.java @@ -8,9 +8,8 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; -import com.sap.sailing.domain.common.ColorMap; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.domain.common.impl.ColorMapImpl; import com.sap.sse.common.Color; import com.sap.sse.common.Util; import com.sap.sse.common.filter.Filter; @@ -25,22 +24,26 @@ public class CompetitorSelectionModel implements CompetitorSelectionProvider { private final boolean hasMultiSelection; - private final ColorMap competitorsColorMap; - private FilterSet> competitorsFilterSet; + private final CompetitorColorProvider competitorColorProvider; + public CompetitorSelectionModel(boolean hasMultiSelection) { - this(hasMultiSelection, null); + this(hasMultiSelection, new CompetitorColorProviderImpl(), null); } - private CompetitorSelectionModel(boolean hasMultiSelection, FilterSet> competitorsFilterSet) { + public CompetitorSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider) { + this(hasMultiSelection, competitorColorProvider, null); + } + + private CompetitorSelectionModel(boolean hasMultiSelection, CompetitorColorProvider competitorColorProvider, FilterSet> competitorsFilterSet) { super(); this.hasMultiSelection = hasMultiSelection; + this.competitorColorProvider = competitorColorProvider; this.competitorsFilterSet = competitorsFilterSet; this.allCompetitors = new LinkedHashSet(); this.selectedCompetitors = new LinkedHashSet(); this.listeners = new HashSet(); - this.competitorsColorMap = new ColorMapImpl(); } /** @@ -53,8 +56,7 @@ public class CompetitorSelectionModel implements CompetitorSelectionProvider { private void add(CompetitorDTO competitor, boolean notifyListeners) { if (competitor.getColor() != null) { - Color color = competitor.getColor(); - competitorsColorMap.addBlockedColor(color); + competitorColorProvider.addBlockedColor(competitor.getColor()); } boolean changed = allCompetitors.add(competitor); if (notifyListeners && changed) { @@ -102,6 +104,9 @@ public class CompetitorSelectionModel implements CompetitorSelectionProvider { if (isSelected(competitor)) { setSelected(competitor, false); } + if (competitor.getColor() != null) { + competitorColorProvider.removeBlockedColor(competitor.getColor()); + } boolean changed = allCompetitors.remove(competitor); if (changed) { fireListChanged(getAllCompetitors()); @@ -228,20 +233,15 @@ public class CompetitorSelectionModel implements CompetitorSelectionProvider { fireListChanged(getAllCompetitors(), listenersNotToNotify); } } - + @Override public Color getColor(CompetitorDTO competitor) { - final Color result; - if (allCompetitors.contains(competitor)) { - if (competitor.getColor() != null) { - result = competitor.getColor(); - } else { - result = competitorsColorMap.getColorByID(competitor); - } - } else { - result = null; - } - return result; + return allCompetitors.contains(competitor) ? competitorColorProvider.getColor(competitor) : null; + } + + @Override + public Color getColor(CompetitorDTO competitor, RegattaAndRaceIdentifier raceIdentfier) { + return allCompetitors.contains(competitor) ? competitorColorProvider.getColor(competitor, raceIdentfier) : null; } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionProvider.java index 77a2e991641..09b05b99fa6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/CompetitorSelectionProvider.java @@ -1,5 +1,6 @@ package com.sap.sailing.gwt.ui.client; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sse.common.Color; import com.sap.sse.common.filter.Filter; @@ -61,6 +62,8 @@ public interface CompetitorSelectionProvider { boolean hasMultiSelection(); Color getColor(CompetitorDTO competitor); + + Color getColor(CompetitorDTO competitor, RegattaAndRaceIdentifier raceIdentfier); void addCompetitorSelectionChangeListener(CompetitorSelectionChangeListener listener); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeService.java deleted file mode 100644 index 429621a4b60..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.sap.sailing.gwt.ui.client; - -import java.util.UUID; - -import com.google.gwt.user.client.rpc.RemoteService; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; - -public interface HomeService extends RemoteService { - EventSeriesViewDTO getEventSeriesViewById(UUID id); - - MediaDTO getMediaForEvent(UUID eventId); - - MediaDTO getMediaForEventSeries(UUID seriesId); - - EventListViewDTO getEventListView() throws Exception; - - StartViewDTO getStartView() throws Exception; -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeServiceAsync.java deleted file mode 100644 index 01042a528bd..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/HomeServiceAsync.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sap.sailing.gwt.ui.client; - -import java.util.UUID; - -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.eventlist.EventListViewDTO; -import com.sap.sailing.gwt.ui.shared.fakeseries.EventSeriesViewDTO; -import com.sap.sailing.gwt.ui.shared.media.MediaDTO; -import com.sap.sailing.gwt.ui.shared.start.StartViewDTO; - - -/** - * The async counterpart of {@link HomeService} - */ -public interface HomeServiceAsync { - void getEventSeriesViewById(UUID id, AsyncCallback asyncCallback); - - void getMediaForEvent(UUID eventId, AsyncCallback callback); - - void getMediaForEventSeries(UUID seriesId, AsyncCallback callback); - - void getEventListView(AsyncCallback callback); - - void getStartView(AsyncCallback callback); -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java index dd94b520c50..ef6d167bb08 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimePanel.java @@ -45,7 +45,7 @@ public class RaceTimePanel extends TimePanel implements R String result = null; RaceTimesInfoDTO selectedRaceTimes = raceTimesInfoProvider.getRaceTimesInfo(selectedRace); if (selectedRaceTimes.startOfRace != null) { - if(time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) { + if (time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) { long timeToStartInMs = selectedRaceTimes.startOfRace.getTime() - time.getTime(); result = timeToStartInMs < 1000 ? stringMessages.start() : stringMessages.timeToStart(DateAndTimeFormatterUtil.formatElapsedTime(timeToStartInMs)); } else { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java index 6923844da16..8a8caed7121 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java @@ -22,8 +22,6 @@ public interface RemoteServiceMappingConstants { public static final String serverConfigurationServiceRemotePath = "service/serverconfiguration"; - public static final String homeServiceRemotePath = "service/home"; - public static final String simulatorServiceRemotePath = "service/simulator"; public static final String dataMiningServiceRemotePath = "service/datamining"; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingClientFactory.java index 1784ae32d98..0ac10ee5dcf 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingClientFactory.java @@ -14,8 +14,6 @@ import com.sap.sse.security.ui.client.UserService; public interface SailingClientFactory extends ClientFactory { SailingServiceAsync getSailingService(); - HomeServiceAsync getHomeService(); - MediaServiceAsync getMediaService(); UserManagementServiceAsync getUserManagementService(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 6880599eadd..594417853c8 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -11,7 +11,6 @@ import java.util.UUID; import com.google.gwt.user.client.rpc.RemoteService; import com.sap.sailing.domain.abstractlog.Revokable; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.base.RemoteSailingServerReference; import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.LeaderboardType; @@ -29,6 +28,7 @@ import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO; @@ -57,7 +57,6 @@ import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; @@ -65,6 +64,7 @@ import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceLogDTO; import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; +import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaLogDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -93,7 +93,6 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.mail.MailException; -import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.gwt.client.ServerInfoDTO; import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService; import com.sap.sse.gwt.client.media.ImageDTO; @@ -152,6 +151,10 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS SimulatorResultsDTO getSimulatorResults(LegIdentifier legIdentifier); + RaceboardDataDTO getRaceboardData(String regattaName, String raceName, String leaderboardName, String leaderboardGroupName, UUID eventId); + + Map getCompetitorBoats(RegattaAndRaceIdentifier raceIdentifier); + CompactRaceMapDataDTO getRaceMapData(RegattaAndRaceIdentifier raceIdentifier, Date date, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, boolean extrapolate, LegIdentifier simulationLegIdentifier) throws NoWindException; @@ -509,32 +512,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getTrackFileImportDeviceIds(List uuids) throws NoCorrespondingServiceRegisteredException, TransformationException; - /** - * A client should search a server in a two-step process. First, the client should ask the server which other - * servers are available for searching additional content. Then, in a second step, the client should fire the - * queries by parallel asynchronous calls to the one server, passing the name of the remote server reference to - * search, or null in order to search the server to which the query is sent by the call. This allows a - * client to asynchronously receive the results from various servers, not requiring the client to block until all - * results from all servers have been received. The key reason for this two-step process is that the GWT RPC does - * not support streaming of results. - * - * @return the list of server reference names, corresponding with {@link RemoteSailingServerReference#getName()}, to - * be used as parameter in {@link #search(String, KeywordQuery)}. This list does not contain the - * null value used to represent the search on the main server to which the query is sent. - */ - Iterable getSearchServerNames(); - - /** - * Call this method once for each result of {@link #getSearchServerNames()} and once with null for - * the serverNameOfNullForMain parameter. - * - * @param serverNameOrNullForMain - * use null to search on the server to which this request is sent; use a name as retrieved - * by {@link #getSearchServerNames()} which corresponds to a name of a - * {@link RemoteSailingServerReference}, to search a remote server. - */ - Iterable search(String serverNameOrNullForMain, KeywordQuery query) throws Exception; - /** * @return The RaceDTO of the modified race or null, if the given newStartTimeReceived was null. */ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 73a7c221b09..0165f4a1628 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -9,7 +9,6 @@ import java.util.Set; import java.util.UUID; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.domain.base.RemoteSailingServerReference; import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.LeaderboardType; @@ -26,6 +25,7 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO; @@ -49,7 +49,6 @@ import com.sap.sailing.gwt.ui.shared.EventBaseDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; @@ -57,6 +56,7 @@ import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; import com.sap.sailing.gwt.ui.shared.RaceLogDTO; import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; +import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaLogDTO; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; @@ -83,7 +83,6 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; -import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.gwt.client.ServerInfoRetriever; import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtServiceAsync; import com.sap.sse.gwt.client.media.ImageDTO; @@ -333,6 +332,11 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable windSourcesToExclude, AsyncCallback callback); + void getCompetitorBoats(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback> callback); + + void getRaceboardData(String regattaName, String raceName, String leaderboardName, + String leaderboardGroupName, UUID eventId, AsyncCallback callback); + /** * @param date * use null to indicate "live" in which case the server live time stamp for the race @@ -650,33 +654,6 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan void getTrackFileImportDeviceIds(List uuids, AsyncCallback> callback); - /** - * A client should search a server in a two-step process. First, the client should ask the server which other - * servers are available for searching additional content. Then, in a second step, the client should fire the - * queries by parallel asynchronous calls to the one server, passing the name of the remote server reference to - * search, or null in order to search the server to which the query is sent by the call. This allows a - * client to asynchronously receive the results from various servers, not requiring the client to block until all - * results from all servers have been received. The key reason for this two-step process is that the GWT RPC does - * not support streaming of results. - * - * @return the list of server reference names, corresponding with {@link RemoteSailingServerReference#getName()}, to - * be used as parameter in {@link #search(String, KeywordQuery)}. This list does not contain the - * null value used to represent the search on the main server to which the query is sent. - */ - void getSearchServerNames(AsyncCallback> callback); - - /** - * Call this method once for each result of {@link #getSearchServerNames()} and once with null for the - * serverNameOfNullForMain parameter. - * - * @param serverNameOrNullForMain - * use null to search on the server to which this request is sent; use a name as retrieved - * by {@link #getSearchServerNames()} which corresponds to a name of a - * {@link RemoteSailingServerReference}, to search a remote server. - */ - void search(String serverNameOrNullForMain, KeywordQuery query, - AsyncCallback> callback); - void setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived, AsyncCallback callback); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 3b3ba032989..486f00f4d4b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -414,6 +414,8 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String scoringSchemeWinnerGetsEightAndInterpolation(); String scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07(); String scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description(); + String scoringSchemeLowPointForLeagueOverallLeaderboard(); + String scoringSchemeLowPointForLeagueOverallLeaderboardDescription(); String scoringSystem(); String createFlexibleLeaderboard(); String createRegattaLeaderboard(); @@ -1365,7 +1367,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String durationPlain(); String finishedRaces(); String selectCompetitor(); - String allBoatClasses(); + String all(); String points(); String numberOfRacesShort(); String courseGeometry(); @@ -1416,6 +1418,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String groupAverageDescending(); String groupMedianAscending(); String groupMedianDescending(); + String resultsFoundForSearch(@PluralCount(DefaultRule_1_0n.class) int amount, String searchText); String runPredefinedQuery(); String selectPredefinedQuery(); String predefinedQueryRunner(); @@ -1426,4 +1429,20 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c String useClassGetNameTooltip(); String useStringLiterals(); String useStringLiteralsTooltip(); + String errorLoadingDataWithTryAgain(); + String addGalleryPhoto(); + String addStageImage(); + String addTeaserImage(); + String addEventLogo(); + String noImagesDefinedYet(); + String imageSizeError(String imageType, int minWidth, int maxWidth, int minHeight, int maxHeight); + String couldNotRetrieveImageSizeYet(); + @Override + String pleaseOnlyUploadContentYouHaveAllUsageRightsFor(); + String selectALeaderboardGroup(); + @Override + String pleaseSelect(); + String requiresValidRegatta(); + String couldNotObtainRace(String regattaLikeName, String raceColumnName, String fleetName, String technicalErrorMessage); + String errorTryingToCreateEmbeddedMap(String message); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index b4d2b53f0ce..38ed0e4890e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -426,6 +426,8 @@ scoringSchemeWinnerGetsEight=High Point System, Winner Gets 8 Points scoringSchemeWinnerGetsEightAndInterpolation=High Point System, Winner 8 Points, Interpolated scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point with Eliminations and Rounds, Winner Gets 0.7 Points scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=A variant of the low-point scoring scheme, using eliminations consisting of rounds.\nEach round shall be modeled as a series in the regatta, and the fleet ordering counts backwards\nstarting with the highest number for the first round.\nIf a final and losers final take place, use 1 and 2 as their ordering. Start with 3 for the semi-final round. +scoringSchemeLowPointForLeagueOverallLeaderboard=Low Point, ties broken by act point sum, then last act +scoringSchemeLowPointForLeagueOverallLeaderboardDescription=Instead of the usual count-back system used for low point schemes to break ties, competitors with equal point sums are compared by comparing the sum of the points they scored across all acts. If this still leaves a tie, the tie is broken by the last act. scoringSystem=Scoring system createFlexibleLeaderboard=Create flexible leaderboard createRegattaLeaderboard=Create regatta leaderboard @@ -463,7 +465,6 @@ actionAddEvent=Add Event publicationUrl=Publication URL suppress=Suppress isPublic=Is public -suppress=Suppress unsuppress=Unsuppress suppressedCompetitors=Suppressed Competitors mediaPanel=Audio & Video @@ -532,7 +533,6 @@ knotsValue={0,number,#0.0} kts knotsRange={0,number,#0.0} - {1,number,#0.0} kts scoringSchemeHighPointFirstGetsOne=High Point, winner gets 1 point scoringSchemeHighPointFirstGetsTen=High Point, winner gets 10 points -knotsUnit=kts generatePolarSheet=Generate Polar Sheet polars=Polar Diagrams polarSheetChart=Polar Sheet @@ -586,7 +586,6 @@ courseAreas=Course areas courseArea=Course area pleaseEnterNonEmptyCourseArea=Please enter a course area. pleaseSelectACourseArea=Please select a course area. -radiusInMeters=Radius (m) lastUpperFlag=Upper flag lastLowerFlag=Lower flag cannotAddRacesToRegattaLeaderboardButOnlyToRegatta=This is a regatta leaderboard. You can only add races to this leaderboard directly in the regatta definition. @@ -766,7 +765,6 @@ startAt=Start at finishAt=Finish at protestEndsAt=Protest ends at unknown=Unknown -earlyStarters=Early starters raceLog=Race log regattaLog=Regatta log refreshRaceLog=Refresh race log @@ -1335,7 +1333,7 @@ winner=Winner durationPlain=Duration finishedRaces=Finished Races selectCompetitor=Please select one competitor -allBoatClasses=All Boat Classes +all=All points=Points numberOfRacesShort=# Races courseGeometry=Course Geometry @@ -1388,6 +1386,8 @@ groupAverageAscending=Group Average (Ascending) groupAverageDescending=Group Average (Descending) groupMedianAscending=Group Median (Ascending) groupMedianDescending=Group Median (Descending) +resultsFoundForSearch= {0,number} results found for ''{1}'' +resultsFoundForSearch[one]= {0,number} result found for ''{1}'' runPredefinedQuery=Run Predefined Query selectPredefinedQuery=Select Predefined Query predefinedQueryRunner=Predefined Query Runner @@ -1397,4 +1397,18 @@ code=Code useClassGetName=Use Class.getName() for type names useClassGetNameTooltip=More robust against changes in the code base, but the code snippet can only be used in the scope where the classes are available. useStringLiterals=Use string literals for type names -useStringLiteralsTooltip=The code snippet can be used anywhere, but it will break if the code base changes. \ No newline at end of file +useStringLiteralsTooltip=The code snippet can be used anywhere, but it will break if the code base changes. +errorLoadingDataWithTryAgain=Error loading data. Trying again in a few moments. +addGalleryPhoto=Add gallery photo +addStageImage=Add stage image +addTeaserImage=Add teaser image +addEventLogo=Add event logo +noImagesDefinedYet=No images defined yet +imageSizeError=The size of the {0} image does not fit. The width should be between {1} and {2} px and the height between {3} and {4} px. +couldNotRetrieveImageSizeYet=The width and height of the image could not be retrieved yet. +pleaseOnlyUploadContentYouHaveAllUsageRightsFor=Please only upload content you have all usage rights for. Remember that content may be cropped. +selectALeaderboardGroup=Select a leaderboard group... +pleaseSelect=Please select +requiresValidRegatta=This page requires a valid regatta, race column and fleet name to identify the race to show. +couldNotObtainRace=Could not obtain a race with name {1} for fleet {2} for a regatta with name {0}: {3} +errorTryingToCreateEmbeddedMap=Error trying to create the embedded map: {0} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index ab6bd713db8..662f15bedb5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -427,6 +427,8 @@ scoringSchemeWinnerGetsEight=High Point System, Gewinner erhält 8 Punkte scoringSchemeWinnerGetsEightAndInterpolation=High Point System, Gewinner erhält 8 Punkte, interpoliert scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point System mit K.O.-Runden, Gewinner erhält 0,7 Punkte scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=Eine Variante des Low Point Systems mit mehreren K.O.-Wertungen.\nJede Runde einer Wertung wird als "Serie" in der Regatta modelliert, und die Gruppen-Ordnung wird rückwärts zählend verwendet, mit der größten Zahl für die erste Runde.\nWenn die Final-Runde in großes und kleines Finale unterteilt ist, soll das große Finale mit Ordnungszahl 1 und das kleine mit Ordnungszahl 2 modelliert werden. Das Halbfinale verwendet dann 3, usw. +scoringSchemeLowPointForLeagueOverallLeaderboard=Low Point System, bei Punktegleichstand zählt Punktesumme der Spieltage, dann letzter Spieltag +scoringSchemeLowPointForLeagueOverallLeaderboardDescription=Bei Punktegleichstand wird die Punktesumme über alle Spieltage verglichen; weniger ist besser. Bei Gleichstand entscheidet das Abschneiden am letzten Spieltag. scoringSystem=Bepunktungssystem createFlexibleLeaderboard=Flexible Rangliste anlegen createRegattaLeaderboard=Rangliste für Regatta anlegen @@ -464,7 +466,6 @@ actionAddEvent=Veranstaltung hinzufügen publicationUrl=URL für die Veröffentlichung suppress=Entfernen isPublic=Öffentlich zugänglich -suppress=Entfernen unsuppress=Wieder hinzufügen suppressedCompetitors=Unterdrückte Wettkampfteilnehmer mediaPanel=Audio & Video @@ -762,7 +763,6 @@ startAt=Start finishAt=Rennende protestEndsAt=Protestzeit endet unknown=Unbekannt -earlyStarters=Frühstarter raceLog=RaceLog regattaLog=RegattaLog refreshRaceLog=RaceLog neu laden @@ -1324,7 +1324,7 @@ winner=Sieger durationPlain=Dauer finishedRaces=Beendete Wettfahrten selectCompetitor=Bitte einen Teilnehmer auswählen -allBoatClasses=Alle Bootsklassen +all=Alle points=Punkte numberOfRacesShort=# Rennen courseGeometry=Kursgeometrie @@ -1377,6 +1377,8 @@ groupAverageAscending=Gruppe Durchschnitt (Aufsteigend) groupAverageDescending=Gruppe Durchschnitt (Absteigend) groupMedianAscending=Gruppe Median (Aufsteigend) groupMedianDescending=Gruppe Median (Absteigend) +resultsFoundForSearch= {0,number} Ergebnisse gefunden für ''{1}'' +resultsFoundForSearch[one]= {0,number} Ergebnis gefunden für ''{1}'' runPredefinedQuery=Vordefinierte Abfrage ausführen selectPredefinedQuery=Vordefinierte Abfrage auswählen predefinedQueryRunner=Vordefinierte Abfrageverarbeiter @@ -1386,4 +1388,18 @@ code=Code useClassGetName=Verwende Class.getName() für Typnamen useClassGetNameTooltip=Robuster gegnüber Änderungen im Code, aber der Code Snippet kann nur in dem Scope verwendet werden in dem die Klassen verfügbar sind. useStringLiterals=Verwende String-Literale für Typnamen -useStringLiteralsTooltip=Der Code Snippet kann überall verwendet werden, wird aber nicht mehr funktionieren, wenn sich der Code ändert. \ No newline at end of file +useStringLiteralsTooltip=Der Code Snippet kann überall verwendet werden, wird aber nicht mehr funktionieren, wenn sich der Code ändert. +errorLoadingDataWithTryAgain=Ladefehler - ein neuer Versuch erfolgt in wenigen Augenblicken. +addGalleryPhoto=Galeriebild hinzufügen +addStageImage=Startseiten-Bild hinzufügen +addTeaserImage=Lock-Bild hinzufügen +addEventLogo=Veranstaltungs-Logo hinzufügen +noImagesDefinedYet=Noch keine Bilder vorhanden +imageSizeError=Die Größe des {0}-Bildes ist unpassend. Die Breite sollte zwischen {1} und {2} px und die Höhe zwischen {3} und {4} px sein. +couldNotRetrieveImageSizeYet=Bildgröße konnte noch nicht ermittelt werden. +pleaseOnlyUploadContentYouHaveAllUsageRightsFor=Bitte nur Inhalte hochladen, für die alle Verwendungsrechte vorliegen. Bitte beachten: Bilder können verändert wiedergegeben werden. +selectALeaderboardGroup=Bitte eine Ranglisten-Gruppe auswählen... +pleaseSelect=Bitte auswählen +requiresValidRegatta=Diese Seite benötigt eine gültige Regatta, Rennspalte und einen gültigen Gruppennamen um die anzuzeigende Wettfahrt zu identifizieren. +couldNotObtainRace=Wettfahrt namens {1} für Gruppe {2} in einer Regatta names {0} konnte nicht gefunden werden: {3} +errorTryingToCreateEmbeddedMap=Fehler beim Erstellen der eingebetteten Karte: {0} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index 287fb9be608..5998760ba2a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -411,6 +411,8 @@ scoringSchemeWinnerGetsEight=Высокобальная система подс scoringSchemeWinnerGetsEightAndInterpolation=Высокобальная система подсчета, победитель получает 8 очков, Interpolated scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point with Eliminations and Rounds, Winner Gets 0.7 Points scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=A variant of the low-point scoring scheme, using eliminations consisting of rounds.\nEach round shall be modeled as a series in the regatta, and the fleet ordering counts backwards\nstarting with the highest number for the first round.\nIf a final and losers final take place, use 1 and 2 as their ordering. Start with 3 for the semi-final round. +scoringSchemeLowPointForLeagueOverallLeaderboard=Low Point, ties broken by act point sum, then last act +scoringSchemeLowPointForLeagueOverallLeaderboardDescription=Instead of the usual count-back system used for low point schemes to break ties, competitors with equal point sums are compared by comparing the sum of the points they scored across all acts. If this still leaves a tie, the tie is broken by the last act. scoringSystem=Система подсчета очков createFlexibleLeaderboard=Создание адаптивной таблицы лидеров createRegattaLeaderboard=Создание таблицы лидеров регаты @@ -447,7 +449,6 @@ actionAddEvent=Добавить событие publicationUrl=URL-адрес для публикации suppress=скрыть isPublic=является открытым -suppress=скрыть unsuppress=Отобразить suppressedCompetitors=Скрытые участники mediaPanel=Аудио и Видео @@ -566,7 +567,6 @@ courseAreas=Зоны курса courseArea=Зона курса pleaseEnterNonEmptyCourseArea=Пожалуйста, выведите зону курса. pleaseSelectACourseArea=Пожалуйста, выберите зону курса. -radiusInMeters=Радиус (м) lastUpperFlag=Верхний флажок lastLowerFlag=Нижний флажок cannotAddRacesToRegattaLeaderboardButOnlyToRegatta=Это таблица лидеров регаты. Вы можете добавлять гонки в эту таблицу лидеров только непосредственно в определении регаты. @@ -747,7 +747,6 @@ startAt=Старт в finishAt=Финиш в protestEndsAt=Срок подачи протеста завершается в unknown=Неизвестно -earlyStarters=Совершивших фальшстарт raceLog=Запись о гонке regattaLog=Regatta log refreshRaceLog=Обновить запись о гонке @@ -1267,7 +1266,7 @@ winner=победитель durationPlain=Продолжительность finishedRaces=Finished Races selectCompetitor=Please select one competitor -allBoatClasses=All Boat Classes +all=All points=Points numberOfRacesShort=# Races courseGeometry=Course Geometry @@ -1317,6 +1316,8 @@ groupAverageAscending=Group Average (Ascending) groupAverageDescending=Group Average (Descending) groupMedianAscending=Group Median (Ascending) groupMedianDescending=Group Median (Descending) +resultsFoundForSearch= {0,number} results found for ''{1}'' +resultsFoundForSearch[one]= {0,number} result found for ''{1}'' runPredefinedQuery=Run Predefined Query selectPredefinedQuery=Select Predefined Query predefinedQueryRunner=Predefined Query Runner @@ -1326,4 +1327,18 @@ code=Code useClassGetName=Use Class.getName() for type names useClassGetNameTooltip=More robust against changes in the code base, but the code snippet can only be used in the scope where the classes are available. useStringLiterals=Use string literals for type names -useStringLiteralsTooltip=The code snippet can be used anywhere, but it will break if the code base changes. \ No newline at end of file +useStringLiteralsTooltip=The code snippet can be used anywhere, but it will break if the code base changes. +errorLoadingDataWithTryAgain=Error loading data. Trying again in a few moments. +addGalleryPhoto=Add gallery photo +addStageImage=Add stage image +addTeaserImage=Add teaser image +addEventLogo=Add event logo +noImagesDefinedYet=No images defined yet +imageSizeError=The size of the {0} image does not fit. The width should be between {1} and {2} px and the height between {3} and {4} px. +couldNotRetrieveImageSizeYet=The width and height of the image could not be retrieved yet. +pleaseOnlyUploadContentYouHaveAllUsageRightsFor=Please only upload content you have all usage rights for. Remember that content may be cropped. +selectALeaderboardGroup=Select a leaderboard group... +pleaseSelect=Please select +requiresValidRegatta=This page requires a valid regatta, race column and fleet name to identify the race to show. +couldNotObtainRace=Could not obtain a race with name {1} for fleet {2} for a regatta with name {0}: {3} +errorTryingToCreateEmbeddedMap=Error trying to create the embedded map: {0} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 7f30d4ebe97..cc9f3f704cc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -527,6 +527,8 @@ hideMap=隐藏地图 scoringSchemeLowPointWinnerGetsZero=Low Point System, Winner Gets Zero scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07=Low Point with Eliminations and Rounds, Winner Gets 0.7 Points scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description=A variant of the low-point scoring scheme, using eliminations consisting of rounds.\nEach round shall be modeled as a series in the regatta, and the fleet ordering counts backwards\nstarting with the highest number for the first round.\nIf a final and losers final take place, use 1 and 2 as their ordering. Start with 3 for the semi-final round. +scoringSchemeLowPointForLeagueOverallLeaderboard=Low Point, ties broken by act point sum, then last act +scoringSchemeLowPointForLeagueOverallLeaderboardDescription=Instead of the usual count-back system used for low point schemes to break ties, competitors with equal point sums are compared by comparing the sum of the points they scored across all acts. If this still leaves a tie, the tie is broken by the last act. averageAbsoluteCrossTrackErrorInMeters=u2205 XTE showOnlyRacesOfSameDay=Show only races of same day waypoints=航路点 @@ -1313,7 +1315,7 @@ noNews=There are no news available. pointsValue={0,number,#0.00} openLeaderboard=Open Leaderboard selectCompetitor=Please select one competitor -allBoatClasses=All Boat Classes +all=All points=Points numberOfRacesShort=# Races courseGeometry=Course Geometry @@ -1339,3 +1341,19 @@ actionWatch=Watch actionAnalyze=Analyze flightsCount={0,number} flights flightsCount[one]={0,number} flight +resultsFoundForSearch= {0,number} 搜寻结果 ''{1}'' +resultsFoundForSearch[one]= {0,number} 搜寻结果 ''{1}'' +errorLoadingDataWithTryAgain=Error loading data. Trying again in a few moments. +addGalleryPhoto=Add gallery photo +addStageImage=Add stage image +addTeaserImage=Add teaser image +addEventLogo=Add event logo +noImagesDefinedYet=No images defined yet +imageSizeError=The size of the {0} image does not fit. The width should be between {1} and {2} px and the height between {3} and {4} px. +couldNotRetrieveImageSizeYet=The width and height of the image could not be retrieved yet. +pleaseOnlyUploadContentYouHaveAllUsageRightsFor=Please only upload content you have all usage rights for. Remember that content may be cropped. +selectALeaderboardGroup=Select a leaderboard group... +pleaseSelect=Please select +requiresValidRegatta=This page requires a valid regatta, race column and fleet name to identify the race to show. +couldNotObtainRace=Could not obtain a race with name {1} for fleet {2} for a regatta with name {0}: {3} +errorTryingToCreateEmbeddedMap=Error trying to create the embedded map: {0} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/GalleryImageHolder.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/GalleryImageHolder.java index 86e8d235299..7df21e93774 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/GalleryImageHolder.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/GalleryImageHolder.java @@ -10,7 +10,7 @@ import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.gwt.ui.shared.media.SailingImageDTO; +import com.sap.sse.gwt.client.media.ImageDTO; public class GalleryImageHolder extends Widget implements HasClickHandlers { @@ -22,7 +22,7 @@ public class GalleryImageHolder extends Widget implements HasClickHandlers { @UiField DivElement imageHolderUi; - public GalleryImageHolder(SailingImageDTO video) { + public GalleryImageHolder(ImageDTO video) { setElement(uiBinder.createAndBindUi(this)); imageHolderUi.getStyle().setBackgroundImage("url(\"" + video.getSourceRef() + "\")"); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/VideoThumbnail.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/VideoThumbnail.java index 0b4ac3b0e83..ccba7cb1121 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/VideoThumbnail.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/VideoThumbnail.java @@ -12,8 +12,8 @@ import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.ui.common.client.YoutubeApi; -import com.sap.sailing.gwt.ui.shared.media.SailingVideoDTO; import com.sap.sse.common.media.MediaSubType; +import com.sap.sse.gwt.client.media.VideoDTO; public class VideoThumbnail extends Widget implements HasClickHandlers { @@ -28,7 +28,7 @@ public class VideoThumbnail extends Widget implements HasClickHandlers { @UiField ImageElement thumbnailUi; - public VideoThumbnail(SailingVideoDTO video) { + public VideoThumbnail(VideoDTO video) { setElement(uiBinder.createAndBindUi(this)); getElement().addClassName("videoThumbnail"); captionUi.setInnerText(video.getTitle()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/BusyView.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/BusyView.java new file mode 100644 index 00000000000..94d18d37239 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/BusyView.java @@ -0,0 +1,6 @@ +package com.sap.sailing.gwt.ui.client.refresh; + +import com.google.gwt.user.client.ui.IsWidget; + +public interface BusyView extends IsWidget { +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/ErrorAndBusyClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/ErrorAndBusyClientFactory.java new file mode 100644 index 00000000000..a5e8ef45d50 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/refresh/ErrorAndBusyClientFactory.java @@ -0,0 +1,9 @@ +package com.sap.sailing.gwt.ui.client.refresh; + +import com.sap.sse.gwt.client.mvp.ErrorView; + +public interface ErrorAndBusyClientFactory { + BusyView createBusyView(); + + ErrorView createErrorView(String errorMessage, Throwable errorReason); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java index 28ed045dec9..58bfe7fe2aa 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorRaceChart.java @@ -391,7 +391,7 @@ public abstract class AbstractCompetitorRaceChart() { @Override public void onFailure(Throwable caught) { @@ -184,7 +184,8 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component() { @Override @@ -205,7 +206,8 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component() { @Override @@ -225,7 +227,8 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component() { @Override @@ -311,7 +314,8 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component>() { @Override public void onFailure(Throwable caught) { @@ -385,15 +389,8 @@ public class EditMarkPassingsPanel extends AbsolutePanel implements Component filteredCompetitors) { } + private String getLeaderboardName() { + return leaderboard.name; + } + + private RaceColumnDTO getColumn() { + RaceColumnDTO result = null; + if (leaderboard != null) { + for (RaceColumnDTO columnDTO : leaderboard.getRaceList()) { + if (columnDTO.containsRace(raceIdentifier)) { + result = columnDTO; + break; + } + } + } + return result; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java old mode 100755 new mode 100644 index c6f543169b1..b4657f0d566 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/racemap/RaceMap.java @@ -284,8 +284,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe private Map> lastDouglasPeuckerResult; - private CompetitorSelectionProvider competitorSelection; - + private final CompetitorSelectionProvider competitorSelection; + private List selectedRaces; /** @@ -398,8 +398,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe private final NumberFormat numberFormatOneDecimal = NumberFormat.getFormat("0.0"); public RaceMap(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, - ErrorReporter errorReporter, Timer timer, CompetitorSelectionProvider competitorSelection, - StringMessages stringMessages, boolean showMapControls, boolean showViewStreamlets, boolean showViewStreamletColors, boolean showViewSimulation, + ErrorReporter errorReporter, Timer timer, CompetitorSelectionProvider competitorSelection, StringMessages stringMessages, + boolean showMapControls, boolean showViewStreamlets, boolean showViewStreamletColors, boolean showViewSimulation, RegattaAndRaceIdentifier raceIdentifier, CombinedWindPanelStyle combinedWindPanelStyle, boolean showHeaderPanel) { this.setSize("100%", "100%"); this.showMapControls = showMapControls; @@ -1777,11 +1777,11 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe private CompetitorInfoOverlay createCompetitorInfoOverlay(int zIndex, final CompetitorDTO competitorDTO) { String infoText = competitorDTO.getSailID() == null || competitorDTO.getSailID().isEmpty() ? competitorDTO.getName() : competitorDTO.getSailID(); - return new CompetitorInfoOverlay(map, zIndex, competitorSelection.getColor(competitorDTO), infoText, coordinateSystem); + return new CompetitorInfoOverlay(map, zIndex, competitorSelection.getColor(competitorDTO, raceIdentifier), infoText, coordinateSystem); } private BoatOverlay createBoatOverlay(int zIndex, final CompetitorDTO competitorDTO, boolean highlighted) { - final BoatOverlay boatCanvas = new BoatOverlay(map, zIndex, competitorDTO, competitorSelection.getColor(competitorDTO), coordinateSystem); + final BoatOverlay boatCanvas = new BoatOverlay(map, zIndex, competitorDTO, competitorSelection.getColor(competitorDTO, raceIdentifier), coordinateSystem); boatCanvas.setSelected(highlighted); boatCanvas.addClickHandler(new ClickMapHandler() { @Override @@ -2476,7 +2476,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe options.setStrokeOpacity(1.0); boolean noCompetitorSelected = Util.isEmpty(competitorSelection.getSelectedCompetitors()); if (isHighlighted || noCompetitorSelected) { - options.setStrokeColor(competitorSelection.getColor(competitor).getAsHtml()); + options.setStrokeColor(competitorSelection.getColor(competitor, raceIdentifier).getAsHtml()); } else { options.setStrokeColor(CssColor.make(200, 200, 200).toString()); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/DateAndTimeFormatterUtil.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/DateAndTimeFormatterUtil.java index 832a8211299..3938fc8090b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/DateAndTimeFormatterUtil.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/common/client/DateAndTimeFormatterUtil.java @@ -15,6 +15,8 @@ public class DateAndTimeFormatterUtil { DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT)); public static DateTimeFormatRenderer defaultTimeFormatter = new DateTimeFormatRenderer( DateTimeFormat.getFormat(PredefinedFormat.TIME_LONG)); + public static DateTimeFormatRenderer shortTimeFormatter = new DateTimeFormatRenderer( + DateTimeFormat.getFormat(PredefinedFormat.TIME_SHORT)); public static DateTimeFormatRenderer weekdayMonthAbbrDayDateFormatter = new DateTimeFormatRenderer( DateTimeFormat.getFormat("EEE, " + LocaleInfo.getCurrentLocale().getDateTimeFormatInfo().formatMonthAbbrevDay())); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java index 0f60284cb40..ecc0a5a25d2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/presentation/ResultsChart.java @@ -77,8 +77,8 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders ascendingByGroupAverageComparator = new Comparator() { @Override public int compare(GroupKey key1, GroupKey key2) { - GroupKey mainKey1 = key1.getMainKey(); - GroupKey mainKey2 = key2.getMainKey(); + GroupKey mainKey1 = GroupKey.Util.getMainKey(key1); + GroupKey mainKey2 = GroupKey.Util.getMainKey(key2); return Double.compare(averagePerMainKey.get(mainKey1), averagePerMainKey.get(mainKey2)); } public String toString() { @@ -97,8 +97,8 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders ascendingByGroupMedianComparator = new Comparator() { @Override public int compare(GroupKey key1, GroupKey key2) { - GroupKey mainKey1 = key1.getMainKey(); - GroupKey mainKey2 = key2.getMainKey(); + GroupKey mainKey1 = GroupKey.Util.getMainKey(key1); + GroupKey mainKey2 = GroupKey.Util.getMainKey(key2); return Double.compare(medianPerMainKey.get(mainKey1), medianPerMainKey.get(mainKey2)); } public String toString() { @@ -244,7 +244,7 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders> valuesPerMainKey = new HashMap<>(); for (Entry resultEntry : currentResultValues.entrySet()) { - GroupKey mainKey = resultEntry.getKey().getMainKey(); + GroupKey mainKey = GroupKey.Util.getMainKey(resultEntry.getKey()); Number value = resultEntry.getValue(); if (!isCurrentResultSimple()) { @@ -313,7 +313,7 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders getSortedMainKeys() { Collection mainKeySet = new HashSet<>(); for (GroupKey groupKey : getCurrentResult().getResults().keySet()) { - mainKeySet.add(groupKey.getMainKey()); + mainKeySet.add(GroupKey.Util.getMainKey(groupKey)); } List sortedKeys = new ArrayList<>(mainKeySet); Collections.sort(sortedKeys, getKeyComparator()); @@ -340,13 +340,8 @@ public class ResultsChart extends AbstractResultsPresenterWithDataProviders subKeys = groupKey.getSubKeys(); - GroupKey subMainKey = subKeys.get(0); - List subSubKeys = new ArrayList<>(); - for (int i = 1; i < subKeys.size(); i++) { - subSubKeys.add(subKeys.get(i)); - } - return subSubKeys.isEmpty() ? subMainKey : new CompoundGroupKey(subMainKey, subSubKeys); + List subKeys = GroupKey.Util.getSubKeys(groupKey); + return subKeys.size() == 1 ? subKeys.get(0) : new CompoundGroupKey(subKeys); } else { return simpleResultSeriesKey; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index 3f4e6aa9e19..11c7854898e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -277,7 +277,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS * {@link RaceColumnDTO#getRaceIdentifier(String) race identifier} matches the value of this attribute will be * added. */ - private final RaceIdentifier preSelectedRace; + private final RegattaAndRaceIdentifier preSelectedRace; private final VerticalPanel contentPanel; @@ -619,7 +619,8 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS @Override public void render(Context context, LeaderboardRowDTO object, SafeHtmlBuilder sb) { - String competitorColor = LeaderboardPanel.this.competitorSelectionProvider.getColor(object.competitor).getAsHtml(); + String competitorColor = LeaderboardPanel.this.competitorSelectionProvider.getColor(object.competitor, + LeaderboardPanel.this.preSelectedRace).getAsHtml(); String competitorColorBarStyle; if (LeaderboardPanel.this.isEmbedded && preSelectedRace != null) { competitorColorBarStyle = "style=\"border-bottom: 2px solid " + competitorColor + ";\""; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java index b167f765189..e3b68c474d5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/ScoringSchemeTypeFormatter.java @@ -32,6 +32,8 @@ public class ScoringSchemeTypeFormatter { return stringMessages.scoringSchemeHighPointFirstGetsTenOrEight(); case LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07: return stringMessages.scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07(); + case LOW_POINT_LEAGUE_OVERALL: + return stringMessages.scoringSchemeLowPointForLeagueOverallLeaderboard(); } return null; } @@ -44,6 +46,8 @@ public class ScoringSchemeTypeFormatter { return stringMessages.scoringSchemeHighPointEssOverallDescription(); case LOW_POINT_WITH_ELIMINATIONS_AND_ROUNDS_WINNER_GETS_07: return stringMessages.scoringSchemeLowPointWithEliminationsAndRoundsWinnerGets07Description(); + case LOW_POINT_LEAGUE_OVERALL: + return stringMessages.scoringSchemeLowPointForLeagueOverallLeaderboardDescription(); default: return format(scoringSchemeType, stringMessages); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java index ca73b1a310f..926e3ca3efe 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java @@ -5,8 +5,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; -import java.util.UUID; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; @@ -21,8 +21,11 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootLayoutPanel; import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.CompetitorColorProvider; +import com.sap.sailing.gwt.ui.client.CompetitorColorProviderImpl; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel; @@ -38,7 +41,6 @@ import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapResources; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes; -import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sse.common.Duration; import com.sap.sse.common.Util; import com.sap.sse.common.filter.Filter; @@ -54,14 +56,17 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint private static final String PARAM_REGATTA_LIKE_NAME = "regattaLikeName"; private static final String PARAM_RACE_COLUMN_NAME = "raceColumnName"; private static final String PARAM_FLEET_NAME = "fleetName"; - private static final String PARAM_EVENT_ID = "eventId"; + private static final String PARAM_SHOW_COMPETITORS = "showCompetitors"; + private static final String PARAM_PLAY = "play"; + private static final String PARAM_SHOW_COURSE_GEOMETRY = "showCourseGeometry"; + private static final String PARAM_MAP_ORIENTATION_WIND_UP = "windUp"; private String regattaLikeName; private String raceColumnName; private String fleetName; - private UUID eventId; private static final RaceMapResources raceMapResources = GWT.create(RaceMapResources.class); + private static final int DEFAULT_WIND_CHART_HEIGHT = 200; @Override @@ -71,13 +76,9 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint regattaLikeName = Window.Location.getParameter(PARAM_REGATTA_LIKE_NAME); raceColumnName = Window.Location.getParameter(PARAM_RACE_COLUMN_NAME); fleetName = Window.Location.getParameter(PARAM_FLEET_NAME); - String eventIdParamValue = Window.Location.getParameter(PARAM_EVENT_ID); - if (eventIdParamValue != null && !eventIdParamValue.isEmpty()) { - eventId = UUID.fromString(eventIdParamValue); - } if (regattaLikeName == null || regattaLikeName.isEmpty() || raceColumnName == null || raceColumnName.isEmpty() || fleetName == null || fleetName.isEmpty()) { - createErrorPage("This page requires a valid regatta, race column and fleet name to identify the race to show."); + createErrorPage(getStringMessages().requiresValidRegatta()); return; } @@ -87,21 +88,36 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint final boolean showViewStreamletColors = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLET_COLORS, false /* default*/); final boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, true /* default*/); final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, true /* default*/); - if (eventId != null) { - sailingService.getEventById(eventId, /* withStatisticalData */ false, new AsyncCallback() { - @Override - public void onSuccess(EventDTO eventDTO) { - checkUrlParameters(eventDTO, showWindChart, showMapControls, showViewStreamlets, showViewStreamletColors, showViewSimulation); + final boolean showCompetitors = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_COMPETITORS, false /* default */); + final boolean play = GwtHttpRequestUtils.getBooleanParameter(PARAM_PLAY, false /* default */); + final boolean showCourseGeometry = GwtHttpRequestUtils.getBooleanParameter(PARAM_SHOW_COURSE_GEOMETRY, true /* default */); + final boolean windUp = GwtHttpRequestUtils.getBooleanParameter(PARAM_MAP_ORIENTATION_WIND_UP, true /* default */); + sailingService.getRaceIdentifier(regattaLikeName, raceColumnName, fleetName, new AsyncCallback() { + @Override + public void onSuccess(final RegattaAndRaceIdentifier selectedRaceIdentifier) { + if (selectedRaceIdentifier == null) { + createErrorPage(getStringMessages().couldNotObtainRace(regattaLikeName, raceColumnName, fleetName, /* technicalErrorMessage */ "")); + } else { + sailingService.getCompetitorBoats(selectedRaceIdentifier, new AsyncCallback>() { + @Override + public void onSuccess(Map result) { + createEmbeddedMap(selectedRaceIdentifier, result, showWindChart, showMapControls, showViewStreamlets, + showViewStreamletColors, showViewSimulation, showCompetitors, play, showCourseGeometry, windUp); + } + + @Override + public void onFailure(Throwable caught) { + reportError(getStringMessages().errorTryingToCreateEmbeddedMap(caught.getMessage())); + } + }); } - - @Override - public void onFailure(Throwable t) { - reportError("Error trying to create the raceboard: " + t.getMessage()); - } - }); - } else { - checkUrlParameters(/* event */ null, showWindChart, showMapControls, showViewStreamlets, showViewStreamletColors, showViewSimulation); - } + } + + @Override + public void onFailure(Throwable caught) { + createErrorPage(getStringMessages().couldNotObtainRace(regattaLikeName, raceColumnName, fleetName, caught.getMessage())); + } + }); } private void createErrorPage(String message) { @@ -113,89 +129,81 @@ public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint vp.add(new Label(message)); } - private void checkUrlParameters(final EventDTO event, final boolean showWindChart, - final boolean showMapControls, final boolean showViewStreamlets, final boolean showViewStreamletColors, final boolean showViewSimulation) { - if (eventId != null && event == null) { - createErrorPage(getStringMessages().noSuchEvent()); + private void createEmbeddedMap(final RegattaAndRaceIdentifier selectedRaceIdentifier, Map competitorBoats, + final boolean showWindChart, final boolean showMapControls, + final boolean showViewStreamlets, final boolean showViewStreamletColors, final boolean showViewSimulation, + final boolean showCompetitors, final boolean play, final boolean showCourseGeometry, final boolean windUp) { + final StringBuilder title = new StringBuilder(regattaLikeName); + title.append('/'); + title.append(raceColumnName); + if (!fleetName.equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) { + title.append('/'); + title.append(fleetName); } - sailingService.getRaceIdentifier(regattaLikeName, raceColumnName, fleetName, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - createErrorPage("Could not obtain a race with name " + raceColumnName + " for fleet "+fleetName+" for a regatta with name " + regattaLikeName+ - ": "+caught.getMessage()); + Window.setTitle(title.toString()); + final RaceSelectionModel raceSelectionModel = new RaceSelectionModel(); + final List raceList = Collections.singletonList(selectedRaceIdentifier); + raceSelectionModel.setSelection(raceList); + final long refreshInterval = Duration.ONE_SECOND.times(3).asMillis(); + final Timer timer = new Timer(play ? PlayModes.Live : PlayModes.Replay); + AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); + final TimeRangeWithZoomProvider timeRangeWithZoomProvider = new TimeRangeWithZoomModel(); + // Use a TimePanel to manage wind chart zoom, although the TimePanel itself is not being displayed; + // let the time panel always return to "live" mode. + final TimePanel timePanel = new TimePanel( + timer, timeRangeWithZoomProvider, getStringMessages(), /* canReplayWhileLive */ false) { + protected boolean isLiveModeToBeMadePossible() { + return true; } - + }; + final Button backToLivePlayButton = timePanel.getBackToLiveButton(); + final TimePanelSettings timePanelSettings = timePanel.getSettings(); + timePanelSettings.setRefreshInterval(refreshInterval); + timePanel.updateSettings(timePanelSettings); + raceMapResources.combinedWindPanelStyle().ensureInjected(); + final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(selectedRaceIdentifier, competitorBoats); + final CompetitorSelectionProvider competitorSelection; + if (showCompetitors) { + competitorSelection = new CompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider); + } else { + competitorSelection = createEmptyFilterCompetitorModel(colorProvider); // show no competitors + } + final RaceMap raceMap = new RaceMap(sailingService, asyncActionsExecutor, /* errorReporter */ EmbeddedMapAndWindChartEntryPoint.this, timer, + competitorSelection, getStringMessages(), showMapControls, showViewStreamlets, showViewStreamletColors, + showViewSimulation, selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle(), /* showHeaderPanel */ false) { @Override - public void onSuccess(final RegattaAndRaceIdentifier selectedRaceIdentifier) { - if (selectedRaceIdentifier == null) { - createErrorPage("Could not obtain a race with name " + raceColumnName + " for fleet "+fleetName+" for a regatta with name " + regattaLikeName); - } else { - final StringBuilder title = new StringBuilder(regattaLikeName); - title.append('/'); - title.append(raceColumnName); - if (!fleetName.equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) { - title.append('/'); - title.append(fleetName); - } - Window.setTitle(title.toString()); - final RaceSelectionModel raceSelectionModel = new RaceSelectionModel(); - final List raceList = Collections.singletonList(selectedRaceIdentifier); - raceSelectionModel.setSelection(raceList); - final long refreshInterval = Duration.ONE_SECOND.times(3).asMillis(); - final Timer timer = new Timer(PlayModes.Replay); - AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); - final TimeRangeWithZoomProvider timeRangeWithZoomProvider = new TimeRangeWithZoomModel(); - // Use a TimePanel to manage wind chart zoom, although the TimePanel itself is not being displayed; - // let the time panel always return to "live" mode if the user wants that - final TimePanel timePanel = new TimePanel( - timer, timeRangeWithZoomProvider, getStringMessages(), /* canReplayWhileLive */ false) { - protected boolean isLiveModeToBeMadePossible() { - return true; - } - }; - final Button backToLivePlayButton = timePanel.getBackToLiveButton(); - final TimePanelSettings timePanelSettings = timePanel.getSettings(); - timePanelSettings.setRefreshInterval(refreshInterval); - timePanel.updateSettings(timePanelSettings); - raceMapResources.combinedWindPanelStyle().ensureInjected(); - final CompetitorSelectionProvider competitorSelection = createEmptyFilterCompetitorModel(); // show no competitors - final RaceMap raceMap = new RaceMap(sailingService, asyncActionsExecutor, /* errorReporter */ EmbeddedMapAndWindChartEntryPoint.this, timer, - competitorSelection, getStringMessages(), showMapControls, showViewStreamlets, showViewStreamletColors, - showViewSimulation, selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle(), /* showHeaderPanel */ false) { - @Override - protected void showAdditionalControls(MapWidget map) { - backToLivePlayButton.removeFromParent(); - map.setControls(ControlPosition.RIGHT_BOTTOM, backToLivePlayButton); - } - }; - final RaceMapSettings mapSettings = new RaceMapSettings(raceMap.getSettings()); - mapSettings.setZoomSettings(new RaceMapZoomSettings(Arrays.asList(ZoomTypes.BUOYS), /* zoom to selection */ false)); - Set helpLineTypes = new HashSet<>(); - Util.addAll(mapSettings.getHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes); - helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY); - mapSettings.setHelpLinesSettings(new RaceMapHelpLinesSettings(helpLineTypes)); - mapSettings.setWindUp(true); - raceMap.updateSettings(mapSettings); - raceMap.onRaceSelectionChange(raceList); - final WindChart windChart; - if (showWindChart) { - windChart = new WindChart(sailingService, raceSelectionModel, timer, - timeRangeWithZoomProvider, new WindChartSettings(), getStringMessages(), - asyncActionsExecutor, /* errorReporter */ - EmbeddedMapAndWindChartEntryPoint.this, /* compactChart */ true); - windChart.onRaceSelectionChange(raceList); - } else { - windChart = null; - } - createRaceBoardInOneScreenMode(raceMap, windChart); - timer.setTime(timer.getTime().getTime()-1000l); - } + protected void showAdditionalControls(MapWidget map) { + backToLivePlayButton.removeFromParent(); + map.setControls(ControlPosition.RIGHT_BOTTOM, backToLivePlayButton); } - }); + }; + final RaceMapSettings mapSettings = new RaceMapSettings(raceMap.getSettings()); + mapSettings.setZoomSettings(new RaceMapZoomSettings(Arrays.asList(ZoomTypes.BUOYS), /* zoom to selection */ false)); + if (showCourseGeometry) { + Set helpLineTypes = new HashSet<>(); + Util.addAll(mapSettings.getHelpLinesSettings().getVisibleHelpLineTypes(), helpLineTypes); + helpLineTypes.add(HelpLineTypes.COURSEGEOMETRY); + mapSettings.setHelpLinesSettings(new RaceMapHelpLinesSettings(helpLineTypes)); + } + mapSettings.setWindUp(windUp); + raceMap.updateSettings(mapSettings); + raceMap.onRaceSelectionChange(raceList); + final WindChart windChart; + if (showWindChart) { + windChart = new WindChart(sailingService, raceSelectionModel, timer, + timeRangeWithZoomProvider, new WindChartSettings(), getStringMessages(), + asyncActionsExecutor, /* errorReporter */ + EmbeddedMapAndWindChartEntryPoint.this, /* compactChart */ true); + windChart.onRaceSelectionChange(raceList); + } else { + windChart = null; + } + createRaceBoardInOneScreenMode(raceMap, windChart); + timer.setTime(timer.getTime().getTime()-1000l); } - private CompetitorSelectionProvider createEmptyFilterCompetitorModel() { - final CompetitorSelectionModel result = new CompetitorSelectionModel(/* hasMultiSelection */ true); + private CompetitorSelectionProvider createEmptyFilterCompetitorModel(CompetitorColorProvider colorProvider) { + final CompetitorSelectionModel result = new CompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider); final FilterSet> filterSet = result.getOrCreateCompetitorsFilterSet("Empty"); filterSet.addFilter(new Filter() { @Override public boolean matches(CompetitorDTO object) { return false; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java index 4c6778185ef..219d66c3acb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java @@ -1,7 +1,6 @@ package com.sap.sailing.gwt.ui.raceboard; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -11,6 +10,7 @@ import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DockLayoutPanel; @@ -18,20 +18,15 @@ import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootLayoutPanel; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel; import com.sap.sailing.gwt.ui.client.MediaService; import com.sap.sailing.gwt.ui.client.MediaServiceAsync; -import com.sap.sailing.gwt.ui.client.ParallelExecutionCallback; -import com.sap.sailing.gwt.ui.client.ParallelExecutionHolder; import com.sap.sailing.gwt.ui.client.RaceSelectionModel; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; -import com.sap.sailing.gwt.ui.shared.EventDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; -import com.sap.sailing.gwt.ui.shared.RegattaDTO; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; +import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsDTO; +import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; import com.sap.sse.gwt.client.player.Timer; @@ -39,7 +34,7 @@ import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { - private RaceDTO selectedRace; + private RaceWithCompetitorsDTO selectedRace; private static final String PARAM_REGATTA_NAME = "regattaName"; private static final String PARAM_RACE_NAME = "raceName"; @@ -93,48 +88,23 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, true /* default*/); String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/); final boolean canReplayWhileLiveIsPossible = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, false); - final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, false); + final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, true); final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default*/); final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, true /* default*/); raceboardViewConfig = new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard, showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, canReplayWhileLiveIsPossible, autoSelectMedia, defaultMedia); - final ParallelExecutionCallback> getLeaderboardNamesCallback = new ParallelExecutionCallback>(); - final ParallelExecutionCallback> getRegattasCallback = new ParallelExecutionCallback>(); - final ParallelExecutionCallback getLeaderboardGroupByNameCallback = new ParallelExecutionCallback(); - final ParallelExecutionCallback getEventByIdCallback = new ParallelExecutionCallback(); - List> callbacks = new ArrayList<>(); - callbacks.add(getLeaderboardNamesCallback); - callbacks.add(getRegattasCallback); - if (leaderboardGroupName != null) { - callbacks.add(getLeaderboardGroupByNameCallback); - } - if (eventId != null) { - callbacks.add(getEventByIdCallback); - } - ParallelExecutionCallback[] callbackArray = callbacks.toArray(new ParallelExecutionCallback[0]); - new ParallelExecutionHolder(callbackArray) { + sailingService.getRaceboardData(regattaName, raceName, leaderboardName, leaderboardGroupName, eventId, new AsyncCallback() { @Override - public void handleSuccess() { - checkUrlParameters(getLeaderboardNamesCallback.getData(), - leaderboardGroupName == null ? null : getLeaderboardGroupByNameCallback.getData(), - canReplayWhileLiveIsPossible, getRegattasCallback.getData(), eventId == null ? null : getEventByIdCallback.getData(), - showMapControls); + public void onSuccess(RaceboardDataDTO result) { + checkUrlParameters(result, canReplayWhileLiveIsPossible, showMapControls); } - + @Override - public void handleFailure(Throwable t) { - reportError("Error trying to create the raceboard: " + t.getMessage()); + public void onFailure(Throwable caught) { + reportError("Error trying to create the raceboard: " + caught.getMessage()); } - }; - sailingService.getRegattas(getRegattasCallback); - sailingService.getLeaderboardNames(getLeaderboardNamesCallback); - if (eventId != null) { - sailingService.getEventById(eventId, /* withStatisticalData */ false, getEventByIdCallback); - } - if (leaderboardGroupName != null) { - sailingService.getLeaderboardGroupByName(leaderboardGroupNameParamValue, false /*withGeoLocationData*/, getLeaderboardGroupByNameCallback); - } + }); } private void createErrorPage(String message) { @@ -146,47 +116,29 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { vp.add(new Label(message)); } - private void checkUrlParameters(List leaderboardNames, LeaderboardGroupDTO leaderboardGroup, - boolean canReplayWhileLiveIsPossible, List regattas, EventDTO event, - boolean showMapControls) { - if (!leaderboardNames.contains(leaderboardName)) { + private void checkUrlParameters(RaceboardDataDTO raceboardData, boolean canReplayWhileLiveIsPossible, boolean showMapControls) { + if (!raceboardData.isValidLeaderboard()) { createErrorPage(getStringMessages().noSuchLeaderboard()); return; } - if (eventId != null && event == null) { + if (eventId != null && !raceboardData.isValidEvent()) { createErrorPage(getStringMessages().noSuchEvent()); } - if (leaderboardGroupName != null && leaderboardGroup != null) { - boolean foundLeaderboard = false; - for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.leaderboards) { - if (leaderboard.name.equals(leaderboardName)) { - foundLeaderboard = true; - break; - } - } - if (!foundLeaderboard) { + if (leaderboardGroupName != null) { + if(!raceboardData.isValidLeaderboardGroup()) { createErrorPage(getStringMessages().leaderboardNotContainedInLeaderboardGroup(leaderboardName, leaderboardGroupName)); return; } - if (event != null) { - boolean foundLeaderboardGroupInEvent = false; - for (LeaderboardGroupDTO lg : event.getLeaderboardGroups()) { - if (lg.getId().equals(leaderboardGroup.getId())) { - foundLeaderboardGroupInEvent = true; - break; - } - } - if (!foundLeaderboardGroupInEvent) { - createErrorPage(getStringMessages().leaderboardGroupNotContainedInEvent(leaderboardGroupName, event.getName())); - } + if (eventId != null && raceboardData.isValidLeaderboardGroup() && !raceboardData.isValidEvent()) { + createErrorPage(getStringMessages().leaderboardGroupNotContainedInEvent(leaderboardGroupName, eventId.toString())); + return; } } - RaceDTO race = findRace(regattaName, raceName, regattas); - selectedRace = race; - if (selectedRace == null) { + if (raceboardData.getRace() == null) { createErrorPage("Could not obtain a race with name " + raceName + " for a regatta with name " + regattaName); return; } + selectedRace = raceboardData.getRace(); Window.setTitle(selectedRace.getName()); RaceSelectionModel raceSelectionModel = new RaceSelectionModel(); List singletonList = Collections.singletonList(selectedRace.getRaceIdentifier()); @@ -194,24 +146,13 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint { Timer timer = new Timer(PlayModes.Replay, 1000l); AsyncActionsExecutor asyncActionsExecutor = new AsyncActionsExecutor(); RaceTimesInfoProvider raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, asyncActionsExecutor, this, singletonList, 5000l /* requestInterval*/); - RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, getUserService(), asyncActionsExecutor, timer, raceSelectionModel, - leaderboardName, leaderboardGroupName, event, raceboardViewConfig, RaceBoardEntryPoint.this, getStringMessages(), userAgent, raceTimesInfoProvider, showMapControls); + RaceBoardPanel raceBoardPanel = new RaceBoardPanel(sailingService, mediaService, getUserService(), asyncActionsExecutor, + raceboardData.getCompetitorAndTheirBoats(), timer, raceSelectionModel, leaderboardName, leaderboardGroupName, eventId, + raceboardViewConfig, RaceBoardEntryPoint.this, getStringMessages(), userAgent, raceTimesInfoProvider, showMapControls); + createRaceBoardInOneScreenMode(raceBoardPanel, raceboardViewConfig); } - private RaceDTO findRace(String regattaName, String raceName, List regattas) { - for (RegattaDTO regattaDTO : regattas) { - if (regattaDTO.getName().equals(regattaName)) { - for (RaceDTO raceDTO : regattaDTO.races) { - if (raceDTO.getName().equals(raceName)) { - return raceDTO; - } - } - } - } - return null; - } - private FlowPanel createTimePanel(RaceBoardPanel raceBoardPanel) { FlowPanel timeLineInnerBgPanel = new FlowPanel(); timeLineInnerBgPanel.addStyleName("timeLineInnerBgPanel"); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java old mode 100755 new mode 100644 index c13ec6619e6..414c16d8f1e --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Document; @@ -21,12 +22,16 @@ import com.google.gwt.user.client.ui.UIObject; import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.gwt.ui.client.CompetitorColorProvider; +import com.sap.sailing.gwt.ui.client.CompetitorColorProviderImpl; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; +import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; import com.sap.sailing.gwt.ui.client.GlobalNavigationPanel; import com.sap.sailing.gwt.ui.client.LeaderboardUpdateListener; @@ -52,7 +57,6 @@ import com.sap.sailing.gwt.ui.leaderboard.ExplicitRaceColumnSelectionWithPresele import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory; -import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sse.common.filter.FilterSet; import com.sap.sse.common.settings.AbstractSettings; import com.sap.sse.gwt.client.ErrorReporter; @@ -78,7 +82,7 @@ import com.sap.sse.security.ui.client.UserService; public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeListener, LeaderboardUpdateListener, PopupPositionProvider { private final SailingServiceAsync sailingService; private final MediaServiceAsync mediaService; - private final EventDTO event; + private final UUID eventId; private final StringMessages stringMessages; private final ErrorReporter errorReporter; private final RaceBoardViewConfiguration raceboardViewConfiguration; @@ -89,7 +93,7 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi private final Timer timer; private final RaceSelectionProvider raceSelectionProvider; private final UserAgentDetails userAgent; - private final CompetitorSelectionModel competitorSelectionModel; + private final CompetitorSelectionProvider competitorSelectionProvider; private final TimeRangeWithZoomModel timeRangeWithZoomModel; private final RegattaAndRaceIdentifier selectedRaceIdentifier; @@ -116,14 +120,14 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi private static final RaceMapResources raceMapResources = GWT.create(RaceMapResources.class); /** - * @param event + * @param eventId * an optional event that can be used for "back"-navigation in case the race board shows a race in the * context of an event; may be null. */ public RaceBoardPanel(SailingServiceAsync sailingService, MediaServiceAsync mediaService, - UserService userService, AsyncActionsExecutor asyncActionsExecutor, + UserService userService, AsyncActionsExecutor asyncActionsExecutor, Map competitorsAndTheirBoats, Timer timer, RaceSelectionProvider theRaceSelectionProvider, String leaderboardName, - String leaderboardGroupName, EventDTO event, RaceBoardViewConfiguration raceboardViewConfiguration, + String leaderboardGroupName, UUID eventId, RaceBoardViewConfiguration raceboardViewConfiguration, ErrorReporter errorReporter, final StringMessages stringMessages, UserAgentDetails userAgent, RaceTimesInfoProvider raceTimesInfoProvider, boolean showMapControls) { this.sailingService = sailingService; @@ -135,7 +139,7 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi this.errorReporter = errorReporter; this.userAgent = userAgent; this.timer = timer; - this.event = event; + this.eventId = eventId; this.currentRaceHasBeenSelectedOnce = false; this.leaderboardName = leaderboardName; raceSelectionProvider.addRaceSelectionChangeListener(this); @@ -151,13 +155,14 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi regattaAndRaceTimeInformationHeader.setStyleName("RegattaAndRaceTime-Header"); timeRangeWithZoomModel = new TimeRangeWithZoomModel(); componentViewers = new ArrayList(); - competitorSelectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true); + final CompetitorColorProvider colorProvider = new CompetitorColorProviderImpl(selectedRaceIdentifier, competitorsAndTheirBoats); + competitorSelectionProvider = new CompetitorSelectionModel(/* hasMultiSelection */ true, colorProvider); raceMapResources.combinedWindPanelStyle().ensureInjected(); raceMap = new RaceMap(sailingService, asyncActionsExecutor, errorReporter, timer, - competitorSelectionModel, stringMessages, showMapControls, getConfiguration().isShowViewStreamlets(), getConfiguration().isShowViewStreamletColors(), getConfiguration().isShowViewSimulation(), + competitorSelectionProvider, stringMessages, showMapControls, getConfiguration().isShowViewStreamlets(), getConfiguration().isShowViewStreamletColors(), getConfiguration().isShowViewSimulation(), selectedRaceIdentifier, raceMapResources.combinedWindPanelStyle(), /* showHeaderPanel */ true); - CompetitorFilterPanel competitorSearchTextBox = new CompetitorFilterPanel(competitorSelectionModel, stringMessages, raceMap, + CompetitorFilterPanel competitorSearchTextBox = new CompetitorFilterPanel(competitorSelectionProvider, stringMessages, raceMap, new LeaderboardFetcher() { @Override public LeaderboardDTO getLeaderboard() { @@ -171,7 +176,7 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi leaderboardPanel.setTitle(stringMessages.leaderboard()); leaderboardPanel.getElement().getStyle().setMarginLeft(6, Unit.PX); leaderboardPanel.getElement().getStyle().setMarginTop(10, Unit.PX); - createOneScreenView(leaderboardName, leaderboardGroupName, event, mainPanel, showMapControls, raceMap, userService); // initializes the raceMap field + createOneScreenView(leaderboardName, leaderboardGroupName, eventId, mainPanel, showMapControls, raceMap, userService); // initializes the raceMap field leaderboardPanel.addLeaderboardUpdateListener(this); // in case the URL configuration contains the name of a competitors filter set we try to activate it // FIXME the competitorsFilterSets has now moved to CompetitorSearchTextBox (which should probably be renamed); pass on the parameters to the LeaderboardPanel and see what it does with it @@ -196,13 +201,13 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi * @param event an optional event; may be null or else can be used to show some context information in * the {@link GlobalNavigationPanel}. */ - private void createOneScreenView(String leaderboardName, String leaderboardGroupName, EventDTO event, FlowPanel mainPanel, + private void createOneScreenView(String leaderboardName, String leaderboardGroupName, UUID event, FlowPanel mainPanel, boolean showMapControls, RaceMap raceMap, UserService userService) { // create the default leaderboard and select the right race raceTimesInfoProvider.addRaceTimesInfoProviderListener(raceMap); raceMap.onRaceSelectionChange(Collections.singletonList(selectedRaceIdentifier)); List> components = new ArrayList>(); - competitorChart = new MultiCompetitorRaceChart(sailingService, asyncActionsExecutor, competitorSelectionModel, raceSelectionProvider, + competitorChart = new MultiCompetitorRaceChart(sailingService, asyncActionsExecutor, competitorSelectionProvider, raceSelectionProvider, timer, timeRangeWithZoomModel, stringMessages, errorReporter, true, true, leaderboardGroupName, leaderboardName); competitorChart.onRaceSelectionChange(raceSelectionProvider.getSelectedRaces()); competitorChart.getEntryWidget().setTitle(stringMessages.competitorCharts()); @@ -214,9 +219,9 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi windChart.onRaceSelectionChange(raceSelectionProvider.getSelectedRaces()); windChart.getEntryWidget().setTitle(stringMessages.windChart()); components.add(windChart); - editMarkPassingPanel = new EditMarkPassingsPanel(sailingService, selectedRaceIdentifier, stringMessages, - competitorSelectionModel, errorReporter, timer); - editMarkPassingPanel.setLeaderboardNameAndColumn(leaderboardPanel.getLeaderboard()); + editMarkPassingPanel = new EditMarkPassingsPanel(sailingService, selectedRaceIdentifier, + stringMessages, competitorSelectionProvider, errorReporter, timer); + editMarkPassingPanel.setLeaderboard(leaderboardPanel.getLeaderboard()); editMarkPassingPanel.getEntryWidget().setTitle(stringMessages.editMarkPassings()); components.add(editMarkPassingPanel); boolean autoSelectMedia = getConfiguration().isAutoSelectMedia(); @@ -261,7 +266,7 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi new ExplicitRaceColumnSelectionWithPreselectedRace(selectedRaceIdentifier), /* showRegattaRank */ false, /*showCompetitorSailIdColumn*/true, /*showCompetitorFullNameColumn*/true); return new LeaderboardPanel(sailingService, asyncActionsExecutor, leaderBoardSettings, selectedRaceIdentifier != null, selectedRaceIdentifier, - competitorSelectionModel, timer, leaderboardGroupName, leaderboardName, errorReporter, stringMessages, + competitorSelectionProvider, timer, leaderboardGroupName, leaderboardName, errorReporter, stringMessages, userAgent, /* showRaceDetails */ true, competitorSearchTextBox, /* showSelectionCheckbox */ true, raceTimesInfoProvider, /* autoExpandLastRaceColumn */ false, /* don't adjust the timer's delay from the leaderboard; control it solely from the RaceTimesInfoProvider */ false, @@ -340,7 +345,7 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi @Override public void updatedLeaderboard(LeaderboardDTO leaderboard) { leaderboardAndMapViewer.setLeftComponentWidth(leaderboardPanel.getContentPanel().getOffsetWidth()); - editMarkPassingPanel.setLeaderboardNameAndColumn(leaderboard); + editMarkPassingPanel.setLeaderboard(leaderboard); } @Override @@ -365,14 +370,14 @@ public class RaceBoardPanel extends SimplePanel implements RaceSelectionChangeLi raceInformationHeader.add(raceNameLabel); raceInformationHeader.add(raceAdditionalInformationLabel); final Anchor regattaNameAnchor = new Anchor(raceIdentifier.getRegattaName()); - if (event != null) { + if (eventId != null) { // we don't use the EntryPointLinkFactory here, because of lacking support for Places String debugParam = Window.Location.getParameter("gwt.codesvr"); String link = "/gwt/Home.html"; if (debugParam != null && !debugParam.isEmpty()) { link += "?gwt.codesvr=" + debugParam; } - link += "#EventPlace:eventId="+event.id.toString(); + link += "#EventPlace:eventId="+eventId.toString(); link += "&navigationTab=Regatta&leaderboardName=" + URLEncoder.encode(leaderboardName); regattaNameAnchor.setHref(link); } else { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardViewConfiguration.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardViewConfiguration.java index c9c7a1ce220..ee83f828313 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardViewConfiguration.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardViewConfiguration.java @@ -85,8 +85,8 @@ public class RaceBoardViewConfiguration { } public boolean isAutoSelectMedia() { - return autoSelectMedia; - } + return autoSelectMedia; + } public String getDefaultMedia() { return defaultMedia; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 09379ba3410..db2cc255c71 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -17,7 +17,6 @@ import java.net.URLEncoder; import java.net.UnknownHostException; import java.text.ParseException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -64,7 +63,6 @@ import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; @@ -72,7 +70,12 @@ import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.MarkPassingDataFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesFinder; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState; @@ -83,6 +86,9 @@ import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogDefinedMarkFinder; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogOpenEndedDeviceMappingCloser; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; @@ -93,6 +99,7 @@ import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.Regatt import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder; import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder; import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer; +import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.ControlPoint; @@ -104,8 +111,6 @@ import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.EventBase; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardGroupBase; -import com.sap.sailing.domain.base.LeaderboardSearchResult; -import com.sap.sailing.domain.base.LeaderboardSearchResultBase; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.base.Nationality; @@ -179,6 +184,7 @@ import com.sap.sailing.domain.common.WindSourceType; import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.common.configuration.DeviceConfigurationMatcherType; import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.FullLeaderboardDTO; @@ -301,7 +307,6 @@ import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.GateDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupBaseDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; -import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO; import com.sap.sailing.gwt.ui.shared.LegInfoDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; @@ -323,6 +328,7 @@ import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO; import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsDTO; +import com.sap.sailing.gwt.ui.shared.RaceboardDataDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.RegattaLogDTO; import com.sap.sailing.gwt.ui.shared.RegattaLogEventDTO; @@ -438,14 +444,7 @@ import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.TimeRangeImpl; import com.sap.sse.common.mail.MailException; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; -import com.sap.sse.common.media.MediaUtils; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; -import com.sap.sse.common.search.KeywordQuery; -import com.sap.sse.common.search.Result; import com.sap.sse.filestorage.FileStorageService; import com.sap.sse.filestorage.InvalidPropertiesException; import com.sap.sse.gwt.client.ServerInfoDTO; @@ -461,6 +460,11 @@ import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.ReplicationService; import com.sap.sse.replication.impl.ReplicaDescriptor; import com.sap.sse.security.SessionUtils; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.MediaUtils; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; import com.sap.sse.util.ServiceTrackerFactory; import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON; @@ -1566,6 +1570,69 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } + @Override + public Map getCompetitorBoats(RegattaAndRaceIdentifier raceIdentifier) { + Map result = null; + TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); + if(trackedRace != null) { + List competitors = convertToCompetitorDTOs(trackedRace.getRace().getCompetitors()); + result = getCompetitorBoatsForRace(trackedRace.getRace(), competitors); + } + return result; + } + + @Override + public RaceboardDataDTO getRaceboardData(String regattaName, String raceName, + String leaderboardName, String leaderboardGroupName, UUID eventId) { + RaceWithCompetitorsDTO raceDTO = null; + Map competitorBoats = null; + Regatta regatta = getService().getRegattaByName(regattaName); + if (regatta != null) { + RaceDefinition race = regatta.getRaceByName(raceName); + if (race != null) { + RegattaAndRaceIdentifier raceIdentifier = new RegattaNameAndRaceName(regatta.getName(), race.getName()); + TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); + List competitors = convertToCompetitorDTOs(race.getCompetitors()); + competitorBoats = getCompetitorBoatsForRace(race, competitors); + TrackedRaceDTO trackedRaceDTO = null; + if (trackedRace != null) { + trackedRaceDTO = getBaseDomainFactory().createTrackedRaceDTO(trackedRace); + } + raceDTO = new RaceWithCompetitorsDTO(raceIdentifier, competitors, trackedRaceDTO, getService().isRaceBeingTracked(regatta, race)); + if (trackedRace != null) { + getBaseDomainFactory().updateRaceDTOWithTrackedRaceData(trackedRace, raceDTO); + } + raceDTO.boatClass = regatta.getBoatClass() == null ? null : regatta.getBoatClass().getName(); + } + } + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + LeaderboardGroup leaderboardGroup = leaderboardGroupName != null ? getService().getLeaderboardGroupByName(leaderboardGroupName) : null; + Event event = eventId != null ? getService().getEvent(eventId) : null; + + boolean isValidLeaderboard = leaderboard != null; + boolean isValidLeaderboardGroup = false; + if (leaderboardGroup != null) { + for(Leaderboard leaderboardInGroup: leaderboardGroup.getLeaderboards()) { + if(leaderboardInGroup.getName().equals(leaderboard.getName())) { + isValidLeaderboardGroup = true; + break; + } + } + } + boolean isValidEvent = event != null; + if (event != null && leaderboardGroup != null) { + isValidEvent = false; + for (LeaderboardGroup leaderboardGroupInEvent: event.getLeaderboardGroups()) { + if (leaderboardGroupInEvent.getId().equals(leaderboardGroup.getId())) { + isValidEvent = true; + break; + } + } + } + RaceboardDataDTO result = new RaceboardDataDTO(raceDTO, competitorBoats, isValidLeaderboard, isValidLeaderboardGroup, isValidEvent); + return result; + } + @Override public CompactRaceMapDataDTO getRaceMapData(RegattaAndRaceIdentifier raceIdentifier, Date date, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, @@ -1583,6 +1650,23 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return new CompactRaceMapDataDTO(boatPositions, coursePositions, courseSidelines, quickRanks, simulationResultVersion); } + private Map getCompetitorBoatsForRace(RaceDefinition race, List competitorDTOs) { + Map competitorBoats = new HashMap(); + HashMap competitorDTOsMap = new HashMap<>(); + for (CompetitorDTO competitorDTO : competitorDTOs) { + competitorDTOsMap.put(competitorDTO.getIdAsString(), competitorDTO); + } + for (Competitor competitor : race.getCompetitors()) { + Boat boatOfCompetitor = race.getBoatOfCompetitorById(competitor.getId()); + if (boatOfCompetitor != null) { + BoatDTO boatDTO = new BoatDTO(boatOfCompetitor.getName(), boatOfCompetitor.getSailID(), + boatOfCompetitor.getColor()); + competitorBoats.put(competitorDTOsMap.get(competitor.getId().toString()), boatDTO); + } + } + return competitorBoats; + } + /** * {@link LegType}s are cached within the method with a resolution of one minute. The cache key is a pair of * {@link TrackedLegOfCompetitor} and {@link TimePoint}. @@ -1862,7 +1946,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S result.totalLegsCount = trackedRace.getRace().getCourse().getLegs().size(); result.currentLegNumber = trackedRace.getLastLegStarted(dateAsTimePoint); result.marks = new HashSet(); - result.course = convertToRaceCourseDTO(trackedRace.getRace().getCourse(), trackedRace, dateAsTimePoint); + result.course = convertToRaceCourseDTO(trackedRace.getRace().getCourse(), new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); // now make sure we don't duplicate the MarkDTO objects but instead use the ones from the RaceCourseDTO // object and amend them with the Position result.waypointPositions = new ArrayList<>(); @@ -1936,7 +2020,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S for (Waypoint waypoint : course.getWaypoints()) { ControlPointDTO controlPointDTO = controlPointCache.get(waypoint.getControlPoint().getId()); if (controlPointDTO == null) { - controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint(), trackedRace, dateAsTimePoint); + controlPointDTO = convertToControlPointDTO(waypoint.getControlPoint(), new TrackedRaceMarkPositionFinder(trackedRace), dateAsTimePoint); controlPointCache.put(waypoint.getControlPoint().getId(), controlPointDTO); } WaypointDTO waypointDTO = new WaypointDTO(waypoint.getName(), controlPointDTO, @@ -1947,20 +2031,44 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return new RaceCourseDTO(waypointDTOs, allMarks); } - private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, TrackedRace trackedRace, TimePoint timePoint) { + class TrackedRaceMarkPositionFinder implements MarkPositionFinder{ + private TrackedRace trackedRace; + + public TrackedRaceMarkPositionFinder(TrackedRace trackedRace) { + this.trackedRace = trackedRace; + } + + @Override + public Position find(Mark mark, TimePoint at) { + final TimePoint timePointToUse = trackedRace == null ? null : + at == null ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : at; + final Position result; + if (timePointToUse == null) { + result = null; + } else { + result = trackedRace.getOrCreateTrack(mark).getEstimatedPosition(timePointToUse, /* extrapolate */ false); + } + return result; + } + } + + private interface MarkPositionFinder { + Position find(Mark mark, TimePoint at); + } + + private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, MarkPositionFinder positionFinder, TimePoint timePoint) { ControlPointDTO result; - final TimePoint timePointToUse = trackedRace == null ? null : - timePoint == null ? MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()) : timePoint; + if (controlPoint instanceof ControlPointWithTwoMarks) { final Mark left = ((ControlPointWithTwoMarks) controlPoint).getLeft(); - final Position leftPos = timePointToUse == null ? null : trackedRace.getOrCreateTrack(left).getEstimatedPosition(timePointToUse, /* extrapolate */ false); + final Position leftPos = positionFinder.find(left, timePoint); final Mark right = ((ControlPointWithTwoMarks) controlPoint).getRight(); - final Position rightPos = timePointToUse == null ? null : trackedRace.getOrCreateTrack(right).getEstimatedPosition(timePointToUse, /* extrapolate */ false); + final Position rightPos = positionFinder.find(right, timePoint); result = new GateDTO(controlPoint.getId().toString(), controlPoint.getName(), convertToMarkDTO(left, leftPos), convertToMarkDTO(right, rightPos)); } else { - final Position posOfFirst = timePointToUse == null ? null : trackedRace.getOrCreateTrack(controlPoint.getMarks().iterator().next()). - getEstimatedPosition(timePointToUse, /* extrapolate */ false); - result = new MarkDTO(controlPoint.getId().toString(), controlPoint.getName(), posOfFirst == null ? -1 : posOfFirst.getLatDeg(), posOfFirst == null ? -1 : posOfFirst.getLngDeg()); + Mark mark = controlPoint.getMarks().iterator().next(); + final Position position = positionFinder.find(mark, timePoint); + result = convertToMarkDTO(mark, position); } return result; } @@ -4729,14 +4837,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceLog raceLog = getRaceLog(dto.leaderboardName, dto.raceColumnName, dto.fleetName); // TODO If new is null and current is not, current should be revoked. if (!Util.equalsWithNull(dto.newStartOfTracking, dto.currentStartOfTracking)) { - raceLog.add(RaceLogEventFactory.INSTANCE.createStartOfTrackingEvent( - dto.newStartOfTracking, new LogEventAuthorImpl(dto.authorName, dto.authorPriority), UUID - .randomUUID(), new ArrayList(), raceLog.getCurrentPassId())); + raceLog.add(new RaceLogStartOfTrackingEventImpl( + dto.newStartOfTracking, new LogEventAuthorImpl(dto.authorName, dto.authorPriority), + raceLog.getCurrentPassId())); } if (!Util.equalsWithNull(dto.newEndOfTracking, dto.currentEndOfTracking)) { - raceLog.add(RaceLogEventFactory.INSTANCE.createEndOfTrackingEvent( - dto.newEndOfTracking, new LogEventAuthorImpl(dto.authorName, dto.authorPriority), UUID - .randomUUID(), new ArrayList(), raceLog.getCurrentPassId())); + raceLog.add(new RaceLogEndOfTrackingEventImpl( + dto.newEndOfTracking, new LogEventAuthorImpl(dto.authorName, dto.authorPriority), + raceLog.getCurrentPassId())); } } @@ -4973,7 +5081,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S public void addMarkToRaceLog(String leaderboardName, String raceColumnName, String fleetName, MarkDTO markDTO) { Mark mark = convertToMark(markDTO, false); RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDefineMarkEvent(MillisecondsTimePoint.now(), + RaceLogEvent event = new RaceLogDefineMarkEventImpl(MillisecondsTimePoint.now(), getService().getServerAuthor(), raceLog.getCurrentPassId(), mark); raceLog.add(event); } @@ -4993,7 +5101,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } if (eventToRevoke != null){ - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createRevokeEvent(getService().getServerAuthor(), raceLog.getCurrentPassId(), eventToRevoke, "Revoked by AdminConsole (RaceLogTracking)"); + RaceLogEvent event = new RaceLogRevokeEventImpl(getService().getServerAuthor(), raceLog.getCurrentPassId(), eventToRevoke, "Revoked by AdminConsole (RaceLogTracking)"); raceLog.add(event); } else { logger.warning("Could not revoke event for mark "+markDTO.getIdAsString()+". Mark not found in RaceLog."); @@ -5059,7 +5167,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S throw new RuntimeException(e); } - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(MillisecondsTimePoint.now(), + RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), getService().getServerAuthor(), raceLog.getCurrentPassId(), course); raceLog.add(event); } @@ -5072,10 +5180,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ - private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map controlPointCache, TrackedRace trackedRace, TimePoint timePoint) { + private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map controlPointCache, MarkPositionFinder positionFinder, TimePoint timePoint) { ControlPointDTO cp = controlPointCache.get(waypoint.getControlPoint().getId()); if (cp == null) { - cp = convertToControlPointDTO(waypoint.getControlPoint(), trackedRace, timePoint); + cp = convertToControlPointDTO(waypoint.getControlPoint(), positionFinder, timePoint); controlPointCache.put(waypoint.getControlPoint().getId(), cp); } return new WaypointDTO(waypoint.getName(), cp, waypoint.getPassingInstructions()); @@ -5091,13 +5199,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ - private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, TrackedRace trackedRace, TimePoint timePoint) { + private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, MarkPositionFinder positionFinder, TimePoint timePoint) { final RaceCourseDTO result; if (course != null) { List waypointDTOs = new ArrayList(); Map controlPointCache = new HashMap<>(); for (Waypoint waypoint : course.getWaypoints()) { - waypointDTOs.add(convertToWaypointDTO(waypoint, controlPointCache, trackedRace, timePoint)); + waypointDTOs.add(convertToWaypointDTO(waypoint, controlPointCache, positionFinder, timePoint)); } result = new RaceCourseDTO(waypointDTOs); } else { @@ -5107,13 +5215,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public RaceCourseDTO getLastCourseDefinitionInRaceLog(String leaderboardName, String raceColumnName, String fleetName) { - RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + public RaceCourseDTO getLastCourseDefinitionInRaceLog(final String leaderboardName, String raceColumnName, String fleetName) { + final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog).analyze(); if (lastPublishedCourse == null) { lastPublishedCourse = new CourseDataImpl(""); } - return convertToRaceCourseDTO(lastPublishedCourse, /* trackedRace */ null, /* timePoint */ null); + return convertToRaceCourseDTO(lastPublishedCourse, new MarkPositionFinder() { + @Override + public Position find(Mark mark, TimePoint at) { + return getService().getMarkPosition(mark, (LeaderboardThatHasRegattaLike) getService().getLeaderboardByName(leaderboardName), at, raceLog); + } + }, /* timePoint */ MillisecondsTimePoint.now()); } @Override @@ -5264,13 +5377,13 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); if (dto.mappedTo instanceof MarkDTO) { Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true); - event = RaceLogEventFactory.INSTANCE.createDeviceMarkMappingEvent(now, getService().getServerAuthor(), - mapping.getDevice(), mark, raceLog.getCurrentPassId(), from, to); + event = new RaceLogDeviceMarkMappingEventImpl(now, getService().getServerAuthor(), + raceLog.getCurrentPassId(), mark, mapping.getDevice(), from, to); } else if (dto.mappedTo instanceof CompetitorDTO) { Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString( ((CompetitorDTO) dto.mappedTo).getIdAsString()); - event = RaceLogEventFactory.INSTANCE.createDeviceCompetitorMappingEvent(now, getService().getServerAuthor(), - mapping.getDevice(), competitor, raceLog.getCurrentPassId(), from, to); + event = new RaceLogDeviceCompetitorMappingEventImpl(now, getService().getServerAuthor(), + raceLog.getCurrentPassId(), competitor, mapping.getDevice(), from, to); } else { throw new RuntimeException("Can only map devices to competitors or marks"); } @@ -5288,12 +5401,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); if (dto.mappedTo instanceof MarkDTO) { Mark mark = convertToMark(((MarkDTO) dto.mappedTo), true); - event = new RegattaLogDeviceMarkMappingEventImpl(now, getService().getServerAuthor(), now, UUID.randomUUID(), + event = new RegattaLogDeviceMarkMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), mark, mapping.getDevice(), from, to); } else if (dto.mappedTo instanceof CompetitorDTO) { Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString( ((CompetitorDTO) dto.mappedTo).getIdAsString()); - event = new RegattaLogDeviceCompetitorMappingEventImpl(now, getService().getServerAuthor(), now, UUID.randomUUID(), + event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), competitor, mapping.getDevice(), from, to); } else { throw new RuntimeException("Can only map devices to competitors or marks"); @@ -5465,45 +5578,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S return result; } - @Override - public Iterable getSearchServerNames() { - List result = new ArrayList<>(); - for (RemoteSailingServerReference remoteServerRef : getService().getLiveRemoteServerReferences()) { - result.add(remoteServerRef.getName()); - } - return result; - } - - @Override - public Iterable search(String serverNameOrNullForMain, KeywordQuery query) throws MalformedURLException { - final List result = new ArrayList<>(); - if (serverNameOrNullForMain == null) { - Result searchResult = getService().search(query); - for (LeaderboardSearchResult hit : searchResult.getHits()) { - result.add(createLeaderboardSearchResultDTO(hit, getRequestBaseURL(), false)); - } - } else { - RemoteSailingServerReference remoteRef = getService().getRemoteServerReferenceByName(serverNameOrNullForMain); - for (LeaderboardSearchResultBase hit : getService().searchRemotely(serverNameOrNullForMain, query).getHits()) { - result.add(createLeaderboardSearchResultDTO(hit, remoteRef.getURL(), true)); - } - } - return result; - } - - private LeaderboardSearchResultDTO createLeaderboardSearchResultDTO(LeaderboardSearchResultBase leaderboardSearchResult, URL baseURL, - boolean isOnRemoteServer) { - ArrayList leaderboardGroups = new ArrayList<>(); - for (LeaderboardGroupBase lgb : leaderboardSearchResult.getLeaderboardGroups()) { - LeaderboardGroupBaseDTO leaderboardGroupDTO = convertToLeaderboardGroupBaseDTO(lgb); - leaderboardGroups.add(leaderboardGroupDTO); - } - return new LeaderboardSearchResultDTO(baseURL.toString(), isOnRemoteServer, leaderboardSearchResult.getLeaderboard().getName(), - leaderboardSearchResult.getLeaderboard().getDisplayName(), leaderboardSearchResult.getRegattaName(), - leaderboardSearchResult.getBoatClassName(), convertToEventDTO(leaderboardSearchResult.getEvent()), - leaderboardGroups); - } - @Override public RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived) { if (newStartTimeReceived != null) { @@ -5574,8 +5648,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } if (dateOfMarkPassing != null) { - raceLog.add(RaceLogEventFactory.INSTANCE.createFixedMarkPassingEvent(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), UUID.randomUUID(), Arrays.asList(competitor), raceLog.getCurrentPassId(), + raceLog.add(new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), getService() + .getServerAuthor(), competitor, raceLog.getCurrentPassId(), new MillisecondsTimePoint(dateOfMarkPassing), indexOfWaypoint)); } } @@ -5622,8 +5696,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } } if (create) { - raceLog.add(RaceLogEventFactory.INSTANCE.createSuppressedMarkPassingsEvent(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), UUID.randomUUID(), Arrays.asList(competitor), raceLog.getCurrentPassId(), + raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), getService() + .getServerAuthor(), competitor, raceLog.getCurrentPassId(), newZeroBasedIndexOfSuppressedMarkPassing)); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CompactRaceMapDataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CompactRaceMapDataDTO.java index 386a21f86ee..d62034481db 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CompactRaceMapDataDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/CompactRaceMapDataDTO.java @@ -24,6 +24,7 @@ import com.sap.sse.common.Util; */ public class CompactRaceMapDataDTO implements IsSerializable { private Map> boatPositionsByCompetitorIdAsString; + private CoursePositionsDTO coursePositions; private List courseSidelines; private List quickRanks; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardSearchResultDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardSearchResultDTO.java index b91cdb995ae..27baba35087 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardSearchResultDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardSearchResultDTO.java @@ -22,13 +22,13 @@ public class LeaderboardSearchResultDTO implements IsSerializable { private String leaderboardDisplayName; private String regattaName; private String boatClassName; - private EventBaseDTO event; + private Iterable events; private Iterable leaderboardGroups; LeaderboardSearchResultDTO() {} // for GWT RPC serialization only public LeaderboardSearchResultDTO(String baseURL, boolean isOnRemoteServer, String leaderboardName, String leaderboardDisplayName, - String regattaName, String boatClassName, EventBaseDTO event, + String regattaName, String boatClassName, Iterable events, Iterable leaderboardGroups) { super(); this.baseURL = baseURL; @@ -37,7 +37,7 @@ public class LeaderboardSearchResultDTO implements IsSerializable { this.leaderboardDisplayName = leaderboardDisplayName; this.regattaName = regattaName; this.boatClassName = boatClassName; - this.event = event; + this.events = events; this.leaderboardGroups = leaderboardGroups; } @@ -61,8 +61,8 @@ public class LeaderboardSearchResultDTO implements IsSerializable { return boatClassName; } - public EventBaseDTO getEvent() { - return event; + public Iterable getEvents() { + return events; } public Iterable getLeaderboardGroups() { @@ -81,9 +81,9 @@ public class LeaderboardSearchResultDTO implements IsSerializable { sb.append(getLeaderboardDisplayName()); sb.append(")"); } - if (getEvent() != null) { - sb.append(", Event "); - sb.append(getEvent().getName()); + if (getEvents() != null) { + sb.append(", Events "); + sb.append(getEvents()); } sb.append(", "); sb.append("Boat class: "); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceWithCompetitorsDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceWithCompetitorsDTO.java index acac6f9885a..06a61fffcad 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceWithCompetitorsDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceWithCompetitorsDTO.java @@ -7,7 +7,7 @@ import com.sap.sailing.domain.common.dto.TrackedRaceDTO; public class RaceWithCompetitorsDTO extends RaceDTO { private static final long serialVersionUID = 5389509649915599951L; - public Iterable competitors; + private Iterable competitors; /** * Constructor for GWT serialization. @@ -24,4 +24,8 @@ public class RaceWithCompetitorsDTO extends RaceDTO { super(raceIdentifier); this.competitors = competitors; } + + public Iterable getCompetitors() { + return competitors; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceboardDataDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceboardDataDTO.java new file mode 100644 index 00000000000..5d49568ef14 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RaceboardDataDTO.java @@ -0,0 +1,51 @@ +package com.sap.sailing.gwt.ui.shared; + +import java.util.Map; + +import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; + +public class RaceboardDataDTO implements IsSerializable { + private Map competitorAndTheirBoats; + private RaceWithCompetitorsDTO race; + private boolean isValidLeaderboardGroup; + private boolean isValidLeaderboard; + private boolean isValidEvent; + + // for GWT + RaceboardDataDTO() {} + + public RaceboardDataDTO(RaceWithCompetitorsDTO race, Map competitorAndTheirBoats, + boolean isValidLeaderboard, boolean isValidLeaderboardGroup, boolean isValidEvent) { + this.race = race; + this.competitorAndTheirBoats = competitorAndTheirBoats; + this.isValidLeaderboard = isValidLeaderboard; + this.isValidLeaderboardGroup = isValidLeaderboardGroup; + this.isValidEvent = isValidEvent; + } + + public Map getCompetitorAndTheirBoats() { + return competitorAndTheirBoats; + } + + public Iterable getCompetitors() { + return race.getCompetitors(); + } + + public RaceWithCompetitorsDTO getRace() { + return race; + } + + public boolean isValidLeaderboardGroup() { + return isValidLeaderboardGroup; + } + + public boolean isValidLeaderboard() { + return isValidLeaderboard; + } + + public boolean isValidEvent() { + return isValidEvent; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Action.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Action.java deleted file mode 100644 index 606e22bc064..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/Action.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.google.gwt.user.client.rpc.IsSerializable; - -public interface Action extends IsSerializable { - - @GwtIncompatible - R execute(DispatchContext ctx) throws Exception; - -} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DTO.java deleted file mode 100644 index 6ef82ee7aae..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/DTO.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; - -import com.google.gwt.user.client.rpc.IsSerializable; - -public interface DTO extends IsSerializable { - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/NonBatchableAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/NonBatchableAction.java deleted file mode 100644 index b213910f11d..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/NonBatchableAction.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; - -public interface NonBatchableAction { - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWithTTL.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWithTTL.java deleted file mode 100644 index bee4a43eb01..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/ResultWithTTL.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch; - -import com.sap.sse.common.Duration; -import com.sap.sse.common.impl.MillisecondsDurationImpl; - -public class ResultWithTTL implements Result { - - /** Time to live*/ - private Duration ttl; - private T dto; - - @SuppressWarnings("unused") - private ResultWithTTL() { - } - - public ResultWithTTL(long ttl, T dto) { - this(new MillisecondsDurationImpl(ttl), dto); - } - - public ResultWithTTL(Duration ttl, T dto) { - this.ttl = ttl; - this.dto = dto; - } - - public T getDto() { - return dto; - } - - public Duration getTtl() { - return ttl; - } - - public long getTtlMillis() { - return ttl.asMillis(); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventStatisticsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventStatisticsAction.java deleted file mode 100644 index 8cf6cb0005f..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetEventStatisticsAction.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; - -public class GetEventStatisticsAction implements Action> { - - private UUID eventId; - - protected GetEventStatisticsAction() { - } - - public GetEventStatisticsAction(UUID eventId) { - this.eventId = eventId; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) throws Exception { - StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); - EventActionUtil.forLeaderboardsOfEvent(context, eventId, statisticsCalculator); - return statisticsCalculator.getResult(); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniLeaderbordAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniLeaderbordAction.java deleted file mode 100644 index 99ed7e7b4a1..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniLeaderbordAction.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; - -public class GetMiniLeaderbordAction implements Action> { - private UUID eventId; - private String leaderboardName; - private int limit = 0; - - @SuppressWarnings("unused") - private GetMiniLeaderbordAction() { - } - - public GetMiniLeaderbordAction(UUID eventId, String leaderboardName) { - this(eventId, leaderboardName, 0); - } - - public GetMiniLeaderbordAction(UUID eventId, String leaderboardName, int limit) { - this.eventId = eventId; - this.leaderboardName = leaderboardName; - this.limit = limit; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) { - return EventActionUtil.getLeaderboardContext(context, eventId, leaderboardName).calculateMiniLeaderboard(context.getRacingEventService(), limit); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniOverallLeaderbordAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniOverallLeaderbordAction.java deleted file mode 100644 index 1ffaef9d896..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetMiniOverallLeaderbordAction.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; - -public class GetMiniOverallLeaderbordAction implements Action> { - private UUID seriesId; - private int limit = 0; - - @SuppressWarnings("unused") - private GetMiniOverallLeaderbordAction() { - } - - public GetMiniOverallLeaderbordAction(UUID eventId) { - this(eventId, 0); - } - - public GetMiniOverallLeaderbordAction(UUID seriesId, int limit) { - this.seriesId = seriesId; - this.limit = limit; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) { - return EventActionUtil.getOverallLeaderboardContext(context, seriesId).calculateMiniLeaderboard(context.getRacingEventService(), limit); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaStatisticsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaStatisticsAction.java deleted file mode 100644 index 6bfc23573b4..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaStatisticsAction.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; - -public class GetRegattaStatisticsAction implements Action>{ - - private UUID eventId; - private String regattaId; - - protected GetRegattaStatisticsAction() { - } - - public GetRegattaStatisticsAction(UUID eventId, String regattaId) { - this.eventId = eventId; - this.regattaId = regattaId; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) throws Exception { - StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); - statisticsCalculator.doForLeaderboard(EventActionUtil.getLeaderboardContext(context, eventId, regattaId)); - return statisticsCalculator.getResult(); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaWithProgressAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaWithProgressAction.java deleted file mode 100644 index 686ac9c5206..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetRegattaWithProgressAction.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; -import com.sap.sailing.gwt.ui.shared.dispatch.regatta.RegattaWithProgressDTO; -import com.sap.sse.common.Duration; - -public class GetRegattaWithProgressAction implements Action> { - - private UUID eventId; - private String regattaId; - - @SuppressWarnings("unused") - private GetRegattaWithProgressAction() { - } - - public GetRegattaWithProgressAction(UUID eventId, String regattaId) { - this.eventId = eventId; - this.regattaId = regattaId; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) { - return new ResultWithTTL<>(EventActionUtil.getEventStateDependentTTL(context, eventId, Duration.ONE_MINUTE.times(5)), - EventActionUtil.getLeaderboardContext(context, eventId, regattaId).getRegattaWithProgress()); - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetSeriesStatisticsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetSeriesStatisticsAction.java deleted file mode 100644 index fc7cf3f05e3..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/event/GetSeriesStatisticsAction.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.event; - -import java.util.UUID; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWithTTL; - -public class GetSeriesStatisticsAction implements Action>{ - - private UUID seriesId; - - protected GetSeriesStatisticsAction() { - } - - public GetSeriesStatisticsAction(UUID seriesId) { - this.seriesId = seriesId; - } - - @Override - @GwtIncompatible - public ResultWithTTL execute(DispatchContext context) throws Exception { - StatisticsCalculator statisticsCalculator = new StatisticsCalculator(); - EventActionUtil.forLeaderboardsOfEvent(context, seriesId, statisticsCalculator); - return statisticsCalculator.getResult(); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPC.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPC.java deleted file mode 100644 index e1c204f73da..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPC.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.rpc; - -import com.google.gwt.user.client.rpc.RemoteService; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchException; -import com.sap.sailing.gwt.ui.shared.dispatch.RequestWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWrapper; - -public interface DispatchRPC extends RemoteService { - - > ResultWrapper execute(RequestWrapper action) throws DispatchException; - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPCAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPCAsync.java deleted file mode 100644 index 575001164ce..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/rpc/DispatchRPCAsync.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.rpc; - -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.RequestWrapper; -import com.sap.sailing.gwt.ui.shared.dispatch.Result; -import com.sap.sailing.gwt.ui.shared.dispatch.ResultWrapper; - -public interface DispatchRPCAsync { - - > void execute(RequestWrapper action, AsyncCallback> callback); - -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetStagedEventsAction.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetStagedEventsAction.java deleted file mode 100644 index 1b558f8dcf4..00000000000 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/dispatch/start/GetStagedEventsAction.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.sap.sailing.gwt.ui.shared.dispatch.start; - -import java.net.MalformedURLException; - -import com.google.gwt.core.shared.GwtIncompatible; -import com.sap.sailing.gwt.server.EventHolder; -import com.sap.sailing.gwt.server.EventStageCandidateCalculator; -import com.sap.sailing.gwt.server.HomeServiceImpl; -import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.shared.dispatch.Action; -import com.sap.sailing.gwt.ui.shared.dispatch.DispatchContext; -import com.sap.sailing.gwt.ui.shared.dispatch.ListResult; -import com.sap.sailing.gwt.ui.shared.start.EventStageDTO; -import com.sap.sailing.gwt.ui.shared.start.StageEventType; -import com.sap.sse.common.Util.Pair; - -public class GetStagedEventsAction implements Action> { - - private boolean useTeaserImage; - - protected GetStagedEventsAction() { - } - - public GetStagedEventsAction(boolean useTeaserImage) { - this.useTeaserImage = useTeaserImage; - } - - @GwtIncompatible - public ListResult execute(final DispatchContext context) throws MalformedURLException { - EventStageCandidateCalculator stageCandidateCalculator = new EventStageCandidateCalculator(); - HomeServiceUtil.forAllPublicEvents(context.getRacingEventService(), context.getRequest(), stageCandidateCalculator); - ListResult result = new ListResult<>(); - int count = 0; - for(Pair pair : stageCandidateCalculator.getFeaturedEvents()) { - count++; - if(count > HomeServiceImpl.MAX_STAGE_EVENTS) { - break; - } - StageEventType stageType = pair.getA(); - EventHolder holder = pair.getB(); - result.addValue(HomeServiceUtil.convertToEventStageDTO(holder.event, holder.baseURL, holder.onRemoteServer, stageType, context.getRacingEventService(), useTeaserImage)); - } - return result; - } -} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorMainPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorMainPanel.java index 5df963e9195..815def789c1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorMainPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorMainPanel.java @@ -310,25 +310,38 @@ public class SimulatorMainPanel extends SimplePanel { int secondsTimeStep = (int) windParams.getTimeStep().asSeconds(); timer.setPlaySpeedFactor(secondsTimeStep); timePanel = new TimePanel(timer, timeRangeProvider, stringMessages, false); - busyIndicator = new SimpleBusyIndicator(false, 0.8f); - - simulatorMap = new SimulatorMap(simulatorSvc, stringMessages, errorReporter, xRes, yRes, border, streamletPars, timer, timePanel, - windParams, busyIndicator, mode, this, showMapControls, new IdentityCoordinateSystem()); + simulatorMap = new SimulatorMap(simulatorSvc, stringMessages, errorReporter, xRes, yRes, border, streamletPars, + timer, timePanel, windParams, busyIndicator, mode, this, showMapControls, + new IdentityCoordinateSystem()); simulatorMap.setSize("100%", "100%"); - this.rightPanel.add(this.simulatorMap); - createOptionsPanelTop(); createOptionsPanel(); - fullTimePanel = this.createTimePanel(); + final Button toggleButton = timePanel.getAdvancedToggleButton(); + toggleButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + boolean advancedModeShown = timePanel.toggleAdvancedMode(); + if (advancedModeShown) { + mainPanel.setWidgetSize(fullTimePanel, 96); + toggleButton.removeStyleDependentName("Closed"); + toggleButton.addStyleDependentName("Open"); + } else { + mainPanel.setWidgetSize(fullTimePanel, 67); + toggleButton.addStyleDependentName("Closed"); + toggleButton.removeStyleDependentName("Open"); + } + } + }); + mainPanel = new DockLayoutPanel(Unit.PX); mainPanel.setSize("100%", "100%"); mainPanel.addWest(leftPanel, 470); - mainPanel.addSouth(fullTimePanel, 90); + mainPanel.addSouth(fullTimePanel, 67); mainPanel.setWidgetHidden(fullTimePanel, true); createMapOptionsPanel(); // add map-options to mainPanel-North @@ -340,21 +353,21 @@ public class SimulatorMainPanel extends SimplePanel { } public native void setMapInstance(Object mapInstance) /*-{ - $wnd.swarmMap = mapInstance; + $wnd.swarmMap = mapInstance; }-*/; public native void setCanvasProjectionInstance(Object instance) /*-{ - $wnd.swarmCanvasProjection = instance; - }-*/; + $wnd.swarmCanvasProjection = instance; + }-*/; public native void startStreamlets() /*-{ - if ($wnd.swarmAnimator) { - $wnd.swarmUpdData = true; - $wnd.updateStreamlets($wnd.swarmUpdData); - } else { - $wnd.initStreamlets($wnd.swarmMap); - } - }-*/; + if ($wnd.swarmAnimator) { + $wnd.swarmUpdData = true; + $wnd.updateStreamlets($wnd.swarmUpdData); + } else { + $wnd.initStreamlets($wnd.swarmMap); + } + }-*/; public void setDefaultTimeSettings() { Date defaultNow = new Date(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/main.gss b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/main.gss index 8bc3232eb44..ef74f7a328f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/main.gss +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/main.gss @@ -74,6 +74,9 @@ figcaption { min-height: 100%; padding-bottom: 5em; } +.mobile .wrapper { + padding-bottom: 11.333333333333334em; +} .navbar { font-size: 1rem; } @@ -90,6 +93,8 @@ figcaption { transition: background-color 0.2s, border-color 0.2s; text-decoration: none; margin-right: 0.555555555555556em; +} +.desktop .navbar_button { border-top-left-radius: 0.277777777777778em; border-top-right-radius: 0.277777777777778em; } @@ -144,9 +149,11 @@ figcaption { font-size: 0.933333333333333rem; font-weight: 700; text-transform: uppercase; - border-radius: 0.214285714285714em; padding: 0.714285714285714em 1.071428571428571em; } +.desktop .buttonstrong { + border-radius: 0.214285714285714em; +} .buttoninactive { background-color: #ebebeb; pointer-events: none; @@ -222,6 +229,12 @@ figcaption { height: 1.666666666666667em; line-height: 1.666666666666667em; } +.mobile .label { + font-size: 0.666666666666667rem; + margin-left: 1em; + height: 1.6em; + line-height: 1.6em; +} .label:before { content: ''; position: absolute; @@ -233,17 +246,34 @@ figcaption { border-bottom: 0.833333333333333em solid transparent; border-right: 0.833333333333333em solid transparent; } +.mobile .label:before { + left: -0.8em; + border-top: 0.8em solid transparent; + border-bottom: 0.8em solid transparent; + border-right: 0.8em solid transparent; +} .labellarge { height: 2em; line-height: 1.75em; margin-left: 1em; } +.mobile .labellarge { + height: 2.4em; + line-height: 2.1em; + margin-left: 1.2em; +} .labellarge:before { left: -1em; border-top-width: 1em; border-bottom-width: 1em; border-right-width: 1em; } +.mobile .labellarge:before { + left: -1.2em; + border-top-width: 1.2em; + border-bottom-width: 1.2em; + border-right-width: 1.2em; +} .label[data-labeltype='live'] { background-color: #e94a1b; vertical-align: middle; @@ -348,6 +378,10 @@ figcaption { .mainsection { padding: 5.333333333333333em 0; } +.mobile .mainsection { + padding-top: 5.333333333333333em; + padding-bottom: 5.333333333333333em; +} .mainsection_header { text-align: center; margin-bottom: 4em; @@ -490,3 +524,13 @@ figcaption { .slidetoactive:hover { border-bottom-color: #d79900; } +.fleetcorner { + position: absolute; + top: 0.333333333333333em; + left: 0.333333333333333em; + width: 0; + height: 0; + border-style: solid; + border-width: 1em 1em 0 0; + color: transparent; +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html index a07f7f35236..547230f6227 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/home/solutions/SailingAnalyticsNotes.html @@ -4,6 +4,51 @@

What's New - SAP Sailing Analytics

+
November 2015
+ +
    +
  • The smartphone page provides some structural navigation items for several pages in the upper right burger menu. + You will see links to e.g. events, regattas and series when navigating on event and series pages. +
  • +
  • It is now possible to filter for competitors in the race list of events/regattas. + If competitor information is available, there is a filter box in the upper right corner of the races page. + The filter is searching for competitors by sail ID as well as the competitor's name. +
  • +
  • Regattas can now be filtered by boat category in the smartphone page. + The filter will be shown for events with multiple regattas if there is more than on boat category associated with the event. +
  • +
+ +
October 2015
+ +
    +
  • A variety of tablets will now show the desktop page by default. + The mobile version of the website is primarily designed to be used on smartphones, + but you can manually switch back to the mobile version by clicking the corresponding link in the page footer. +
  • +
  • There is some amount of caching on the web page to reduce the consumed traffic for mobile users. + Contents aren't loaded again on each page switch. This improves the traffic consumption and loading speed on fast page switches. +
  • +
  • The fullscreen image viewer (start page and event media page) can automatically slide through the images. + This can be turned on by clicking the corresponding icon in the upper right corner of the fullscreen viewer. +
  • +
  • There is an optimized search and results page for mobile devices now. +
  • +
+ +
September 2015
+ +
    +
  • Races in the event/regatta race list can now be shown in 'competition format'. + In this format the races and flights are shown in a structural view. + In contrast to the default list view there is no grouping by live and finished states and all + (including upcoming) races/flights are shown in one structural view. +
  • +
  • The mobile page now provides regatta overview pages for events having multiple regattas. + This page shows live races, an excerpt of the current results as well as statistics for the regatta. +
  • +
+
August 2015
    @@ -18,6 +63,10 @@ Log entries added after import on the importing server were not written to the database and therefore were lost upon server restart. +
  • There is a smartphone-optimized version of the "solutions" page known from the desktop. +
  • +
  • The smartphone event history now has a slider that allows swiping through the events of a year. +
July 2015
@@ -27,7 +76,7 @@ users. Race lists are now sortable by various criteria by clicking on the column headers. A new fancy progress indicator now also provides visual feedback for multi-fleet regattas. A news ticker box has been implemented, and the event - overview page can hold a video player on its stage. The even media gallery section + overview page can hold a video player on its stage. The event media gallery section has been greatly improved.
  • Fixed a bug in the wind streamlet visualization. Now the wind streamlets @@ -39,6 +88,11 @@ or line, respectively, and its angle to the wind. For the start and finish line the advantage of the favored side is shown in meters.
  • +
  • The SAP Sailing Analytics start page is now available in the smartphone version. + This page features some events that are currently interesting as well as showing a + quickfinder for a variety of recent and upcoming events. + Previously, the start page redirected to the event history. +
  • May 2015
    diff --git a/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF index 119decea365..fa9864f7111 100644 --- a/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.mongodb.test/META-INF/MANIFEST.MF @@ -27,7 +27,8 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sse.operationaltransformation, com.sap.sse.replication, com.sap.sse, - com.sap.sse.filestorage + com.sap.sse.filestorage, + com.sap.sse.shared.android Import-Package: com.sap.sailing.domain.common, com.sap.sailing.domain.common.impl, com.sap.sailing.domain.common.racelog, diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java index 6929cd0e4ad..ccc0a758f12 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadDeviceIdentifierTest.java @@ -15,8 +15,8 @@ import com.mongodb.MongoException; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.impl.CompetitorImpl; @@ -83,8 +83,8 @@ public class StoreAndLoadDeviceIdentifierTest extends AbstractMongoDBTest { createFactories(forStoring); Competitor c = new CompetitorImpl("a", "a", null, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); - raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceCompetitorMappingEvent(now(), author, device, - c, 0, now(), now())); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(now(), author, 0, + c, device, now(), now())); createFactories(forLoading); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java index ac1c218881a..ab651c9a1b8 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogEventsTest.java @@ -22,18 +22,29 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDeviceMarkMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -58,8 +69,7 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { .getMongoObjectFactory(getMongoService(), new MockSmartphoneImeiServiceFinderFactory()); protected DomainObjectFactoryImpl domainFactory = (DomainObjectFactoryImpl) PersistenceFactory.INSTANCE .getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE, - new MockSmartphoneImeiServiceFinderFactory()); - protected RaceLogEventRestoreFactory eventFactory = RaceLogEventRestoreFactory.INSTANCE; + new MockSmartphoneImeiServiceFinderFactory()); protected RaceLogIdentifier logIdentifier; @@ -76,7 +86,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Before public void setUp() { logIdentifier = mock(RaceLogIdentifier.class); - when(logIdentifier.getIdentifier()).thenReturn(new com.sap.sse.common.Util.Triple("a", "b", UUID.randomUUID().toString())); + when(logIdentifier.getIdentifier()).thenReturn( + new com.sap.sse.common.Util.Triple("a", "b", UUID.randomUUID().toString())); } public void assertBaseFields(RaceLogEvent expectedEvent, RaceLogEvent actualEvent) { @@ -87,15 +98,15 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { assertEquals(expectedEvent.getInvolvedBoats().size(), Util.size(actualEvent.getInvolvedBoats())); assertEquals(expectedEvent.getPassId(), actualEvent.getPassId()); } - - @Test + + @Test public void testStoreEventWithoutAuthorLoadsCompatibilityAuthor() { - RaceLogFlagEvent expectedEvent = eventFactory.createFlagEvent(expectedEventTime, - null, expectedId, expectedInvolvedBoats, expectedPassId, Flags.NONE, Flags.NONE, true); + RaceLogFlagEvent expectedEvent = new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), expectedEventTime, null, + expectedId, expectedPassId, Flags.NONE, Flags.NONE, true); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogFlagEvent actualEvent = loadEvent(dbObject); - + assertNull(expectedEvent.getAuthor()); assertNotNull(actualEvent.getAuthor()); assertEquals(AbstractLogEventAuthor.PRIORITY_COMPATIBILITY, actualEvent.getAuthor().getPriority()); @@ -108,8 +119,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { Flags lowerFlag = Flags.BRAVO; boolean isDisplayed = true; - RaceLogFlagEvent expectedEvent = eventFactory.createFlagEvent(expectedEventTime, - author, expectedId, expectedInvolvedBoats, expectedPassId, upperFlag, lowerFlag, isDisplayed); + RaceLogFlagEvent expectedEvent = new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), expectedEventTime, + author, expectedId, expectedPassId, upperFlag, lowerFlag, isDisplayed); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogFlagEvent actualEvent = loadEvent(dbObject); @@ -124,8 +135,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { public void testStoreAndLoadCourseAreaChangedEvent() { Serializable courseAreaId = UUID.randomUUID(); - RaceLogCourseAreaChangedEvent expectedEvent = eventFactory.createCourseAreaChangedEvent( - expectedEventTime, author, expectedId, expectedInvolvedBoats, expectedPassId, courseAreaId); + RaceLogCourseAreaChangedEvent expectedEvent = new RaceLogCourseAreaChangeEventImpl(MillisecondsTimePoint.now(), + expectedEventTime, author, expectedId, expectedPassId, courseAreaId); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogCourseAreaChangedEvent actualEvent = loadEvent(dbObject); @@ -136,8 +147,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadPassChangeEvent() { - RaceLogPassChangeEvent expectedEvent = eventFactory.createPassChangeEvent(expectedEventTime, - author, expectedId, expectedInvolvedBoats, expectedPassId); + RaceLogPassChangeEvent expectedEvent = new RaceLogPassChangeEventImpl(MillisecondsTimePoint.now(), + expectedEventTime, author, expectedId, expectedPassId); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogPassChangeEvent actualEvent = loadEvent(dbObject); @@ -148,8 +159,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadRaceStatusEvent() { RaceLogRaceStatus status = RaceLogRaceStatus.SCHEDULED; - RaceLogRaceStatusEvent expectedEvent = eventFactory.createRaceStatusEvent(expectedEventTime, - author, expectedId, expectedInvolvedBoats, expectedPassId, status); + RaceLogRaceStatusEvent expectedEvent = new RaceLogRaceStatusEventImpl(MillisecondsTimePoint.now(), + expectedEventTime, author, expectedId, expectedPassId, status); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogRaceStatusEvent actualEvent = loadEvent(dbObject); @@ -161,8 +172,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadStartTimeEvent() { TimePoint startTime = new MillisecondsTimePoint(1337); - RaceLogStartTimeEvent expectedEvent = eventFactory.createStartTimeEvent(expectedEventTime, - author, expectedId, expectedInvolvedBoats, expectedPassId, startTime); + RaceLogStartTimeEvent expectedEvent = new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), + expectedEventTime, author, expectedId, expectedPassId, startTime, RaceLogRaceStatus.SCHEDULED); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogStartTimeEvent actualEvent = loadEvent(dbObject); @@ -178,8 +189,9 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { null, /* timeOnDistanceAllowancePerNauticalMile */null); TimePoint from = new MillisecondsTimePoint(20); TimePoint to = new MillisecondsTimePoint(30); - RaceLogDeviceCompetitorMappingEvent expectedEvent = eventFactory.createDeviceCompetitorMappingEvent( - expectedEventTime, author, expectedEventTime, expectedId, device, mappedTo, expectedPassId, from, to); + RaceLogDeviceCompetitorMappingEvent expectedEvent = new RaceLogDeviceCompetitorMappingEventImpl( + expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, + mappedTo, device, from, to); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogDeviceCompetitorMappingEvent actualEvent = loadEvent(dbObject); @@ -197,8 +209,9 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { Mark mappedTo = DomainFactory.INSTANCE.getOrCreateMark("abc", "abc"); TimePoint from = new MillisecondsTimePoint(20); TimePoint to = new MillisecondsTimePoint(30); - RaceLogDeviceMarkMappingEvent expectedEvent = eventFactory.createDeviceMarkMappingEvent( - expectedEventTime, author, expectedEventTime, expectedId, device, mappedTo, expectedPassId, from, to); + RaceLogDeviceMarkMappingEvent expectedEvent = new RaceLogDeviceMarkMappingEventImpl( + expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, + mappedTo, device, from, to); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogDeviceMarkMappingEvent actualEvent = loadEvent(dbObject); @@ -212,12 +225,12 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadDenoteForTrackingEvent() { - String raceName = "race"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); - UUID raceId = UUID.randomUUID(); - RaceLogDenoteForTrackingEvent expectedEvent = eventFactory.createDenoteForTrackingEvent( - expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, raceName, boatClass, - raceId); + String raceName = "race"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("49er"); + UUID raceId = UUID.randomUUID(); + RaceLogDenoteForTrackingEvent expectedEvent = new RaceLogDenoteForTrackingEventImpl( + expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, + raceName, boatClass, raceId); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogDenoteForTrackingEvent actualEvent = loadEvent(dbObject); @@ -234,9 +247,8 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { String revokedEventType = "type"; String revokedEventShortInfo = "short info"; String reason = "reason"; - RaceLogRevokeEvent expectedEvent = eventFactory.createRevokeEvent( - expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, revokedEventId, - revokedEventType, revokedEventShortInfo, reason); + RaceLogRevokeEvent expectedEvent = new RaceLogRevokeEventImpl(expectedEventTime, expectedEventTime, author, + expectedId, expectedPassId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogRevokeEvent actualEvent = loadEvent(dbObject); @@ -250,10 +262,10 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadRegisterCompetitorEvent() { - RaceLogRegisterCompetitorEvent expectedEvent = eventFactory.createRegisterCompetitorEvent( - expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, - DomainFactory.INSTANCE.getOrCreateCompetitor("comp", "comp", null, null, null, null, null, - /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); + RaceLogRegisterCompetitorEvent expectedEvent = new RaceLogRegisterCompetitorEventImpl(expectedEventTime, + expectedEventTime, author, expectedId, expectedPassId, DomainFactory.INSTANCE.getOrCreateCompetitor( + "comp", "comp", null, null, null, null, null, + /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogRegisterCompetitorEvent actualEvent = loadEvent(dbObject); @@ -264,9 +276,9 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadDefineMarkEvent() { - RaceLogDefineMarkEvent expectedEvent = eventFactory.createDefineMarkEvent( - expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, - DomainFactory.INSTANCE.getOrCreateMark("mytestmark")); + RaceLogDefineMarkEvent expectedEvent = new RaceLogDefineMarkEventImpl(MillisecondsTimePoint.now(), + expectedEventTime, author, expectedId, expectedPassId, + DomainFactory.INSTANCE.getOrCreateMark("mytestmark")); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogDefineMarkEvent actualEvent = loadEvent(dbObject); @@ -277,9 +289,9 @@ public class StoreAndLoadRaceLogEventsTest extends AbstractMongoDBTest { @Test public void testStoreAndLoadCloseOpenDeviceMappingEvent() { - RaceLogCloseOpenEndedDeviceMappingEvent expectedEvent = eventFactory.createCloseOpenEndedDeviceMappingEvent( - expectedEventTime, author, expectedEventTime, expectedId, expectedPassId, - UUID.randomUUID(), new MillisecondsTimePoint(49)); + RaceLogCloseOpenEndedDeviceMappingEvent expectedEvent = new RaceLogCloseOpenEndedDeviceMappingEventImpl( + expectedEventTime, expectedEventTime, author, expectedId, expectedPassId, UUID.randomUUID(), + new MillisecondsTimePoint(49)); DBObject dbObject = mongoFactory.storeRaceLogEntry(logIdentifier, expectedEvent); RaceLogCloseOpenEndedDeviceMappingEvent actualEvent = loadEvent(dbObject); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java index d9740110b41..a1e39ec8e09 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadRaceLogsTest.java @@ -6,7 +6,6 @@ import static org.mockito.Mockito.when; import java.io.Serializable; import java.net.UnknownHostException; -import java.util.Collections; import java.util.UUID; import org.junit.Test; @@ -15,9 +14,8 @@ import com.mongodb.DBObject; import com.mongodb.MongoException; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.common.racelog.Flags; @@ -36,7 +34,6 @@ public class StoreAndLoadRaceLogsTest extends AbstractMongoDBTest { .getMongoObjectFactory(getMongoService()); protected DomainObjectFactoryImpl domainFactory = (DomainObjectFactoryImpl) PersistenceFactory.INSTANCE .getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - protected RaceLogEventFactory eventFactory = RaceLogEventFactory.INSTANCE; public StoreAndLoadRaceLogsTest() throws UnknownHostException, MongoException { super(); @@ -99,7 +96,7 @@ public class StoreAndLoadRaceLogsTest extends AbstractMongoDBTest { } private RaceLogFlagEvent createRaceLogFlagEvent(Serializable id) { - return eventFactory.createFlagEvent(new MillisecondsTimePoint(42), new LogEventAuthorImpl("Test author", /* priority */ 1), id, Collections. emptyList(), + return new RaceLogFlagEventImpl(MillisecondsTimePoint.now(), new MillisecondsTimePoint(42), new LogEventAuthorImpl("Test author", /* priority */ 1), id, 42, Flags.ALPHA, Flags.BRAVO, true); } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java index ce41d3e48d2..c281b7d4f4c 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreGPSFixTrackTest.java @@ -13,8 +13,9 @@ import com.mongodb.MongoException; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Mark; @@ -86,8 +87,8 @@ public class StoreGPSFixTrackTest extends AbstractMongoDBTest { store.storeFix(device2, fix4); RaceLog raceLog = new RaceLogImpl("racelog"); - raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceCompetitorMappingEvent(time0, author, device1, comp, 0, time0, time1)); - raceLog.add(RaceLogEventFactory.INSTANCE.createDeviceMarkMappingEvent(time0, author, device2, mark, 0, time0, time1)); + raceLog.add(new RaceLogDeviceCompetitorMappingEventImpl(time0, author, 0, comp, device1, time0, time1)); + raceLog.add(new RaceLogDeviceMarkMappingEventImpl(time0, author, 0, mark, device2, time0, time1)); DynamicGPSFixMovingTrackImpl track1 = new DynamicGPSFixMovingTrackImpl<>(comp, 0); store.loadCompetitorTrack(track1, raceLog, comp); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java index 1359256c846..ecf424c8071 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestRaceLogRemovalInRegatta.java @@ -10,9 +10,10 @@ import org.junit.Test; import com.mongodb.MongoException; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.impl.FleetImpl; @@ -50,9 +51,9 @@ public class TestRaceLogRemovalInRegatta extends AbstractTestStoringAndRetrievin Fleet blueFleet = qualification.getFleetByName(blueFleetName); RaceLog yellowLog = qualification.getRaceColumnByName(raceColumnName).getRaceLog(yellowFleet); RaceLog blueLog = qualification.getRaceColumnByName(raceColumnName).getRaceLog(blueFleet); - RaceLogProtestStartTimeEvent expectedEventYellow = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogProtestStartTimeEvent expectedEventYellow = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); yellowLog.add(expectedEventYellow); - RaceLogStartTimeEvent expectedEventBlue = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogStartTimeEvent expectedEventBlue = new RaceLogStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); blueLog.add(expectedEventBlue); // these events are now expected to be stored persistently in the race log store //getLastError() is now deprecated - seems to run fine without (at least locally) diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java index 9db1f518d68..6bbb0174268 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndLoadingEventsAndRegattas.java @@ -1,836 +1,836 @@ -package com.sap.sailing.mongodb.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.UUID; -import java.util.logging.Logger; - -import org.junit.Test; - -import com.mongodb.MongoException; -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.Course; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnInSeries; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.Venue; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.EventImpl; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; -import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.SeriesImpl; -import com.sap.sailing.domain.base.impl.VenueImpl; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.RankingMetrics; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.leaderboard.EventResolver; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.LeaderboardGroupResolver; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; -import com.sap.sailing.domain.leaderboard.impl.HighPoint; -import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; -import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.persistence.DomainObjectFactory; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.persistence.impl.CollectionNames; -import com.sap.sailing.domain.persistence.media.MediaDBFactory; -import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; -import com.sap.sailing.domain.ranking.OneDesignRankingMetric; -import com.sap.sailing.domain.ranking.RankingMetricConstructor; -import com.sap.sailing.domain.ranking.TimeOnTimeAndDistanceRankingMetric; -import com.sap.sailing.domain.test.AbstractLeaderboardTest; -import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; -import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; -import com.sap.sailing.domain.tracking.impl.EmptyWindStore; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardMaxPointsReason; -import com.sap.sse.common.Color; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; -import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; - -public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest { - private static final Logger logger = Logger.getLogger(TestStoringAndLoadingEventsAndRegattas.class.getName()); - - private final TimePoint eventStartDate; - private final TimePoint eventEndDate; - private final TimePoint regattaStartDate; - private final TimePoint regattaEndDate; - - public TestStoringAndLoadingEventsAndRegattas() throws UnknownHostException, MongoException { - super(); - - Calendar cal = Calendar.getInstance(); - - cal.set(2012, 12, 1); - eventStartDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - cal.set(2012, 12, 5); - eventEndDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - - cal.set(2012, 12, 2); - regattaStartDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - cal.set(2012, 12, 3); - regattaEndDate = new MillisecondsTimePoint(cal.getTimeInMillis()); - } - - private LeaderboardGroup createLeaderboardGroup(String name) { - return new LeaderboardGroupImpl(name, "Description for "+name, /* displayName */ null, /* displayInReverseOrder */ false, Collections.emptyList()); - } - - @Test - public void testLoadStoreSimpleEventWithLinkToLeaderboardGroups() throws MalformedURLException { - final String eventName = "Event Name"; - final String eventDescription = "Event Description"; - final String venueName = "Venue Name"; - final String[] courseAreaNames = new String[] { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrott" }; - final URL officialWebsiteURL = new URL("http://official.website.com"); - final URL sailorsInfoWebsiteURL = new URL("http://sailorsinfo.website.com"); - final Venue venue = new VenueImpl(venueName); - - for (String courseAreaName : courseAreaNames) { - CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); - venue.addCourseArea(courseArea); - } - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - final Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); - final LeaderboardGroup lg1 = createLeaderboardGroup("lg1"); - final LeaderboardGroup lg2 = createLeaderboardGroup("lg2"); - event.addLeaderboardGroup(lg1); - event.addLeaderboardGroup(lg2); - event.setDescription(eventDescription); - event.setOfficialWebsiteURL(officialWebsiteURL); - event.setSailorsInfoWebsiteURL(sailorsInfoWebsiteURL); - mof.storeEvent(event); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - final Event loadedEvent = dof.loadEvent(eventName); - dof.loadLeaderboardGroupLinksForEvents(new EventResolver() { - @Override - public Event getEvent(Serializable id) { - return id.equals(loadedEvent.getId()) ? loadedEvent : null; - } - }, new LeaderboardGroupResolver() { - @Override - public LeaderboardGroup getLeaderboardGroupByName(String leaderboardGroupName) { - return leaderboardGroupName.equals(lg1.getName()) ? lg1 : leaderboardGroupName.equals(lg2.getName()) ? lg2 : null; - } - - @Override - public LeaderboardGroup getLeaderboardGroupByID(UUID leaderboardGroupID) { - return leaderboardGroupID.equals(lg1.getId()) ? lg1 : leaderboardGroupID.equals(lg2.getId()) ? lg2 : null; - } - }); - assertNotNull(loadedEvent); - assertEquals(eventName, loadedEvent.getName()); - assertEquals(eventDescription, loadedEvent.getDescription()); - assertEquals(event.getOfficialWebsiteURL(), loadedEvent.getOfficialWebsiteURL()); - assertEquals(event.getSailorsInfoWebsiteURL(), loadedEvent.getSailorsInfoWebsiteURL()); - assertEquals(2, Util.size(loadedEvent.getLeaderboardGroups())); - Iterator lgIter = loadedEvent.getLeaderboardGroups().iterator(); - assertSame(lg1, lgIter.next()); - assertSame(lg2, lgIter.next()); - final Venue loadedVenue = loadedEvent.getVenue(); - assertNotNull(loadedVenue); - assertEquals(venueName, loadedVenue.getName()); - assertEquals(courseAreaNames.length, Util.size(loadedVenue.getCourseAreas())); - int i=0; - for (CourseArea loadedCourseArea : loadedVenue.getCourseAreas()) { - assertEquals(courseAreaNames[i++], loadedCourseArea.getName()); - } - } - - @Test - public void testLoadStoreSimpleEventAndRegattaWithCourseArea() { - final String eventName = "Event Name"; - final String venueName = "Venue Name"; - final String courseAreaName = "Alpha"; - final Venue venue = new VenueImpl(venueName); - CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); - venue.addCourseArea(courseArea); - - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); - mof.storeEvent(event); - - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Regatta regatta = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), courseArea, OneDesignRankingMetric::new); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertNotNull(loadedRegatta); - assertEquals(regatta.getName(), loadedRegatta.getName()); - assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); - assertNotNull(loadedRegatta.getDefaultCourseArea()); - assertEquals(loadedRegatta.getDefaultCourseArea().getId(), courseArea.getId()); - assertEquals(loadedRegatta.getDefaultCourseArea().getName(), courseArea.getName()); - assertEquals(loadedRegatta.getStartDate(), regattaStartDate); - assertEquals(loadedRegatta.getEndDate(), regattaEndDate); - } - - @Test - public void testLoadStoreSimpleEventWithImages() throws MalformedURLException { - final URL imageURL = new URL("http://some.host/with/some/file2.jpg"); - final String copyright = "copyright by Alex"; - final String imageTitle = "My image title"; - final String imageSubtitle = "My image subtitle"; - final Integer imageWidth = 500; - final Integer imageHeight = 300; - final TimePoint createdAt = MillisecondsTimePoint.now(); - final String eventName = "Event Name"; - final String venueName = "Venue Name"; - final String courseAreaName = "Alpha"; - final Venue venue = new VenueImpl(venueName); - CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); - venue.addCourseArea(courseArea); - - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); - - ImageDescriptor image1 = new ImageDescriptorImpl(imageURL, createdAt); - image1.setCopyright(copyright); - image1.setSize(imageWidth, imageHeight); - image1.setTitle(imageTitle); - image1.setSubtitle(imageSubtitle); - image1.addTag("Tag1"); - image1.addTag("Tag2"); - image1.addTag("Tag3"); - event.addImage(image1); - - ImageDescriptor image2 = new ImageDescriptorImpl(new URL("http://some.host/with/some/file2.jpg"), MillisecondsTimePoint.now()); - image2.setCopyright("copyright"); - event.addImage(image2); - - mof.storeEvent(event); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - final Event loadedEvent = dof.loadEvent(eventName); - assertEquals(2, Util.size(loadedEvent.getImages())); - ImageDescriptor loadedImage1 = loadedEvent.getImages().iterator().next(); - assertNotNull(loadedImage1); - assertEquals(imageURL, loadedImage1.getURL()); - assertEquals(copyright, loadedImage1.getCopyright()); - assertEquals(copyright, loadedImage1.getCopyright()); - assertEquals(imageTitle, loadedImage1.getTitle()); - assertEquals(imageSubtitle, loadedImage1.getSubtitle()); - assertEquals(createdAt, loadedImage1.getCreatedAtDate()); - assertEquals(imageWidth, loadedImage1.getWidthInPx()); - assertEquals(imageHeight, loadedImage1.getHeightInPx()); - assertEquals(3, Util.size(loadedImage1.getTags())); - } - - @Test - public void testLoadStoreSimpleEventWithVideos() throws MalformedURLException { - final URL videoURL = new URL("http://some.host/with/some/video.mpg"); - final URL videoThumbnailURL = new URL("http://some.host/with/some/video_thumbnail.jpg"); - final Locale locale = Locale.GERMAN; - final Integer videoLengthInSeconds = 2 * 60 * 60 * 1000; // 2h - final MimeType mimeType = MimeType.mp4; - final String copyright = "copyright by Don"; - final String videoTitle = "My video title"; - final String videoSubtitle = "My video subtitle"; - final TimePoint createdAt = MillisecondsTimePoint.now(); - final String eventName = "Event Name"; - final String venueName = "Venue Name"; - final String courseAreaName = "Alpha"; - final Venue venue = new VenueImpl(venueName); - CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); - venue.addCourseArea(courseArea); - - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); - - VideoDescriptor video1 = new VideoDescriptorImpl(videoURL, mimeType, createdAt); - video1.setCopyright(copyright); - video1.setTitle(videoTitle); - video1.setLocale(locale); - video1.setSubtitle(videoSubtitle); - video1.setThumbnailURL(videoThumbnailURL); - video1.setLengthInSeconds(videoLengthInSeconds); - video1.addTag("Tag1"); - video1.addTag("Tag2"); - video1.addTag("Tag3"); - event.addVideo(video1); - - VideoDescriptor video2 = new VideoDescriptorImpl(new URL("http://some.host/with/some/file2.ogg"), MimeType.ogg, MillisecondsTimePoint.now()); - video2.setCopyright("copyright"); - event.addVideo(video2); - - mof.storeEvent(event); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - final Event loadedEvent = dof.loadEvent(eventName); - assertEquals(2, Util.size(loadedEvent.getVideos())); - VideoDescriptor loadedVideo1 = loadedEvent.getVideos().iterator().next(); - assertNotNull(loadedVideo1); - assertEquals(videoURL, loadedVideo1.getURL()); - assertEquals(videoThumbnailURL, loadedVideo1.getThumbnailURL()); - assertEquals(videoLengthInSeconds, loadedVideo1.getLengthInSeconds()); - assertEquals(copyright, loadedVideo1.getCopyright()); - assertEquals(locale, loadedVideo1.getLocale()); - assertEquals(videoTitle, loadedVideo1.getTitle()); - assertEquals(videoSubtitle, loadedVideo1.getSubtitle()); - assertEquals(createdAt, loadedVideo1.getCreatedAtDate()); - assertEquals(3, Util.size(loadedVideo1.getTags())); - } - - @SuppressWarnings("deprecation") - @Test - /** - * We expected that the migration code creates also an image URL for each image we create. - * Images with the 'Sponsor' tag should create a corresponding sponsor image URL - * Videos should create a video URL. - */ - public void testLoadStoreSimpleEventWithImageAndVideoURLMigration() throws MalformedURLException { - final URL imageURL = new URL("http://some.host/with/some/bla.jpg"); - final URL sponsorImageURL = new URL("http://some.host/with/some/sponsor.jpg"); - final URL videoURL = new URL("http://some.host/with/some/video.mpg"); - final TimePoint createdAt = MillisecondsTimePoint.now(); - final String eventName = "Event Name"; - final Venue venue = new VenueImpl("My Venue"); - CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), "Alfa"); - venue.addCourseArea(courseArea); - - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); - - ImageDescriptor image1 = new ImageDescriptorImpl(imageURL, createdAt); - image1.addTag(MediaTagConstants.GALLERY); - event.addImage(image1); - - ImageDescriptor image2 = new ImageDescriptorImpl(sponsorImageURL, createdAt); - event.addImage(image2); - image2.addTag(MediaTagConstants.SPONSOR); - - VideoDescriptor video1 = new VideoDescriptorImpl(videoURL, MimeType.mp4, createdAt); - event.addVideo(video1); - - mof.storeEvent(event); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - final Event loadedEvent = dof.loadEvent(eventName); - assertEquals(2, Util.size(loadedEvent.getImages())); - assertEquals(1, Util.size(loadedEvent.getVideos())); - assertEquals(1, Util.size(loadedEvent.getImageURLs())); - assertEquals(1, Util.size(loadedEvent.getSponsorImageURLs())); - assertEquals(1, Util.size(loadedEvent.getVideoURLs())); - } - - - @Test - public void testLoadStoreRegattaConfiguration() { - - RegattaConfigurationImpl configuration = new RegattaConfigurationImpl(); - configuration.setDefaultRacingProcedureType(RacingProcedureType.BASIC); - - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", false); - Regatta regatta = createRegattaAndAddRaceColumns(1, 1, RegattaImpl.getDefaultName("RR", boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT), OneDesignRankingMetric::new); - regatta.setRegattaConfiguration(configuration); - - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), null); - - assertNotNull(loadedRegatta.getRegattaConfiguration()); - assertEquals(RacingProcedureType.BASIC, loadedRegatta.getRegattaConfiguration().getDefaultRacingProcedureType()); - } - - @Test - public void testLoadStoreSimpleRegattaLeaderboard() { - RacingEventService res = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - final String regattaName = regattaProxy.getName(); - Regatta regatta = res.createRegatta(regattaName, regattaProxy.getBoatClass().getName(), regattaStartDate, regattaEndDate, - "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); - addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); - res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertNotNull(loadedRegatta); - assertEquals(regatta.getName(), loadedRegatta.getName()); - assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); - - Leaderboard loadedLeaderboard = dof.loadLeaderboard(regatta.getName(), res); - assertNotNull(loadedLeaderboard); - assertTrue(loadedLeaderboard instanceof RegattaLeaderboard); - RegattaLeaderboard loadedRegattaLeaderboard = (RegattaLeaderboard) loadedLeaderboard; - assertSame(regatta, loadedRegattaLeaderboard.getRegatta()); - } - - @Test - public void testLoadStoreRegattaLeaderboardWithScoreCorrections() { - // for some reason the dropping of collections doesn't work reliably on Linux... explicitly drop those collections that we depend on - getMongoService().getDB().getCollection(CollectionNames.LEADERBOARDS.name()).drop(); - getMongoService().getDB().getCollection(CollectionNames.REGATTAS.name()).drop(); - Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - final DynamicTrackedRegatta[] trackedRegatta = new DynamicTrackedRegatta[1]; - final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { - private static final long serialVersionUID = 1234L; - @Override - public RegattaAndRaceIdentifier getRaceIdentifier() { - return new RegattaNameAndRaceName("Kieler Woche (29ERXX)", "Yellow Race 2"); - } - @Override - public DynamicTrackedRegatta getTrackedRegatta() { - return trackedRegatta[0]; - } - }; - RacingEventService res = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace); - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - - Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - Regatta regatta = res.createRegatta(regattaProxy.getName(), regattaProxy.getBoatClass().getName(), regattaProxy.getStartDate(), regattaProxy.getEndDate(), - "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); - trackedRegatta[0] = new DynamicTrackedRegattaImpl(regatta); - addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); - logColumnsInRegatta(regatta); - RegattaLeaderboard regattaLeaderboard = res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); - assertSame(regatta, regattaLeaderboard.getRegatta()); - final RaceColumnInSeries q2 = regatta.getSeriesByName("Qualifying").getRaceColumnByName("Q2"); - final Fleet yellow = q2.getFleetByName("Yellow"); - logColumnsInRegatta(regatta); - logColumnsInRegattaLeaderboard(regattaLeaderboard); - assertNotNull(regattaLeaderboard.getRaceColumnByName(q2.getName())); - res.apply(new ConnectTrackedRaceToLeaderboardColumn(regattaLeaderboard.getName(), q2.getName(), yellow - .getName(), q2YellowTrackedRace.getRaceIdentifier())); - res.apply(new UpdateLeaderboardMaxPointsReason(regattaLeaderboard.getName(), q2.getName(), hasso.getId().toString(), - MaxPointsReason.DNF, MillisecondsTimePoint.now())); - - // load new RacingEventService including regatta and leaderboard - RacingEventService resForLoading = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace); - Regatta loadedRegatta = resForLoading.getRegattaByName("Kieler Woche (29ERXX)"); - assertNotNull(loadedRegatta); - assertEquals(regatta.getName(), loadedRegatta.getName()); - assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); - Leaderboard loadedLeaderboard = resForLoading.getLeaderboardByName(loadedRegatta.getName()); - assertNotNull(loadedLeaderboard); - assertEquals(((ThresholdBasedResultDiscardingRule) regattaLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces().length, - ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces().length); - assertTrue(Arrays.equals(((ThresholdBasedResultDiscardingRule) regattaLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(), - ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces())); - assertTrue(loadedLeaderboard instanceof RegattaLeaderboard); - RegattaLeaderboard loadedRegattaLeaderboard = (RegattaLeaderboard) loadedLeaderboard; - assertSame(loadedRegatta, loadedRegattaLeaderboard.getRegatta()); - // now re-associate the tracked race to let score correction "snap" to competitor: - final RaceColumnInSeries loadedQ2 = loadedRegatta.getSeriesByName("Qualifying").getRaceColumnByName("Q2"); - final Fleet loadedYellow = loadedQ2.getFleetByName("Yellow"); - // adjust tracked regatta for tracked race: - trackedRegatta[0] = new DynamicTrackedRegattaImpl(loadedRegatta); - resForLoading.apply(new ConnectTrackedRaceToLeaderboardColumn(loadedLeaderboard.getName(), loadedQ2.getName(), loadedYellow - .getName(), q2YellowTrackedRace.getRaceIdentifier())); - MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso, loadedQ2, MillisecondsTimePoint.now()); - assertEquals(MaxPointsReason.DNF, hassosLoadedMaxPointsReason); - } - - private void logColumnsInRegattaLeaderboard(RegattaLeaderboard regattaLeaderboard) { - StringBuilder rlbrcNames = new StringBuilder(); - for (RaceColumn rlbrc : regattaLeaderboard.getRaceColumns()) { - rlbrcNames.append("; "); - rlbrcNames.append(rlbrc.getName()); - } - logger.info("columns in regatta leaderboard for regatta "+regattaLeaderboard.getRegatta().getName()+" ("+ - regattaLeaderboard.getRegatta().hashCode()+"): "+rlbrcNames); - logColumnsInRegatta(regattaLeaderboard.getRegatta()); - } - - private void logColumnsInRegatta(Regatta regatta) { - StringBuilder rrcNames = new StringBuilder(); - for (Series series : regatta.getSeries()) { - for (RaceColumn raceColumn : series.getRaceColumns()) { - rrcNames.append("; "); - rrcNames.append(raceColumn.getName()); - } - } - logger.info("columns in regatta "+regatta.getName()+" ("+regatta.hashCode()+") : "+rrcNames); - } - - private RacingEventServiceImpl createRacingEventServiceWithOneMockedTrackedRace(final DynamicTrackedRace q2YellowTrackedRace) { - return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE) { - @Override - public DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { - return q2YellowTrackedRace; - } - }; - } - - @Test - public void testLoadStoreSimpleRegatta() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); - final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, - boatClass, regattaStartDate, regattaEndDate, /* persistent */false, - DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertSame(LowPoint.class, loadedRegatta.getScoringScheme().getClass()); - assertEquals(regattaName, loadedRegatta.getName()); - Iterator seriesIter = loadedRegatta.getSeries().iterator(); - Series loadedQualifyingSeries = seriesIter.next(); - assertEquals(numberOfQualifyingRaces, Util.size(loadedQualifyingSeries.getRaceColumns())); - assertEquals(0, loadedQualifyingSeries.getFleetByName("Yellow").compareTo(loadedQualifyingSeries.getFleetByName("Blue"))); - Series loadedFinalSeries = seriesIter.next(); - assertEquals(numberOfFinalRaces, Util.size(loadedFinalSeries.getRaceColumns())); - assertTrue(loadedFinalSeries.getFleetByName("Silver").compareTo(loadedFinalSeries.getFleetByName("Gold")) > 0); - Series loadedMedalSeries = seriesIter.next(); - assertEquals(1, Util.size(loadedMedalSeries.getRaceColumns())); - assertEquals(loadedRegatta.getStartDate(), regattaStartDate); - assertEquals(loadedRegatta.getEndDate(), regattaEndDate); - assertEquals(RankingMetrics.ONE_DESIGN, loadedRegatta.getRankingMetricType()); - } - - @Test - public void testLoadStoreRegattaWithHandicapRanking() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); - final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, - boatClass, regattaStartDate, regattaEndDate, /* persistent */false, - DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), TimeOnTimeAndDistanceRankingMetric::new); - assertEquals(RankingMetrics.TIME_ON_TIME_AND_DISTANCE, regatta.getRankingMetricType()); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertSame(LowPoint.class, loadedRegatta.getScoringScheme().getClass()); - assertEquals(regattaName, loadedRegatta.getName()); - Iterator seriesIter = loadedRegatta.getSeries().iterator(); - Series loadedQualifyingSeries = seriesIter.next(); - assertEquals(numberOfQualifyingRaces, Util.size(loadedQualifyingSeries.getRaceColumns())); - assertEquals(0, loadedQualifyingSeries.getFleetByName("Yellow").compareTo(loadedQualifyingSeries.getFleetByName("Blue"))); - Series loadedFinalSeries = seriesIter.next(); - assertEquals(numberOfFinalRaces, Util.size(loadedFinalSeries.getRaceColumns())); - assertTrue(loadedFinalSeries.getFleetByName("Silver").compareTo(loadedFinalSeries.getFleetByName("Gold")) > 0); - Series loadedMedalSeries = seriesIter.next(); - assertEquals(1, Util.size(loadedMedalSeries.getRaceColumns())); - assertEquals(loadedRegatta.getStartDate(), regattaStartDate); - assertEquals(loadedRegatta.getEndDate(), regattaEndDate); - assertEquals(RankingMetrics.TIME_ON_TIME_AND_DISTANCE, loadedRegatta.getRankingMetricType()); - } - - @Test - public void testLoadStoreSimpleRegattaWithEmptyStartAndEndDate() { - final int numberOfQualifyingRaces = 1; - final int numberOfFinalRaces = 1; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); - final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, - boatClass, null, null, /* persistent */false, - DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertEquals(regattaName, loadedRegatta.getName()); - assertEquals(loadedRegatta.getStartDate(), null); - assertEquals(loadedRegatta.getEndDate(), null); - } - - @Test - public void testLoadStoreSimpleRegattaWithSeriesScoringScheme() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), - boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - regatta.getSeriesByName("Qualifying").setResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(new int[] { 1, 2, 3 })); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertTrue(Arrays.equals(new int[] { 1, 2, 3 }, - loadedRegatta.getSeriesByName("Qualifying").getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces())); - } - - @Test - public void testLoadStoreSimpleRegattaWithScoreForMedalStartingWithZero() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), - boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - regatta.getSeriesByName("Medal").setStartsWithZeroScore(true); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertFalse(loadedRegatta.getSeriesByName("Qualifying").isStartsWithZeroScore()); - assertTrue(loadedRegatta.getSeriesByName("Medal").isStartsWithZeroScore()); - } - - @Test - public void testLoadStoreSimpleRegattaWithHighPointScoringScheme() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "ESS40 Cardiff 2012"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", /* typicallyStartsUpwind */ false); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), - boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT), OneDesignRankingMetric::new); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertSame(HighPoint.class, loadedRegatta.getScoringScheme().getClass()); - } - - @Test - public void testLoadStoreRegattaWithFleetsEnsuringIdenticalFleetsInSeriesAndRaceColumns() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, - regattaName, boatClass, regattaStartDate, regattaEndDate, - /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertEquals(regattaName, loadedRegatta.getName()); - Iterator seriesIter = loadedRegatta.getSeries().iterator(); - Series loadedQualifyingSeries = seriesIter.next(); - int i=1; - for (RaceColumn raceColumn : loadedQualifyingSeries.getRaceColumns()) { - assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); - assertEquals("Q"+i, raceColumn.getName()); - assertTrue(Util.equals(loadedQualifyingSeries.getFleets(), raceColumn.getFleets())); - i++; - } - Series loadedFinalSeries = seriesIter.next(); - i=1; - for (RaceColumn raceColumn : loadedFinalSeries.getRaceColumns()) { - assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); - assertEquals("F"+i, raceColumn.getName()); - assertTrue(Util.equals(loadedFinalSeries.getFleets(), raceColumn.getFleets())); - i++; - } - Series loadedMedalSeries = seriesIter.next(); - for (RaceColumn raceColumn : loadedMedalSeries.getRaceColumns()) { - assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); - assertEquals("M", raceColumn.getName()); - assertTrue(Util.equals(loadedMedalSeries.getFleets(), raceColumn.getFleets())); - } - } - - @Test - public void testLoadStoreRegattaWithFleetsEnsuringFleetOrdering() { - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); - Regatta regatta = createRegatta(regattaName, boatClass, regattaStartDate, regattaEndDate, - /* persistent */ false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - assertEquals(regattaName, loadedRegatta.getName()); - - Iterator seriesIter = loadedRegatta.getSeries().iterator(); - Series loadedQualifyingSeries = seriesIter.next(); - - Iterator qualiFleetIt = loadedQualifyingSeries.getFleets().iterator(); - Fleet qualiFleet1 = qualiFleetIt.next(); - assertEquals(qualiFleet1.getName(), "Yellow"); - Fleet qualiFleet2 = qualiFleetIt.next(); - assertEquals(qualiFleet2.getName(), "Blue"); - - Series loadedFinalSeries = seriesIter.next(); - Iterator finalFleetIt = loadedFinalSeries.getFleets().iterator(); - Fleet finalFleet1 = finalFleetIt.next(); - assertEquals(finalFleet1.getName(), "Gold"); - Fleet finalFleet2 = finalFleetIt.next(); - assertEquals(finalFleet2.getName(), "Silver"); - } - - @Test - public void testStorageOfRaceIdentifiersOnRaceColumnInSeries() { - final int numberOfQualifyingRaces = 5; - final int numberOfFinalRaces = 7; - final String regattaBaseName = "Kieler Woche"; - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); - Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, - RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, - /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); - Series qualifyingSeries = regatta.getSeries().iterator().next(); - RaceColumn q2 = qualifyingSeries.getRaceColumnByName("Q2"); - final RegattaNameAndRaceName q2TrackedRaceIdentifier = new RegattaNameAndRaceName(regatta.getName(), "Q2 TracTrac"); - q2.setRaceIdentifier(qualifyingSeries.getFleetByName("Yellow"), q2TrackedRaceIdentifier); - MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); - mof.storeRegatta(regatta); - - DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); - Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); - Series loadedQualifyingSeries = loadedRegatta.getSeries().iterator().next(); - RaceColumn loadedQ2 = loadedQualifyingSeries.getRaceColumnByName("Q2"); - RaceIdentifier loadedQ2TrackedRaceIdentifier = loadedQ2.getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow")); - assertEquals(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier); - assertNotSame(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier); - assertNull(loadedQualifyingSeries.getRaceColumnByName("Q1").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow"))); - assertNull(loadedQualifyingSeries.getRaceColumnByName("Q2").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Blue"))); - } - - private Regatta createRegattaAndAddRaceColumns(final int numberOfQualifyingRaces, final int numberOfFinalRaces, - final String regattaName, BoatClass boatClass, TimePoint startDate, TimePoint endDate, boolean persistent, - ScoringScheme scoringScheme, RankingMetricConstructor rankingMetricConstructor) { - Regatta regatta = createRegatta(regattaName, boatClass, startDate, endDate, persistent, scoringScheme, null, - rankingMetricConstructor); - addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); - return regatta; - } - - private void addRaceColumns(final int numberOfQualifyingRaces, final int numberOfFinalRaces, Regatta regatta) { - List finalRaceColumnNames = new ArrayList(); - for (int i=1; i<=numberOfFinalRaces; i++) { - finalRaceColumnNames.add("F"+i); - } - List qualifyingRaceColumnNames = new ArrayList(); - for (int i=1; i<=numberOfQualifyingRaces; i++) { - qualifyingRaceColumnNames.add("Q"+i); - } - List medalRaceColumnNames = new ArrayList(); - medalRaceColumnNames.add("M"); - addRaceColumnsToSeries(qualifyingRaceColumnNames, regatta.getSeriesByName("Qualifying")); - addRaceColumnsToSeries(finalRaceColumnNames, regatta.getSeriesByName("Final")); - addRaceColumnsToSeries(medalRaceColumnNames, regatta.getSeriesByName("Medal")); - } - - private Regatta createRegatta(final String regattaName, BoatClass boatClass, TimePoint startDate, - TimePoint endDate, boolean persistent, ScoringScheme scoringScheme, CourseArea courseArea, - RankingMetricConstructor rankingMetricConstructor) { - List emptyRaceColumnNames = Collections.emptyList(); - List series = new ArrayList(); - - // -------- qualifying series ------------ - List qualifyingFleets = new ArrayList(); - qualifyingFleets.add(new FleetImpl("Yellow")); - qualifyingFleets.add(new FleetImpl("Blue")); - Series qualifyingSeries = new SeriesImpl("Qualifying", /* isMedal */false, qualifyingFleets, - emptyRaceColumnNames, /* trackedRegattaRegistry */ null); - series.add(qualifyingSeries); - - // -------- final series ------------ - List finalFleets = new ArrayList(); - finalFleets.add(new FleetImpl("Gold", 1)); - finalFleets.add(new FleetImpl("Silver", 2)); - Series finalSeries = new SeriesImpl("Final", /* isMedal */ false, finalFleets, emptyRaceColumnNames, /* trackedRegattaRegistry */ null); - series.add(finalSeries); - - // ------------ medal -------------- - List medalFleets = new ArrayList(); - medalFleets.add(new FleetImpl("Medal")); - Series medalSeries = new SeriesImpl("Medal", /* isMedal */ true, medalFleets, emptyRaceColumnNames, /* trackedRegattaRegistry */ null); - series.add(medalSeries); - Regatta regatta = new RegattaImpl(regattaName, boatClass, startDate, endDate, series, persistent, scoringScheme, "123", courseArea, rankingMetricConstructor); - return regatta; - } - - private void addRaceColumnsToSeries(List finalRaceColumnNames, Series finalSeries) { - for (String raceColumnName : finalRaceColumnNames) { - finalSeries.addRaceColumn(raceColumnName, /* trackedRegattaRegistry */ null); - } - } - - @Test - public void testRegattaRaceAssociationStore() throws Exception { - BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("112er", /* typicallyStartsUpwind */ true); - Regatta regatta = createRegatta(RegattaImpl.getDefaultName("Cologne Masters", boatClass.getName()), boatClass, - regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); - - List competitors = new ArrayList(); - competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - Iterable waypoints = Collections.emptyList(); - Course course = new CourseImpl("Course", waypoints); - - RaceDefinition racedef = new RaceDefinitionImpl("M1", course, boatClass, competitors); - regatta.addRace(racedef); - - RacingEventServiceImpl evs = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE - .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - assertNull(evs.getRememberedRegattaForRace(racedef.getId())); - evs.raceAdded(regatta, racedef); - assertNotNull(evs.getRememberedRegattaForRace(racedef.getId())); - evs.removeRegatta(regatta); - assertNull(evs.getRememberedRegattaForRace(racedef.getId())); - } - -} +package com.sap.sailing.mongodb.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.UUID; +import java.util.logging.Logger; + +import org.junit.Test; + +import com.mongodb.MongoException; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.Course; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnInSeries; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.Venue; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.EventImpl; +import com.sap.sailing.domain.base.impl.FleetImpl; +import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl; +import com.sap.sailing.domain.base.impl.RaceDefinitionImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.SeriesImpl; +import com.sap.sailing.domain.base.impl.VenueImpl; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RankingMetrics; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.domain.leaderboard.EventResolver; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.LeaderboardGroupResolver; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.impl.HighPoint; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.LowPoint; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.impl.CollectionNames; +import com.sap.sailing.domain.persistence.media.MediaDBFactory; +import com.sap.sailing.domain.racelog.tracking.EmptyGPSFixStore; +import com.sap.sailing.domain.ranking.OneDesignRankingMetric; +import com.sap.sailing.domain.ranking.RankingMetricConstructor; +import com.sap.sailing.domain.ranking.TimeOnTimeAndDistanceRankingMetric; +import com.sap.sailing.domain.test.AbstractLeaderboardTest; +import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; +import com.sap.sailing.domain.tracking.impl.EmptyWindStore; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.impl.RacingEventServiceImpl; +import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardMaxPointsReason; +import com.sap.sse.common.Color; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.media.MediaTagConstants; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; + +public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest { + private static final Logger logger = Logger.getLogger(TestStoringAndLoadingEventsAndRegattas.class.getName()); + + private final TimePoint eventStartDate; + private final TimePoint eventEndDate; + private final TimePoint regattaStartDate; + private final TimePoint regattaEndDate; + + public TestStoringAndLoadingEventsAndRegattas() throws UnknownHostException, MongoException { + super(); + + Calendar cal = Calendar.getInstance(); + + cal.set(2012, 12, 1); + eventStartDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + cal.set(2012, 12, 5); + eventEndDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + + cal.set(2012, 12, 2); + regattaStartDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + cal.set(2012, 12, 3); + regattaEndDate = new MillisecondsTimePoint(cal.getTimeInMillis()); + } + + private LeaderboardGroup createLeaderboardGroup(String name) { + return new LeaderboardGroupImpl(name, "Description for "+name, /* displayName */ null, /* displayInReverseOrder */ false, Collections.emptyList()); + } + + @Test + public void testLoadStoreSimpleEventWithLinkToLeaderboardGroups() throws MalformedURLException { + final String eventName = "Event Name"; + final String eventDescription = "Event Description"; + final String venueName = "Venue Name"; + final String[] courseAreaNames = new String[] { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrott" }; + final URL officialWebsiteURL = new URL("http://official.website.com"); + final URL sailorsInfoWebsiteURL = new URL("http://sailorsinfo.website.com"); + final Venue venue = new VenueImpl(venueName); + + for (String courseAreaName : courseAreaNames) { + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); + venue.addCourseArea(courseArea); + } + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + final Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); + final LeaderboardGroup lg1 = createLeaderboardGroup("lg1"); + final LeaderboardGroup lg2 = createLeaderboardGroup("lg2"); + event.addLeaderboardGroup(lg1); + event.addLeaderboardGroup(lg2); + event.setDescription(eventDescription); + event.setOfficialWebsiteURL(officialWebsiteURL); + event.setSailorsInfoWebsiteURL(sailorsInfoWebsiteURL); + mof.storeEvent(event); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + final Event loadedEvent = dof.loadEvent(eventName); + dof.loadLeaderboardGroupLinksForEvents(new EventResolver() { + @Override + public Event getEvent(Serializable id) { + return id.equals(loadedEvent.getId()) ? loadedEvent : null; + } + }, new LeaderboardGroupResolver() { + @Override + public LeaderboardGroup getLeaderboardGroupByName(String leaderboardGroupName) { + return leaderboardGroupName.equals(lg1.getName()) ? lg1 : leaderboardGroupName.equals(lg2.getName()) ? lg2 : null; + } + + @Override + public LeaderboardGroup getLeaderboardGroupByID(UUID leaderboardGroupID) { + return leaderboardGroupID.equals(lg1.getId()) ? lg1 : leaderboardGroupID.equals(lg2.getId()) ? lg2 : null; + } + }); + assertNotNull(loadedEvent); + assertEquals(eventName, loadedEvent.getName()); + assertEquals(eventDescription, loadedEvent.getDescription()); + assertEquals(event.getOfficialWebsiteURL(), loadedEvent.getOfficialWebsiteURL()); + assertEquals(event.getSailorsInfoWebsiteURL(), loadedEvent.getSailorsInfoWebsiteURL()); + assertEquals(2, Util.size(loadedEvent.getLeaderboardGroups())); + Iterator lgIter = loadedEvent.getLeaderboardGroups().iterator(); + assertSame(lg1, lgIter.next()); + assertSame(lg2, lgIter.next()); + final Venue loadedVenue = loadedEvent.getVenue(); + assertNotNull(loadedVenue); + assertEquals(venueName, loadedVenue.getName()); + assertEquals(courseAreaNames.length, Util.size(loadedVenue.getCourseAreas())); + int i=0; + for (CourseArea loadedCourseArea : loadedVenue.getCourseAreas()) { + assertEquals(courseAreaNames[i++], loadedCourseArea.getName()); + } + } + + @Test + public void testLoadStoreSimpleEventAndRegattaWithCourseArea() { + final String eventName = "Event Name"; + final String venueName = "Venue Name"; + final String courseAreaName = "Alpha"; + final Venue venue = new VenueImpl(venueName); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); + venue.addCourseArea(courseArea); + + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); + mof.storeEvent(event); + + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + Regatta regatta = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, + regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), courseArea, OneDesignRankingMetric::new); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertNotNull(loadedRegatta); + assertEquals(regatta.getName(), loadedRegatta.getName()); + assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); + assertNotNull(loadedRegatta.getDefaultCourseArea()); + assertEquals(loadedRegatta.getDefaultCourseArea().getId(), courseArea.getId()); + assertEquals(loadedRegatta.getDefaultCourseArea().getName(), courseArea.getName()); + assertEquals(loadedRegatta.getStartDate(), regattaStartDate); + assertEquals(loadedRegatta.getEndDate(), regattaEndDate); + } + + @Test + public void testLoadStoreSimpleEventWithImages() throws MalformedURLException { + final URL imageURL = new URL("http://some.host/with/some/file2.jpg"); + final String copyright = "copyright by Alex"; + final String imageTitle = "My image title"; + final String imageSubtitle = "My image subtitle"; + final Integer imageWidth = 500; + final Integer imageHeight = 300; + final TimePoint createdAt = MillisecondsTimePoint.now(); + final String eventName = "Event Name"; + final String venueName = "Venue Name"; + final String courseAreaName = "Alpha"; + final Venue venue = new VenueImpl(venueName); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); + venue.addCourseArea(courseArea); + + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); + + ImageDescriptor image1 = new ImageDescriptorImpl(imageURL, createdAt); + image1.setCopyright(copyright); + image1.setSize(imageWidth, imageHeight); + image1.setTitle(imageTitle); + image1.setSubtitle(imageSubtitle); + image1.addTag("Tag1"); + image1.addTag("Tag2"); + image1.addTag("Tag3"); + event.addImage(image1); + + ImageDescriptor image2 = new ImageDescriptorImpl(new URL("http://some.host/with/some/file2.jpg"), MillisecondsTimePoint.now()); + image2.setCopyright("copyright"); + event.addImage(image2); + + mof.storeEvent(event); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + final Event loadedEvent = dof.loadEvent(eventName); + assertEquals(2, Util.size(loadedEvent.getImages())); + ImageDescriptor loadedImage1 = loadedEvent.getImages().iterator().next(); + assertNotNull(loadedImage1); + assertEquals(imageURL, loadedImage1.getURL()); + assertEquals(copyright, loadedImage1.getCopyright()); + assertEquals(copyright, loadedImage1.getCopyright()); + assertEquals(imageTitle, loadedImage1.getTitle()); + assertEquals(imageSubtitle, loadedImage1.getSubtitle()); + assertEquals(createdAt, loadedImage1.getCreatedAtDate()); + assertEquals(imageWidth, loadedImage1.getWidthInPx()); + assertEquals(imageHeight, loadedImage1.getHeightInPx()); + assertEquals(3, Util.size(loadedImage1.getTags())); + } + + @Test + public void testLoadStoreSimpleEventWithVideos() throws MalformedURLException { + final URL videoURL = new URL("http://some.host/with/some/video.mpg"); + final URL videoThumbnailURL = new URL("http://some.host/with/some/video_thumbnail.jpg"); + final Locale locale = Locale.GERMAN; + final Integer videoLengthInSeconds = 2 * 60 * 60 * 1000; // 2h + final MimeType mimeType = MimeType.mp4; + final String copyright = "copyright by Don"; + final String videoTitle = "My video title"; + final String videoSubtitle = "My video subtitle"; + final TimePoint createdAt = MillisecondsTimePoint.now(); + final String eventName = "Event Name"; + final String venueName = "Venue Name"; + final String courseAreaName = "Alpha"; + final Venue venue = new VenueImpl(venueName); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), courseAreaName); + venue.addCourseArea(courseArea); + + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); + + VideoDescriptor video1 = new VideoDescriptorImpl(videoURL, mimeType, createdAt); + video1.setCopyright(copyright); + video1.setTitle(videoTitle); + video1.setLocale(locale); + video1.setSubtitle(videoSubtitle); + video1.setThumbnailURL(videoThumbnailURL); + video1.setLengthInSeconds(videoLengthInSeconds); + video1.addTag("Tag1"); + video1.addTag("Tag2"); + video1.addTag("Tag3"); + event.addVideo(video1); + + VideoDescriptor video2 = new VideoDescriptorImpl(new URL("http://some.host/with/some/file2.ogg"), MimeType.ogg, MillisecondsTimePoint.now()); + video2.setCopyright("copyright"); + event.addVideo(video2); + + mof.storeEvent(event); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + final Event loadedEvent = dof.loadEvent(eventName); + assertEquals(2, Util.size(loadedEvent.getVideos())); + VideoDescriptor loadedVideo1 = loadedEvent.getVideos().iterator().next(); + assertNotNull(loadedVideo1); + assertEquals(videoURL, loadedVideo1.getURL()); + assertEquals(videoThumbnailURL, loadedVideo1.getThumbnailURL()); + assertEquals(videoLengthInSeconds, loadedVideo1.getLengthInSeconds()); + assertEquals(copyright, loadedVideo1.getCopyright()); + assertEquals(locale, loadedVideo1.getLocale()); + assertEquals(videoTitle, loadedVideo1.getTitle()); + assertEquals(videoSubtitle, loadedVideo1.getSubtitle()); + assertEquals(createdAt, loadedVideo1.getCreatedAtDate()); + assertEquals(3, Util.size(loadedVideo1.getTags())); + } + + @SuppressWarnings("deprecation") + @Test + /** + * We expected that the migration code creates also an image URL for each image we create. + * Images with the 'Sponsor' tag should create a corresponding sponsor image URL + * Videos should create a video URL. + */ + public void testLoadStoreSimpleEventWithImageAndVideoURLMigration() throws MalformedURLException { + final URL imageURL = new URL("http://some.host/with/some/bla.jpg"); + final URL sponsorImageURL = new URL("http://some.host/with/some/sponsor.jpg"); + final URL videoURL = new URL("http://some.host/with/some/video.mpg"); + final TimePoint createdAt = MillisecondsTimePoint.now(); + final String eventName = "Event Name"; + final Venue venue = new VenueImpl("My Venue"); + CourseArea courseArea = DomainFactory.INSTANCE.getOrCreateCourseArea(UUID.randomUUID(), "Alfa"); + venue.addCourseArea(courseArea); + + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + Event event = new EventImpl(eventName, eventStartDate, eventEndDate, venue, /*isPublic*/ true, UUID.randomUUID()); + + ImageDescriptor image1 = new ImageDescriptorImpl(imageURL, createdAt); + image1.addTag(MediaTagConstants.GALLERY); + event.addImage(image1); + + ImageDescriptor image2 = new ImageDescriptorImpl(sponsorImageURL, createdAt); + event.addImage(image2); + image2.addTag(MediaTagConstants.SPONSOR); + + VideoDescriptor video1 = new VideoDescriptorImpl(videoURL, MimeType.mp4, createdAt); + event.addVideo(video1); + + mof.storeEvent(event); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + final Event loadedEvent = dof.loadEvent(eventName); + assertEquals(2, Util.size(loadedEvent.getImages())); + assertEquals(1, Util.size(loadedEvent.getVideos())); + assertEquals(1, Util.size(loadedEvent.getImageURLs())); + assertEquals(1, Util.size(loadedEvent.getSponsorImageURLs())); + assertEquals(1, Util.size(loadedEvent.getVideoURLs())); + } + + + @Test + public void testLoadStoreRegattaConfiguration() { + + RegattaConfigurationImpl configuration = new RegattaConfigurationImpl(); + configuration.setDefaultRacingProcedureType(RacingProcedureType.BASIC); + + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", false); + Regatta regatta = createRegattaAndAddRaceColumns(1, 1, RegattaImpl.getDefaultName("RR", boatClass.getName()), boatClass, + regattaStartDate, regattaEndDate, false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT), OneDesignRankingMetric::new); + regatta.setRegattaConfiguration(configuration); + + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), null); + + assertNotNull(loadedRegatta.getRegattaConfiguration()); + assertEquals(RacingProcedureType.BASIC, loadedRegatta.getRegattaConfiguration().getDefaultRacingProcedureType()); + } + + @Test + public void testLoadStoreSimpleRegattaLeaderboard() { + RacingEventService res = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, + regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + final String regattaName = regattaProxy.getName(); + Regatta regatta = res.createRegatta(regattaName, regattaProxy.getBoatClass().getName(), regattaStartDate, regattaEndDate, + "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); + res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertNotNull(loadedRegatta); + assertEquals(regatta.getName(), loadedRegatta.getName()); + assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); + + Leaderboard loadedLeaderboard = dof.loadLeaderboard(regatta.getName(), res); + assertNotNull(loadedLeaderboard); + assertTrue(loadedLeaderboard instanceof RegattaLeaderboard); + RegattaLeaderboard loadedRegattaLeaderboard = (RegattaLeaderboard) loadedLeaderboard; + assertSame(regatta, loadedRegattaLeaderboard.getRegatta()); + } + + @Test + public void testLoadStoreRegattaLeaderboardWithScoreCorrections() { + // for some reason the dropping of collections doesn't work reliably on Linux... explicitly drop those collections that we depend on + getMongoService().getDB().getCollection(CollectionNames.LEADERBOARDS.name()).drop(); + getMongoService().getDB().getCollection(CollectionNames.REGATTAS.name()).drop(); + Competitor hasso = AbstractLeaderboardTest.createCompetitor("Dr. Hasso Plattner"); + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + final DynamicTrackedRegatta[] trackedRegatta = new DynamicTrackedRegatta[1]; + final DynamicTrackedRace q2YellowTrackedRace = new MockedTrackedRaceWithFixedRank(hasso, /* rank */ 1, /* started */ false, boatClass) { + private static final long serialVersionUID = 1234L; + @Override + public RegattaAndRaceIdentifier getRaceIdentifier() { + return new RegattaNameAndRaceName("Kieler Woche (29ERXX)", "Yellow Race 2"); + } + @Override + public DynamicTrackedRegatta getTrackedRegatta() { + return trackedRegatta[0]; + } + }; + RacingEventService res = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace); + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + + Regatta regattaProxy = createRegatta(RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + Regatta regatta = res.createRegatta(regattaProxy.getName(), regattaProxy.getBoatClass().getName(), regattaProxy.getStartDate(), regattaProxy.getEndDate(), + "123", regattaProxy.getSeries(), regattaProxy.isPersistent(), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + trackedRegatta[0] = new DynamicTrackedRegattaImpl(regatta); + addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); + logColumnsInRegatta(regatta); + RegattaLeaderboard regattaLeaderboard = res.addRegattaLeaderboard(regatta.getRegattaIdentifier(), null, new int[] { 3, 5 }); + assertSame(regatta, regattaLeaderboard.getRegatta()); + final RaceColumnInSeries q2 = regatta.getSeriesByName("Qualifying").getRaceColumnByName("Q2"); + final Fleet yellow = q2.getFleetByName("Yellow"); + logColumnsInRegatta(regatta); + logColumnsInRegattaLeaderboard(regattaLeaderboard); + assertNotNull(regattaLeaderboard.getRaceColumnByName(q2.getName())); + res.apply(new ConnectTrackedRaceToLeaderboardColumn(regattaLeaderboard.getName(), q2.getName(), yellow + .getName(), q2YellowTrackedRace.getRaceIdentifier())); + res.apply(new UpdateLeaderboardMaxPointsReason(regattaLeaderboard.getName(), q2.getName(), hasso.getId().toString(), + MaxPointsReason.DNF, MillisecondsTimePoint.now())); + + // load new RacingEventService including regatta and leaderboard + RacingEventService resForLoading = createRacingEventServiceWithOneMockedTrackedRace(q2YellowTrackedRace); + Regatta loadedRegatta = resForLoading.getRegattaByName("Kieler Woche (29ERXX)"); + assertNotNull(loadedRegatta); + assertEquals(regatta.getName(), loadedRegatta.getName()); + assertEquals(Util.size(regatta.getSeries()), Util.size(loadedRegatta.getSeries())); + Leaderboard loadedLeaderboard = resForLoading.getLeaderboardByName(loadedRegatta.getName()); + assertNotNull(loadedLeaderboard); + assertEquals(((ThresholdBasedResultDiscardingRule) regattaLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces().length, + ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces().length); + assertTrue(Arrays.equals(((ThresholdBasedResultDiscardingRule) regattaLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(), + ((ThresholdBasedResultDiscardingRule) loadedLeaderboard.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces())); + assertTrue(loadedLeaderboard instanceof RegattaLeaderboard); + RegattaLeaderboard loadedRegattaLeaderboard = (RegattaLeaderboard) loadedLeaderboard; + assertSame(loadedRegatta, loadedRegattaLeaderboard.getRegatta()); + // now re-associate the tracked race to let score correction "snap" to competitor: + final RaceColumnInSeries loadedQ2 = loadedRegatta.getSeriesByName("Qualifying").getRaceColumnByName("Q2"); + final Fleet loadedYellow = loadedQ2.getFleetByName("Yellow"); + // adjust tracked regatta for tracked race: + trackedRegatta[0] = new DynamicTrackedRegattaImpl(loadedRegatta); + resForLoading.apply(new ConnectTrackedRaceToLeaderboardColumn(loadedLeaderboard.getName(), loadedQ2.getName(), loadedYellow + .getName(), q2YellowTrackedRace.getRaceIdentifier())); + MaxPointsReason hassosLoadedMaxPointsReason = loadedLeaderboard.getScoreCorrection().getMaxPointsReason(hasso, loadedQ2, MillisecondsTimePoint.now()); + assertEquals(MaxPointsReason.DNF, hassosLoadedMaxPointsReason); + } + + private void logColumnsInRegattaLeaderboard(RegattaLeaderboard regattaLeaderboard) { + StringBuilder rlbrcNames = new StringBuilder(); + for (RaceColumn rlbrc : regattaLeaderboard.getRaceColumns()) { + rlbrcNames.append("; "); + rlbrcNames.append(rlbrc.getName()); + } + logger.info("columns in regatta leaderboard for regatta "+regattaLeaderboard.getRegatta().getName()+" ("+ + regattaLeaderboard.getRegatta().hashCode()+"): "+rlbrcNames); + logColumnsInRegatta(regattaLeaderboard.getRegatta()); + } + + private void logColumnsInRegatta(Regatta regatta) { + StringBuilder rrcNames = new StringBuilder(); + for (Series series : regatta.getSeries()) { + for (RaceColumn raceColumn : series.getRaceColumns()) { + rrcNames.append("; "); + rrcNames.append(raceColumn.getName()); + } + } + logger.info("columns in regatta "+regatta.getName()+" ("+regatta.hashCode()+") : "+rrcNames); + } + + private RacingEventServiceImpl createRacingEventServiceWithOneMockedTrackedRace(final DynamicTrackedRace q2YellowTrackedRace) { + return new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE) { + @Override + public DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { + return q2YellowTrackedRace; + } + }; + } + + @Test + public void testLoadStoreSimpleRegatta() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, + boatClass, regattaStartDate, regattaEndDate, /* persistent */false, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertSame(LowPoint.class, loadedRegatta.getScoringScheme().getClass()); + assertEquals(regattaName, loadedRegatta.getName()); + Iterator seriesIter = loadedRegatta.getSeries().iterator(); + Series loadedQualifyingSeries = seriesIter.next(); + assertEquals(numberOfQualifyingRaces, Util.size(loadedQualifyingSeries.getRaceColumns())); + assertEquals(0, loadedQualifyingSeries.getFleetByName("Yellow").compareTo(loadedQualifyingSeries.getFleetByName("Blue"))); + Series loadedFinalSeries = seriesIter.next(); + assertEquals(numberOfFinalRaces, Util.size(loadedFinalSeries.getRaceColumns())); + assertTrue(loadedFinalSeries.getFleetByName("Silver").compareTo(loadedFinalSeries.getFleetByName("Gold")) > 0); + Series loadedMedalSeries = seriesIter.next(); + assertEquals(1, Util.size(loadedMedalSeries.getRaceColumns())); + assertEquals(loadedRegatta.getStartDate(), regattaStartDate); + assertEquals(loadedRegatta.getEndDate(), regattaEndDate); + assertEquals(RankingMetrics.ONE_DESIGN, loadedRegatta.getRankingMetricType()); + } + + @Test + public void testLoadStoreRegattaWithHandicapRanking() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, + boatClass, regattaStartDate, regattaEndDate, /* persistent */false, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), TimeOnTimeAndDistanceRankingMetric::new); + assertEquals(RankingMetrics.TIME_ON_TIME_AND_DISTANCE, regatta.getRankingMetricType()); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertSame(LowPoint.class, loadedRegatta.getScoringScheme().getClass()); + assertEquals(regattaName, loadedRegatta.getName()); + Iterator seriesIter = loadedRegatta.getSeries().iterator(); + Series loadedQualifyingSeries = seriesIter.next(); + assertEquals(numberOfQualifyingRaces, Util.size(loadedQualifyingSeries.getRaceColumns())); + assertEquals(0, loadedQualifyingSeries.getFleetByName("Yellow").compareTo(loadedQualifyingSeries.getFleetByName("Blue"))); + Series loadedFinalSeries = seriesIter.next(); + assertEquals(numberOfFinalRaces, Util.size(loadedFinalSeries.getRaceColumns())); + assertTrue(loadedFinalSeries.getFleetByName("Silver").compareTo(loadedFinalSeries.getFleetByName("Gold")) > 0); + Series loadedMedalSeries = seriesIter.next(); + assertEquals(1, Util.size(loadedMedalSeries.getRaceColumns())); + assertEquals(loadedRegatta.getStartDate(), regattaStartDate); + assertEquals(loadedRegatta.getEndDate(), regattaEndDate); + assertEquals(RankingMetrics.TIME_ON_TIME_AND_DISTANCE, loadedRegatta.getRankingMetricType()); + } + + @Test + public void testLoadStoreSimpleRegattaWithEmptyStartAndEndDate() { + final int numberOfQualifyingRaces = 1; + final int numberOfFinalRaces = 1; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regattaName, + boatClass, null, null, /* persistent */false, + DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertEquals(regattaName, loadedRegatta.getName()); + assertEquals(loadedRegatta.getStartDate(), null); + assertEquals(loadedRegatta.getEndDate(), null); + } + + @Test + public void testLoadStoreSimpleRegattaWithSeriesScoringScheme() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), + boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + regatta.getSeriesByName("Qualifying").setResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(new int[] { 1, 2, 3 })); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertTrue(Arrays.equals(new int[] { 1, 2, 3 }, + loadedRegatta.getSeriesByName("Qualifying").getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces())); + } + + @Test + public void testLoadStoreSimpleRegattaWithScoreForMedalStartingWithZero() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), + boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + regatta.getSeriesByName("Medal").setStartsWithZeroScore(true); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertFalse(loadedRegatta.getSeriesByName("Qualifying").isStartsWithZeroScore()); + assertTrue(loadedRegatta.getSeriesByName("Medal").isStartsWithZeroScore()); + } + + @Test + public void testLoadStoreSimpleRegattaWithHighPointScoringScheme() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "ESS40 Cardiff 2012"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("ESS40", /* typicallyStartsUpwind */ false); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), + boatClass, regattaStartDate, regattaEndDate, /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT), OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertSame(HighPoint.class, loadedRegatta.getScoringScheme().getClass()); + } + + @Test + public void testLoadStoreRegattaWithFleetsEnsuringIdenticalFleetsInSeriesAndRaceColumns() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, + regattaName, boatClass, regattaStartDate, regattaEndDate, + /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertEquals(regattaName, loadedRegatta.getName()); + Iterator seriesIter = loadedRegatta.getSeries().iterator(); + Series loadedQualifyingSeries = seriesIter.next(); + int i=1; + for (RaceColumn raceColumn : loadedQualifyingSeries.getRaceColumns()) { + assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); + assertEquals("Q"+i, raceColumn.getName()); + assertTrue(Util.equals(loadedQualifyingSeries.getFleets(), raceColumn.getFleets())); + i++; + } + Series loadedFinalSeries = seriesIter.next(); + i=1; + for (RaceColumn raceColumn : loadedFinalSeries.getRaceColumns()) { + assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); + assertEquals("F"+i, raceColumn.getName()); + assertTrue(Util.equals(loadedFinalSeries.getFleets(), raceColumn.getFleets())); + i++; + } + Series loadedMedalSeries = seriesIter.next(); + for (RaceColumn raceColumn : loadedMedalSeries.getRaceColumns()) { + assertTrue(raceColumn instanceof RaceColumnInSeriesImpl); + assertEquals("M", raceColumn.getName()); + assertTrue(Util.equals(loadedMedalSeries.getFleets(), raceColumn.getFleets())); + } + } + + @Test + public void testLoadStoreRegattaWithFleetsEnsuringFleetOrdering() { + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + final String regattaName = RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()); + Regatta regatta = createRegatta(regattaName, boatClass, regattaStartDate, regattaEndDate, + /* persistent */ false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + assertEquals(regattaName, loadedRegatta.getName()); + + Iterator seriesIter = loadedRegatta.getSeries().iterator(); + Series loadedQualifyingSeries = seriesIter.next(); + + Iterator qualiFleetIt = loadedQualifyingSeries.getFleets().iterator(); + Fleet qualiFleet1 = qualiFleetIt.next(); + assertEquals(qualiFleet1.getName(), "Yellow"); + Fleet qualiFleet2 = qualiFleetIt.next(); + assertEquals(qualiFleet2.getName(), "Blue"); + + Series loadedFinalSeries = seriesIter.next(); + Iterator finalFleetIt = loadedFinalSeries.getFleets().iterator(); + Fleet finalFleet1 = finalFleetIt.next(); + assertEquals(finalFleet1.getName(), "Gold"); + Fleet finalFleet2 = finalFleetIt.next(); + assertEquals(finalFleet2.getName(), "Silver"); + } + + @Test + public void testStorageOfRaceIdentifiersOnRaceColumnInSeries() { + final int numberOfQualifyingRaces = 5; + final int numberOfFinalRaces = 7; + final String regattaBaseName = "Kieler Woche"; + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("29erXX", /* typicallyStartsUpwind */ true); + Regatta regatta = createRegattaAndAddRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, + RegattaImpl.getDefaultName(regattaBaseName, boatClass.getName()), boatClass, regattaStartDate, regattaEndDate, + /* persistent */false, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), OneDesignRankingMetric::new); + Series qualifyingSeries = regatta.getSeries().iterator().next(); + RaceColumn q2 = qualifyingSeries.getRaceColumnByName("Q2"); + final RegattaNameAndRaceName q2TrackedRaceIdentifier = new RegattaNameAndRaceName(regatta.getName(), "Q2 TracTrac"); + q2.setRaceIdentifier(qualifyingSeries.getFleetByName("Yellow"), q2TrackedRaceIdentifier); + MongoObjectFactory mof = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); + mof.storeRegatta(regatta); + + DomainObjectFactory dof = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE); + Regatta loadedRegatta = dof.loadRegatta(regatta.getName(), /* trackedRegattaRegistry */ null); + Series loadedQualifyingSeries = loadedRegatta.getSeries().iterator().next(); + RaceColumn loadedQ2 = loadedQualifyingSeries.getRaceColumnByName("Q2"); + RaceIdentifier loadedQ2TrackedRaceIdentifier = loadedQ2.getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow")); + assertEquals(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier); + assertNotSame(q2TrackedRaceIdentifier, loadedQ2TrackedRaceIdentifier); + assertNull(loadedQualifyingSeries.getRaceColumnByName("Q1").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Yellow"))); + assertNull(loadedQualifyingSeries.getRaceColumnByName("Q2").getRaceIdentifier(loadedQualifyingSeries.getFleetByName("Blue"))); + } + + private Regatta createRegattaAndAddRaceColumns(final int numberOfQualifyingRaces, final int numberOfFinalRaces, + final String regattaName, BoatClass boatClass, TimePoint startDate, TimePoint endDate, boolean persistent, + ScoringScheme scoringScheme, RankingMetricConstructor rankingMetricConstructor) { + Regatta regatta = createRegatta(regattaName, boatClass, startDate, endDate, persistent, scoringScheme, null, + rankingMetricConstructor); + addRaceColumns(numberOfQualifyingRaces, numberOfFinalRaces, regatta); + return regatta; + } + + private void addRaceColumns(final int numberOfQualifyingRaces, final int numberOfFinalRaces, Regatta regatta) { + List finalRaceColumnNames = new ArrayList(); + for (int i=1; i<=numberOfFinalRaces; i++) { + finalRaceColumnNames.add("F"+i); + } + List qualifyingRaceColumnNames = new ArrayList(); + for (int i=1; i<=numberOfQualifyingRaces; i++) { + qualifyingRaceColumnNames.add("Q"+i); + } + List medalRaceColumnNames = new ArrayList(); + medalRaceColumnNames.add("M"); + addRaceColumnsToSeries(qualifyingRaceColumnNames, regatta.getSeriesByName("Qualifying")); + addRaceColumnsToSeries(finalRaceColumnNames, regatta.getSeriesByName("Final")); + addRaceColumnsToSeries(medalRaceColumnNames, regatta.getSeriesByName("Medal")); + } + + private Regatta createRegatta(final String regattaName, BoatClass boatClass, TimePoint startDate, + TimePoint endDate, boolean persistent, ScoringScheme scoringScheme, CourseArea courseArea, + RankingMetricConstructor rankingMetricConstructor) { + List emptyRaceColumnNames = Collections.emptyList(); + List series = new ArrayList(); + + // -------- qualifying series ------------ + List qualifyingFleets = new ArrayList(); + qualifyingFleets.add(new FleetImpl("Yellow")); + qualifyingFleets.add(new FleetImpl("Blue")); + Series qualifyingSeries = new SeriesImpl("Qualifying", /* isMedal */false, qualifyingFleets, + emptyRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(qualifyingSeries); + + // -------- final series ------------ + List finalFleets = new ArrayList(); + finalFleets.add(new FleetImpl("Gold", 1)); + finalFleets.add(new FleetImpl("Silver", 2)); + Series finalSeries = new SeriesImpl("Final", /* isMedal */ false, finalFleets, emptyRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(finalSeries); + + // ------------ medal -------------- + List medalFleets = new ArrayList(); + medalFleets.add(new FleetImpl("Medal")); + Series medalSeries = new SeriesImpl("Medal", /* isMedal */ true, medalFleets, emptyRaceColumnNames, /* trackedRegattaRegistry */ null); + series.add(medalSeries); + Regatta regatta = new RegattaImpl(regattaName, boatClass, startDate, endDate, series, persistent, scoringScheme, "123", courseArea, rankingMetricConstructor); + return regatta; + } + + private void addRaceColumnsToSeries(List finalRaceColumnNames, Series finalSeries) { + for (String raceColumnName : finalRaceColumnNames) { + finalSeries.addRaceColumn(raceColumnName, /* trackedRegattaRegistry */ null); + } + } + + @Test + public void testRegattaRaceAssociationStore() throws Exception { + BoatClass boatClass = DomainFactory.INSTANCE.getOrCreateBoatClass("112er", /* typicallyStartsUpwind */ true); + Regatta regatta = createRegatta(RegattaImpl.getDefaultName("Cologne Masters", boatClass.getName()), boatClass, + regattaStartDate, regattaEndDate, /* persistent */ true, DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT), null, OneDesignRankingMetric::new); + + List competitors = new ArrayList(); + competitors.add(new CompetitorImpl("Axel", "Axel Uhl", Color.RED, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); + Iterable waypoints = Collections.emptyList(); + Course course = new CourseImpl("Course", waypoints); + + RaceDefinition racedef = new RaceDefinitionImpl("M1", course, boatClass, competitors); + regatta.addRace(racedef); + + RacingEventServiceImpl evs = new RacingEventServiceImpl(PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), DomainFactory.INSTANCE), PersistenceFactory.INSTANCE + .getMongoObjectFactory(getMongoService()), MediaDBFactory.INSTANCE.getMediaDB(getMongoService()), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); + assertNull(evs.getRememberedRegattaForRace(racedef.getId())); + evs.raceAdded(regatta, racedef); + assertNotNull(evs.getRememberedRegattaForRace(racedef.getId())); + evs.removeRegatta(regatta); + assertNull(evs.getRememberedRegattaForRace(racedef.getId())); + } + +} diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogEventData.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogEventData.java index 83a2898c51a..2c738aa2199 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogEventData.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogEventData.java @@ -14,8 +14,8 @@ import com.mongodb.DBObject; import com.mongodb.MongoException; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.persistence.PersistenceFactory; import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl; @@ -71,7 +71,7 @@ public class TestStoringAndRetrievingRaceLogEventData extends AbstractMongoDBTes @Test public void storeRaceLogFlagEvent() throws UnknownHostException, MongoException, InterruptedException { TimePoint now = MillisecondsTimePoint.now(); - RaceLogFlagEvent rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(now, author, 0, Flags.AP, Flags.ALPHA, true); + RaceLogFlagEvent rcEvent = new RaceLogFlagEventImpl(now, author, 0, Flags.AP, Flags.ALPHA, true); { DBObject rcEventForMongo = ((MongoObjectFactoryImpl) PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory()) .storeRaceLogFlagEvent(rcEvent); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java index 2eefda7a85f..483deeae753 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInLeaderboards.java @@ -27,7 +27,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; @@ -41,7 +40,21 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventComparator; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; @@ -107,7 +120,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogProtestStartTimeEvent() { - RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent); RaceLog loadedRaceLog = retrieveRaceLog(); loadedRaceLog.lockForRead(); @@ -126,7 +139,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testThatRemoveRaceColumnAlsoRemovesPersistentRaceLog() { - RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); raceColumn.getRaceLog(defaultFleet).add(expectedEvent); @@ -152,7 +165,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD when(service.getMongoObjectFactory()).thenReturn(mongoObjectFactory); when(service.getLeaderboardByName(leaderboardName)).thenReturn(leaderboard); doCallRealMethod().when(service).renameLeaderboardColumn(Matchers.anyString(), Matchers.anyString(), Matchers.anyString()); - RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); raceColumn.getRaceLog(defaultFleet).add(expectedEvent); @@ -195,7 +208,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogStartProcedureChangedEvent() { - RaceLogStartProcedureChangedEvent expectedEvent = RaceLogEventFactory.INSTANCE.createStartProcedureChangedEvent(now, author, 0, RacingProcedureType.ESS); + RaceLogStartProcedureChangedEvent expectedEvent = new RaceLogStartProcedureChangedEventImpl(now, author, 0, RacingProcedureType.ESS); addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent); @@ -217,7 +230,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogGateLineOpeningTimeEvent() { - RaceLogGateLineOpeningTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createGateLineOpeningTimeEvent(now, author, 0, 1234l, 54321l); + RaceLogGateLineOpeningTimeEvent expectedEvent = new RaceLogGateLineOpeningTimeEventImpl(now, author, 0, 1234l, 54321l); addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent); @@ -239,7 +252,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogPathfinderEvent() { - RaceLogPathfinderEvent expectedEvent = RaceLogEventFactory.INSTANCE.createPathfinderEvent(now, author, 0, "GER 20"); + RaceLogPathfinderEvent expectedEvent = new RaceLogPathfinderEventImpl(now, author, 0, "GER 20"); addAndStoreRaceLogEvent(leaderboard, raceColumnName, expectedEvent); @@ -261,7 +274,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogPassChangeEvent() { - RaceLogPassChangeEvent event = RaceLogEventFactory.INSTANCE.createPassChangeEvent(now, author, 0); + RaceLogPassChangeEvent event = new RaceLogPassChangeEventImpl(now, author, 0); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -288,7 +301,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, storedPositioningList); + RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -309,7 +322,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithBackwardsCompatibleRaceLogFinishPositioningConfirmedEvent() { - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, null); + RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, null); createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry(); @@ -358,7 +371,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); - RaceLogFinishPositioningListChangedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningListChangedEvent(now, author, 0, storedPositioningList); + RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -385,7 +398,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogCourseAreaChangeEvent() { final UUID uuid = UUID.randomUUID(); - RaceLogCourseAreaChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseAreaChangedEvent(now, author, 0, uuid); + RaceLogCourseAreaChangedEvent event = new RaceLogCourseAreaChangeEventImpl(now, author, 0, uuid); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -409,7 +422,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogRaceStatusEvent() { - RaceLogRaceStatusEvent event = RaceLogEventFactory.INSTANCE.createRaceStatusEvent(now, author, 0, RaceLogRaceStatus.SCHEDULED); + RaceLogRaceStatusEvent event = new RaceLogRaceStatusEventImpl(now, author, 0, RaceLogRaceStatus.SCHEDULED); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -432,7 +445,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogStartTimeEvent() { - RaceLogStartTimeEvent event = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 0, now); + RaceLogStartTimeEvent event = new RaceLogStartTimeEventImpl(now, author, 0, now); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -456,7 +469,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogFlagEvent() { - RaceLogFlagEvent event = RaceLogEventFactory.INSTANCE.createFlagEvent(now, author, 0, Flags.FIRSTSUBSTITUTE, Flags.NONE, true); + RaceLogFlagEvent event = new RaceLogFlagEventImpl(now, author, 0, Flags.FIRSTSUBSTITUTE, Flags.NONE, true); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -480,7 +493,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogCourseDesignChangedEvent() { CourseBase course = createCourseBase(); - RaceLogCourseDesignChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now, author, 0, course); + RaceLogCourseDesignChangedEvent event = new RaceLogCourseDesignChangedEventImpl(now, author, 0, course); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); @@ -503,7 +516,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD @Test public void testStoreAndRetrieveSimpleLeaderboardWithRaceLogWindFixEvent() { Wind wind = createWindFix(); - RaceLogWindFixEvent event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, author, 0, wind, /* isMagnetic */ false); + RaceLogWindFixEvent event = new RaceLogWindFixEventImpl(now, author, 0, wind, /* isMagnetic */ false); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); RaceLog loadedRaceLog = retrieveRaceLog(); loadedRaceLog.lockForRead(); @@ -527,7 +540,7 @@ public class TestStoringAndRetrievingRaceLogInLeaderboards extends RaceLogMongoD final String COLUMN = "column"; final String FLEET = "fleet"; final SimpleRaceLogIdentifier srli = new SimpleRaceLogIdentifierImpl(PARENT, COLUMN, FLEET); - RaceLogDependentStartTimeEvent event = RaceLogEventFactory.INSTANCE.createDependentStartTimeEvent( + RaceLogDependentStartTimeEvent event = new RaceLogDependentStartTimeEventImpl( now, author, 0, srli, Duration.ONE_MINUTE); addAndStoreRaceLogEvent(leaderboard, raceColumnName, event); RaceLog loadedRaceLog = retrieveRaceLog(); diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java index cd61dca59f0..dea3c3d63e4 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingRaceLogInRegatta.java @@ -20,7 +20,6 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; @@ -33,6 +32,19 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.DomainFactory; @@ -84,7 +96,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogProtestStartTimeEvent() { - RaceLogProtestStartTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createProtestStartTimeEvent(now, author, 0, MillisecondsTimePoint.now()); + RaceLogProtestStartTimeEvent expectedEvent = new RaceLogProtestStartTimeEventImpl(now, author, 0, MillisecondsTimePoint.now()); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); RaceLog loadedRaceLog = retrieveRaceLog(); loadedRaceLog.lockForRead(); @@ -103,7 +115,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogStartProcedureChangedEvent() { - RaceLogStartProcedureChangedEvent expectedEvent = RaceLogEventFactory.INSTANCE.createStartProcedureChangedEvent(now, author, 0, RacingProcedureType.ESS); + RaceLogStartProcedureChangedEvent expectedEvent = new RaceLogStartProcedureChangedEventImpl(now, author, 0, RacingProcedureType.ESS); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); RaceLog loadedRaceLog = retrieveRaceLog(); loadedRaceLog.lockForRead(); @@ -122,7 +134,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogPathfinderEvent() { - RaceLogPathfinderEvent expectedEvent = RaceLogEventFactory.INSTANCE.createPathfinderEvent(now, author, 0, "GER 20"); + RaceLogPathfinderEvent expectedEvent = new RaceLogPathfinderEventImpl(now, author, 0, "GER 20"); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); @@ -144,7 +156,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogGateLineOpeningTimeEvent() { - RaceLogGateLineOpeningTimeEvent expectedEvent = RaceLogEventFactory.INSTANCE.createGateLineOpeningTimeEvent(now, author, 0, 1234l, 54321l); + RaceLogGateLineOpeningTimeEvent expectedEvent = new RaceLogGateLineOpeningTimeEventImpl(now, author, 0, 1234l, 54321l); addAndStoreRaceLogEvent(regatta, raceColumnName, expectedEvent); @@ -166,7 +178,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogPassChangeEvent() { - RaceLogPassChangeEvent event = RaceLogEventFactory.INSTANCE.createPassChangeEvent(now, author, 0); + RaceLogPassChangeEvent event = new RaceLogPassChangeEventImpl(now, author, 0); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -192,7 +204,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); - RaceLogFinishPositioningListChangedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningListChangedEvent(now, author, 0, storedPositioningList); + RaceLogFinishPositioningListChangedEvent event = new RaceLogFinishPositioningListChangedEventImpl(now, author, 0, storedPositioningList); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -223,7 +235,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin CompetitorResults storedPositioningList = new CompetitorResultsImpl(); storedPositioningList.add(new com.sap.sse.common.Util.Triple(storedCompetitor.getId(), storedCompetitor.getName(), MaxPointsReason.NONE)); - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, storedPositioningList); + RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, storedPositioningList); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -249,7 +261,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithBackwardsCompatibleRaceLogFinishPositioningConfirmedEvent() { - RaceLogFinishPositioningConfirmedEvent event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, null); + RaceLogFinishPositioningConfirmedEvent event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, null); createAndStoreOldRaceLogFinishPositioningConfirmedEventDBEntry(); @@ -295,7 +307,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogCourseAreaChangeEvent() { final UUID uuid = UUID.randomUUID(); - RaceLogCourseAreaChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseAreaChangedEvent(now, author, 0, uuid); + RaceLogCourseAreaChangedEvent event = new RaceLogCourseAreaChangeEventImpl(now, author, 0, uuid); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -318,7 +330,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogRaceStatusEvent() { - RaceLogRaceStatusEvent event = RaceLogEventFactory.INSTANCE.createRaceStatusEvent(now, author, 0, RaceLogRaceStatus.SCHEDULED); + RaceLogRaceStatusEvent event = new RaceLogRaceStatusEventImpl(now, author, 0, RaceLogRaceStatus.SCHEDULED); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -341,7 +353,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogStartTimeEvent() { - RaceLogStartTimeEvent event = RaceLogEventFactory.INSTANCE.createStartTimeEvent(now, author, 0, now); + RaceLogStartTimeEvent event = new RaceLogStartTimeEventImpl(now, author, 0, now); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -365,7 +377,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogFlagEvent() { - RaceLogFlagEvent event = RaceLogEventFactory.INSTANCE.createFlagEvent(now, author, 0, Flags.FIRSTSUBSTITUTE, Flags.NONE, true); + RaceLogFlagEvent event = new RaceLogFlagEventImpl(now, author, 0, Flags.FIRSTSUBSTITUTE, Flags.NONE, true); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -389,7 +401,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogCourseDesignChangedEvent() { CourseBase course = createCourseBase(); - RaceLogCourseDesignChangedEvent event = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now, author, 0, course); + RaceLogCourseDesignChangedEvent event = new RaceLogCourseDesignChangedEventImpl(now, author, 0, course); addAndStoreRaceLogEvent(regatta, raceColumnName, event); @@ -412,7 +424,7 @@ public class TestStoringAndRetrievingRaceLogInRegatta extends AbstractTestStorin @Test public void testStoreAndRetrieveRegattaWithRaceLogWindFixEvent() { Wind wind = createWindFix(); - RaceLogWindFixEvent event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, author, 0, wind, /* isMagnetic */ false); + RaceLogWindFixEvent event = new RaceLogWindFixEventImpl(now, author, 0, wind, /* isMagnetic */ false); addAndStoreRaceLogEvent(regatta, raceColumnName, event); diff --git a/java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/data/impl/GPSFixWithPolarContext.java b/java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/data/impl/GPSFixWithPolarContext.java index 642b8fae873..22b2eead462 100644 --- a/java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/data/impl/GPSFixWithPolarContext.java +++ b/java/com.sap.sailing.polars.datamining/src/com/sap/sailing/polars/datamining/data/impl/GPSFixWithPolarContext.java @@ -38,7 +38,7 @@ public class GPSFixWithPolarContext implements HasGPSFixPolarContext { @Override public ClusterDTO getWindSpeedRange() { - return new ClusterDTO(windSpeedRangeGroup.getClusterFor(wind.getObject()).toString()); + return new ClusterDTO(wind == null || wind.getObject() == null ? "null" : windSpeedRangeGroup.getClusterFor(wind.getObject()).toString()); } @Override diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java index 4c0ae954db4..8366b4e61b3 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/mining/AngleAndSpeedRegression.java @@ -27,7 +27,7 @@ import com.sap.sse.common.Util.Pair; /** * This container has two regressions. One for boatSpeed over windSpeed and one for beatAngle over windSpeed - * estimations. + * estimations.

    * * It can return speed and angle for a given windSpeed and should only be used for restricted sets of input data. There * should be one instance per BoatClass+LegType combination. This seperation needs to be taken care of in a higher level diff --git a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/impl/IncrementalAnyOrderLeastSquaresImpl.java b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/impl/IncrementalAnyOrderLeastSquaresImpl.java index 0fefd2ce27d..b71e70a2e4f 100644 --- a/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/impl/IncrementalAnyOrderLeastSquaresImpl.java +++ b/java/com.sap.sailing.polars/src/com/sap/sailing/polars/regression/impl/IncrementalAnyOrderLeastSquaresImpl.java @@ -24,7 +24,7 @@ import com.sap.sse.concurrent.NamedReentrantReadWriteLock; * http://erikerlandson.github.io/blog/2012/07/05/deriving-an-incremental-form-of-the-polynomial-regression-equations/ - * + *

    * * It can be used in parallel, because it uses locking for adding and reading data. * diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java index 12298649ca8..4b56dafba9c 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/AdminConsolePage.java @@ -18,6 +18,7 @@ import com.sap.sailing.selenium.pages.HostPage; import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO; import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardGroupConfigurationPanelPO; import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorsPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesManagementPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; @@ -47,7 +48,7 @@ public class AdminConsolePage extends HostPage { private static final String TRACTRAC_EVENTS_TAB_LABEL = "TracTrac Events"; //$NON-NLS-1$ private static final String TRACTRAC_EVENTS_TAB_IDENTIFIER = "TracTracEventManagement"; //$NON-NLS-1$ - private static final String TRACKED_RACES_TAB_PARENT_LABEL = "Races"; //$NON-NLS-1$ + private static final String TRACKED_RACES_TAB_PARENT_LABEL = "Tracked races"; //$NON-NLS-1$ private static final String TRACKED_RACES_TAB_PARENT_IDENTIFIER = "RacesPanel"; //$NON-NLS-1$ private static final String TRACKED_RACES_TAB_LABEL = "Tracked races"; //$NON-NLS-1$ @@ -62,6 +63,9 @@ public class AdminConsolePage extends HostPage { private static final String LEADERBOARD_GROUP_CONFIGURATION_TAB_LABEL = "Leaderboard groups"; //$NON-NLS-1$ private static final String LEADERBOARD_GROUP_CONFIGURATION_TAB_IDENTIFIER = "LeaderboardGroupConfiguration"; //$NON-NLS-1$ + private static final String COMPETITOR_PANEL_TAB_LABEL = "Competitors"; //$NON-NLS-1$ + private static final String COMPETITOR_PANEL_TAB_IDENTIFIER = "CompetitorPanel"; //$NON-NLS-1$ + /** *

    Goes to the administration console and returns the representing page object.

    * @@ -120,6 +124,12 @@ public class AdminConsolePage extends HostPage { LEADERBOARD_GROUP_CONFIGURATION_TAB_IDENTIFIER, false)); } + public TrackedRacesCompetitorsPanelPO goToTrackedRacesCompetitors() { + goToTab(TRACKED_RACES_TAB_PARENT_LABEL, TRACKED_RACES_TAB_PARENT_IDENTIFIER, true); + return new TrackedRacesCompetitorsPanelPO(this.driver, goToTab(COMPETITOR_PANEL_TAB_LABEL, + COMPETITOR_PANEL_TAB_IDENTIFIER, false)); + } + /** *

    Verifies that the current page is the administration console by checking the title of the page.

    */ diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java new file mode 100644 index 00000000000..b7b4f317153 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorCreateDialogPO.java @@ -0,0 +1,41 @@ +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; + +public class TrackedRacesCompetitorCreateDialogPO extends DataEntryDialogPO { + @FindBy(how = BySeleniumId.class, using = "NameTextBox") + private WebElement nameTextBox; + + @FindBy(how = BySeleniumId.class, using = "SailIdTextBox") + private WebElement sailIdTextBox; + + @FindBy(how = BySeleniumId.class, using = "BoatClassNameSuggestBox") + private WebElement boatClassNameSuggestBox; + + @FindBy(how = BySeleniumId.class, using = "OkButton") + private WebElement okButton; + + public TrackedRacesCompetitorCreateDialogPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + public void setNameTextBox(String name) { + this.nameTextBox.clear(); + this.nameTextBox.sendKeys(name); + } + + public void setSailIdTextBox(String sailId) { + this.sailIdTextBox.clear(); + this.sailIdTextBox.sendKeys(sailId); + } + + public void setBoatClassNameSuggestBox(String boatClassName) { + this.boatClassNameSuggestBox.clear(); + this.boatClassNameSuggestBox.sendKeys(boatClassName); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorTablePO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorTablePO.java new file mode 100644 index 00000000000..cb3732f9cf7 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorTablePO.java @@ -0,0 +1,51 @@ +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.pages.gwt.CellTablePO; +import com.sap.sailing.selenium.pages.gwt.DataEntryPO; + +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorTablePO.CompetitorEntry; + +public class TrackedRacesCompetitorTablePO extends CellTablePO { + public static class CompetitorEntry extends DataEntryPO { + private static final String NAME_COLUMN = "Name"; + private static final String SAILID_COLUMN = "Sail number"; + private static final String BOATCLASSNAME_COLUMN = "Boat Class"; + private static final String ID_COLUMN = "ID"; + + protected CompetitorEntry(TrackedRacesCompetitorTablePO table, WebElement element) { + super(table, element); + } + + @Override + public String getIdentifier() { + return getId(); + } + + public String getId() { + return getColumnContent(ID_COLUMN); + } + + public String getName() { + return getColumnContent(NAME_COLUMN); + } + + public String getSailId() { + return getColumnContent(SAILID_COLUMN); + } + + public String getBoatClassName() { + return getColumnContent(BOATCLASSNAME_COLUMN); + } + } + public TrackedRacesCompetitorTablePO(WebDriver driver, WebElement element) { + super(driver,element); + } + + @Override + protected CompetitorEntry createDataEntry(WebElement element) { + return new CompetitorEntry(this, element); + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java new file mode 100644 index 00000000000..096e5ab9fe9 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java @@ -0,0 +1,31 @@ +package com.sap.sailing.selenium.pages.adminconsole.tracking; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.PageArea; + +public class TrackedRacesCompetitorsPanelPO extends PageArea { + @FindBy(how = BySeleniumId.class, using = "AddCompetitorButton") + private WebElement addButton; + + @FindBy(how = BySeleniumId.class, using = "CompetitorsTable") + private WebElement competitorsTable; + + public TrackedRacesCompetitorsPanelPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + public TrackedRacesCompetitorCreateDialogPO pushAddButton() { + this.addButton.click(); + waitForAjaxRequests(); + WebElement dialog = findElementBySeleniumId(this.driver, "CompetitorEditDialog"); + return new TrackedRacesCompetitorCreateDialogPO(this.driver, dialog); + } + + public TrackedRacesCompetitorTablePO getCompetitorTable() { + return new TrackedRacesCompetitorTablePO(this.driver, this.competitorsTable); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java new file mode 100644 index 00000000000..0c2a8f3f4b5 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java @@ -0,0 +1,60 @@ +package com.sap.sailing.selenium.test.adminconsole; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorCreateDialogPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorTablePO.CompetitorEntry; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesCompetitorsPanelPO; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; + +public class TestCompetitorCreation extends AbstractSeleniumTest { + @Override + @Before + public void setUp() { + clearState(getContextRoot()); + super.setUp(); + } + + @Test + public void testOpenCreateCompetitorDialog() { + final TrackedRacesCompetitorsPanelPO competitorsPanel = goToCompetitorsPanel(); + final TrackedRacesCompetitorCreateDialogPO dialog = competitorsPanel.pushAddButton(); // fails with an exception if the dialog is not found + assertNotNull(dialog); + } + + private TrackedRacesCompetitorsPanelPO goToCompetitorsPanel() { + final AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + final TrackedRacesCompetitorsPanelPO competitorsPanel = adminConsole.goToTrackedRacesCompetitors(); + return competitorsPanel; + } + + @Test + public void testCompetitorCreation() { + final TrackedRacesCompetitorsPanelPO competitorsPanel = goToCompetitorsPanel(); + final TrackedRacesCompetitorCreateDialogPO dialog = competitorsPanel.pushAddButton(); + final String name = ""+System.currentTimeMillis(); + dialog.setNameTextBox(name); + String sailId = ""+System.currentTimeMillis(); + dialog.setSailIdTextBox(sailId); + final String boatClassName = "Laser Int."; + dialog.setBoatClassNameSuggestBox(boatClassName); + dialog.pressOk(); + boolean found = false; + for (final CompetitorEntry it : competitorsPanel.getCompetitorTable().getEntries()) { + String itName = it.getName(); + if (itName.equals(name)) { + found = true; + // found a candidate: + assertEquals(sailId, it.getSailId()); + assertEquals(boatClassName, it.getBoatClassName()); + } + } + assertTrue(found); + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF index e228dc67daf..424fff1b6fb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Require-Bundle: com.sap.sailing.domain.common, com.sap.sailing.domain.shared.android, org.json.simple;bundle-version="1.1.0", - com.sap.sse.common + com.sap.sse.common, + com.sap.sse.shared.android Export-Package: com.sap.sailing.server.gateway.deserialization, com.sap.sailing.server.gateway.deserialization.coursedata.impl, com.sap.sailing.server.gateway.deserialization.impl, diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/EventBaseJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/EventBaseJsonDeserializer.java index 847060e6060..421acf0842f 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/EventBaseJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/EventBaseJsonDeserializer.java @@ -23,12 +23,12 @@ import com.sap.sailing.server.gateway.serialization.impl.EventBaseJsonSerializer import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; import com.sap.sse.common.media.ImageSize; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; public class EventBaseJsonDeserializer implements JsonDeserializer { private final JsonDeserializer venueDeserializer; diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LeagueConfigurationJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LeagueConfigurationJsonDeserializer.java index 42cc2f9e014..4312ba57a14 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LeagueConfigurationJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/LeagueConfigurationJsonDeserializer.java @@ -1,12 +1,13 @@ package com.sap.sailing.server.gateway.deserialization.impl; +import org.json.simple.JSONObject; + import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; import com.sap.sailing.domain.base.configuration.impl.LeagueConfigurationImpl; import com.sap.sailing.domain.base.configuration.procedures.LeagueConfiguration; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; -import org.json.simple.JSONObject; public class LeagueConfigurationJsonDeserializer extends RacingProcedureConfigurationJsonDeserializer implements JsonDeserializer { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/RegattaConfigurationJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/RegattaConfigurationJsonDeserializer.java index 18b72cdb1c7..3e833c1d68c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/RegattaConfigurationJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/impl/RegattaConfigurationJsonDeserializer.java @@ -1,5 +1,7 @@ package com.sap.sailing.server.gateway.deserialization.impl; +import org.json.simple.JSONObject; + import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; import com.sap.sailing.domain.base.configuration.RegattaConfiguration; import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; @@ -12,7 +14,6 @@ import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sailing.server.gateway.serialization.impl.RegattaConfigurationJsonSerializer; -import org.json.simple.JSONObject; public class RegattaConfigurationJsonDeserializer implements JsonDeserializer { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java index 65a7436e45e..e5dd9f40f82 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/BaseRaceLogEventDeserializer.java @@ -10,7 +10,6 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -21,11 +20,9 @@ import com.sap.sse.common.impl.MillisecondsTimePoint; public abstract class BaseRaceLogEventDeserializer implements JsonDeserializer { - protected RaceLogEventRestoreFactory factory; protected JsonDeserializer competitorDeserializer; public BaseRaceLogEventDeserializer(JsonDeserializer competitorDeserializer) { - this.factory = RaceLogEventRestoreFactory.INSTANCE; this.competitorDeserializer = competitorDeserializer; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogAdditionalScoringInformationEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogAdditionalScoringInformationEventDeserializer.java index ba2b95a78c2..9b3aaf8a2fb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogAdditionalScoringInformationEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogAdditionalScoringInformationEventDeserializer.java @@ -8,6 +8,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.scoring.AdditionalScoringInformationType; +import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -24,6 +25,6 @@ public class RaceLogAdditionalScoringInformationEventDeserializer extends BaseRa protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { AdditionalScoringInformationType informationType = AdditionalScoringInformationType.valueOf((String)object.get(FIELD_TYPE)); - return factory.createAdditionalScoringInformationEvent(timePoint, id, author, passId, informationType); + return new RaceLogAdditionalScoringInformationEventImpl(createdAt, timePoint, author, id, passId, informationType); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCloseOpenEndedDeviceMappingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCloseOpenEndedDeviceMappingEventDeserializer.java index 3c5932810a4..6b5e267c27a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCloseOpenEndedDeviceMappingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCloseOpenEndedDeviceMappingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -28,7 +29,7 @@ public class RaceLogCloseOpenEndedDeviceMappingEventDeserializer extends BaseRac Serializable deviceMappingEventId = Helpers.tryUuidConversion((Serializable) object.get(FIELD_DEVICE_MAPPING_EVENT_ID)); TimePoint closingTimePoint = new MillisecondsTimePoint((Long) object.get(FIELD_CLOSING_TIMEPOINT_MILLIS)); - return factory.createCloseOpenEndedDeviceMappingEvent(createdAt, author, timePoint, id, passId, + return new RaceLogCloseOpenEndedDeviceMappingEventImpl(createdAt, timePoint, author, id, passId, deviceMappingEventId, closingTimePoint); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseAreaChangedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseAreaChangedEventDeserializer.java index e7688a762b1..9820f070d6a 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseAreaChangedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseAreaChangedEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -24,7 +25,7 @@ public class RaceLogCourseAreaChangedEventDeserializer extends BaseRaceLogEventD protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { Serializable courseAreaId = (Serializable) object.get(RaceLogCourseAreaChangedEventSerializer.FIELD_COURSE_AREA_ID); - return factory.createCourseAreaChangedEvent(createdAt, author, timePoint, id, competitors, + return new RaceLogCourseAreaChangeEventImpl(createdAt, timePoint, author, id, passId, Helpers.tryUuidConversion(courseAreaId)); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseDesignChangedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseDesignChangedEventDeserializer.java index 64ddc3bb8bc..2f61f1af5be 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseDesignChangedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogCourseDesignChangedEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -31,7 +32,7 @@ public class RaceLogCourseDesignChangedEventDeserializer extends BaseRaceLogEven JSONObject jsonCourseDesign = (JSONObject) object.get(RaceLogCourseDesignChangedEventSerializer.FIELD_COURSE_DESIGN); CourseBase courseData = courseDataDeserializer.deserialize(jsonCourseDesign); - return factory.createCourseDesignChangedEvent(createdAt, author, timePoint, id, competitors, passId, courseData); + return new RaceLogCourseDesignChangedEventImpl(createdAt, timePoint, author, id, passId, courseData); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDefineMarkEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDefineMarkEventDeserializer.java index 4981ad034b5..257b743f295 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDefineMarkEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDefineMarkEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -28,6 +29,6 @@ public class RaceLogDefineMarkEventDeserializer extends BaseRaceLogEventDeserial throws JsonDeserializationException { Mark mark = markDeserializer.deserialize(Helpers.getNestedObjectSafe(object, RaceLogDefineMarkEventSerializer.FIELD_MARK)); - return factory.createDefineMarkEvent(createdAt, author, timePoint, id, passId, mark); + return new RaceLogDefineMarkEventImpl(createdAt, timePoint, author, id, passId, mark); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDenoteForTrackingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDenoteForTrackingEventDeserializer.java index f8dee80153e..7d38a822d12 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDenoteForTrackingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDenoteForTrackingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.SharedDomainFactory; @@ -31,6 +32,6 @@ public class RaceLogDenoteForTrackingEventDeserializer extends BaseRaceLogEventD (String) object.get(RaceLogDenoteForTrackingEventSerializer.FIELD_BOAT_CLASS)); Serializable raceId = (Serializable) object.get(RaceLogDenoteForTrackingEventSerializer.FIELD_RACE_ID); - return factory.createDenoteForTrackingEvent(createdAt, author, timePoint, id, passId, raceName, boatClass, raceId); + return new RaceLogDenoteForTrackingEventImpl(createdAt, timePoint, author, id, passId, raceName, boatClass, raceId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDependentStartTimeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDependentStartTimeEventDeserializer.java index d228dc8d41b..7c7f33633ff 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDependentStartTimeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDependentStartTimeEventDeserializer.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; import com.sap.sailing.domain.abstractlog.race.SimpleRaceLogIdentifier; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.SimpleRaceLogIdentifierImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -35,7 +36,7 @@ public class RaceLogDependentStartTimeEventDeserializer extends RaceLogRaceStatu Duration startTimeDifference = new MillisecondsDurationImpl(startTimeDifferenceInMs); RaceLogRaceStatusEvent event = (RaceLogRaceStatusEvent) super.deserialize(object, id, createdAt, author, timePoint, passId, competitors); SimpleRaceLogIdentifier dependentOnRace = new SimpleRaceLogIdentifierImpl(regattaLikeParentName, raceColumnName, fleetName); - return factory.createDependentStartTimeEvent(event.getCreatedAt(), author, event.getLogicalTimePoint(), event.getId(), event.getInvolvedBoats(), + return new RaceLogDependentStartTimeEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), author, event.getId(), event.getPassId(), dependentOnRace, startTimeDifference, event.getNextStatus()); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceCompetitorMappingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceCompetitorMappingEventDeserializer.java index f7c196ab536..d89ed2065ba 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceCompetitorMappingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceCompetitorMappingEventDeserializer.java @@ -6,6 +6,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -25,8 +26,8 @@ public class RaceLogDeviceCompetitorMappingEventDeserializer extends DeviceIdentifier device, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId) throws JsonDeserializationException { Competitor mappedTo = competitorDeserializer.deserialize(itemObject); - return factory.createDeviceCompetitorMappingEvent(createdAt, author, timePoint, id, device, - mappedTo, passId, from, to); + return new RaceLogDeviceCompetitorMappingEventImpl(createdAt, timePoint, author, id, passId, + mappedTo, device, from, to); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceMarkMappingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceMarkMappingEventDeserializer.java index 838df5965d6..1823dcbe870 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceMarkMappingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogDeviceMarkMappingEventDeserializer.java @@ -6,6 +6,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.Mark; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; @@ -29,8 +30,8 @@ public class RaceLogDeviceMarkMappingEventDeserializer extends DeviceIdentifier device, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId) throws JsonDeserializationException { Mark mappedTo = (Mark) markDeserializer.deserialize(itemObject); - return factory.createDeviceMarkMappingEvent(createdAt, author, timePoint, id, device, - mappedTo, passId, from, to); + return new RaceLogDeviceMarkMappingEventImpl(createdAt, timePoint, author, id, passId, + mappedTo, device, from, to); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEndOfTrackingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEndOfTrackingEventDeserializer.java index b438859805b..a618ef45eea 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEndOfTrackingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogEndOfTrackingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -23,7 +24,7 @@ public class RaceLogEndOfTrackingEventDeserializer extends BaseRaceLogEventDeser protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - return factory.createEndOfTrackingEvent(timePoint, author, id, competitors, passId); + return new RaceLogEndOfTrackingEventImpl(createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java index a7bf33b6121..684435f0f33 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningConfirmedEventDeserializer.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -32,7 +33,7 @@ public class RaceLogFinishPositioningConfirmedEventDeserializer extends BaseRace JSONArray jsonPositionedCompetitors = Helpers.getNestedArraySafe(object, RaceLogFinishPositioningConfirmedEventSerializer.FIELD_POSITIONED_COMPETITORS); CompetitorResults positionedCompetitors = deserializePositionedCompetitors(jsonPositionedCompetitors); - return factory.createFinishPositioningConfirmedEvent(createdAt, author, timePoint, id, competitors, passId, positionedCompetitors); + return new RaceLogFinishPositioningConfirmedEventImpl(createdAt, timePoint, author, id, passId, positionedCompetitors); } private CompetitorResults deserializePositionedCompetitors(JSONArray jsonPositionedCompetitors) throws JsonDeserializationException { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningListChangedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningListChangedEventDeserializer.java index b3755b03bdc..e0561b41c54 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningListChangedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFinishPositioningListChangedEventDeserializer.java @@ -10,6 +10,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -32,7 +33,7 @@ public class RaceLogFinishPositioningListChangedEventDeserializer extends BaseRa JSONArray jsonPositionedCompetitors = Helpers.getNestedArraySafe(object, RaceLogFinishPositioningListChangedEventSerializer.FIELD_POSITIONED_COMPETITORS); CompetitorResults positionedCompetitors = deserializePositionedCompetitors(jsonPositionedCompetitors); - return factory.createFinishPositioningListChangedEvent(createdAt, author, timePoint, id, competitors, passId, positionedCompetitors); + return new RaceLogFinishPositioningListChangedEventImpl(createdAt, timePoint, author, id, passId, positionedCompetitors); } private CompetitorResults deserializePositionedCompetitors(JSONArray jsonPositionedCompetitors) throws JsonDeserializationException { diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java index 7c622a08551..792f0c543aa 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFixedMarkPassingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -28,7 +29,7 @@ public class RaceLogFixedMarkPassingEventDeserializer extends BaseRaceLogEventDe Number zeroBasedIndexOfPassedWaypointObj = (Number) object .get(RaceLogFixedMarkPassingEventSerializer.FIELD_INDEX_OF_PASSED_WAYPOINT); Integer zeroBasedIndexOfPassedWaypoint = zeroBasedIndexOfPassedWaypointObj != null ? zeroBasedIndexOfPassedWaypointObj.intValue() : null; - return factory.createFixedMarkPassingEvent(timePoint, author, id, competitors, passId, ofPassing, + return new RaceLogFixedMarkPassingEventImpl(createdAt, timePoint, author, id, competitors, passId, ofPassing, zeroBasedIndexOfPassedWaypoint); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFlagEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFlagEventDeserializer.java index fbb8e0a6f07..ac55c2f9bcb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFlagEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogFlagEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -26,7 +27,7 @@ public class RaceLogFlagEventDeserializer extends BaseRaceLogEventDeserializer { Flags lowerFlag = Flags.valueOf(object.get(RaceLogFlagEventSerializer.FIELD_LOWER_FLAG).toString()); boolean isDisplayed = (Boolean) object.get(RaceLogFlagEventSerializer.FIELD_DISPLAYED); - return factory.createFlagEvent(createdAt, author, timePoint, id, competitors, passId, upperFlag, lowerFlag, isDisplayed); + return new RaceLogFlagEventImpl(createdAt, timePoint, author, id, passId, upperFlag, lowerFlag, isDisplayed); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogGateLineOpeningTimeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogGateLineOpeningTimeEventDeserializer.java index 2fab762df78..7e066f1cfcc 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogGateLineOpeningTimeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogGateLineOpeningTimeEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -21,13 +22,16 @@ public class RaceLogGateLineOpeningTimeEventDeserializer extends BaseRaceLogEven } @Override - protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, - int passId, List competitors) throws JsonDeserializationException { - Number gateLaunchTime = (Number) object.get(RaceLogGateLineOpeningTimeEventSerializer.FIELD_GATE_LAUNCH_STOP_TIME); + protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, + AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) + throws JsonDeserializationException { + Number gateLaunchTime = (Number) object + .get(RaceLogGateLineOpeningTimeEventSerializer.FIELD_GATE_LAUNCH_STOP_TIME); Number golfDownTime = 0; if (object.containsKey(RaceLogGateLineOpeningTimeEventSerializer.FIELD_GATE_GOLF_DOWN_TIME)) { golfDownTime = (Number) object.get(RaceLogGateLineOpeningTimeEventSerializer.FIELD_GATE_GOLF_DOWN_TIME); } - return factory.createGateLineOpeningTimeEvent(timePoint, author, id, competitors, passId, gateLaunchTime.longValue(), golfDownTime.longValue()); + return new RaceLogGateLineOpeningTimeEventImpl(createdAt, timePoint, author, id, passId, + gateLaunchTime.longValue(), golfDownTime.longValue()); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPassChangeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPassChangeEventDeserializer.java index 0c2d9d0ef5b..0da098ddef5 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPassChangeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPassChangeEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sse.common.TimePoint; @@ -19,8 +20,7 @@ public class RaceLogPassChangeEventDeserializer extends BaseRaceLogEventDeserial @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { - - return factory.createPassChangeEvent(createdAt, author, timePoint, id, competitors, passId); + return new RaceLogPassChangeEventImpl(createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPathFinderEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPathFinderEventDeserializer.java index 24c501aa727..db621c82349 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPathFinderEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogPathFinderEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -24,7 +25,7 @@ public class RaceLogPathFinderEventDeserializer extends BaseRaceLogEventDeserial protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { String pathfinderId = object.get(RaceLogPathfinderEventSerializer.FIELD_PATHFINDER_ID).toString(); - return factory.createPathfinderEvent(createdAt, author, timePoint, id, competitors, passId, pathfinderId); + return new RaceLogPathfinderEventImpl(createdAt, timePoint, author, id, passId, pathfinderId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java index 754733ffb23..7fb40c04455 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogProtestStartTimeEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -24,7 +25,7 @@ public class RaceLogProtestStartTimeEventDeserializer extends BaseRaceLogEventDe protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { Long protestStartTime = (Long) object.get(RaceLogProtestStartTimeEventSerializer.FIELD_PROTEST_START_TIME); - return factory.createProtestStartTimeEvent(createdAt, author, timePoint, id, competitors, + return new RaceLogProtestStartTimeEventImpl(createdAt, timePoint, author, id, passId, new MillisecondsTimePoint(protestStartTime)); } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRaceStatusEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRaceStatusEventDeserializer.java index d4ecefdefc7..56e05b07e71 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRaceStatusEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRaceStatusEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -25,6 +26,6 @@ public class RaceLogRaceStatusEventDeserializer extends BaseRaceLogEventDeserial throws JsonDeserializationException { String statusValue = object.get(RaceLogRaceStatusEventSerializer.FIELD_NEXT_STATUS).toString(); RaceLogRaceStatus nextStatus = RaceLogRaceStatus.valueOf(statusValue); - return factory.createRaceStatusEvent(createdAt, author, timePoint, id, competitors, passId, nextStatus); + return new RaceLogRaceStatusEventImpl(createdAt, timePoint, author, id, passId, nextStatus); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java index 53d77180a9b..6272c1e5dbb 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRegisterCompetitorEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; import com.sap.sse.common.TimePoint; @@ -20,7 +21,7 @@ public class RaceLogRegisterCompetitorEventDeserializer extends BaseRaceLogEvent @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) { assert competitors.size() == 1 : "Expected exactly one competitor for RegisterCompetitorEvent"; - return factory.createRegisterCompetitorEvent(createdAt, author, timePoint, id, passId, competitors.get(0)); + return new RaceLogRegisterCompetitorEventImpl(createdAt, timePoint, author, id, passId, competitors.get(0)); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRevokeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRevokeEventDeserializer.java index 26d00d46ea3..5c5eee4033c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRevokeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogRevokeEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -28,7 +29,7 @@ public class RaceLogRevokeEventDeserializer extends BaseRaceLogEventDeserializer String revokedEventShortInfo = (String) object.get(RaceLogRevokeEventSerializer.FIELD_REVOKED_EVENT_SHORT_INFO); String reason = (String) object.get(RaceLogRevokeEventSerializer.FIELD_REASON); - return factory.createRevokeEvent(createdAt, author, timePoint, id, passId, revokedEventId, + return new RaceLogRevokeEventImpl(createdAt, timePoint, author, id, passId, revokedEventId, revokedEventType, revokedEventShortInfo, reason); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartOfTrackingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartOfTrackingEventDeserializer.java index bb067d83d01..25f3336c73e 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartOfTrackingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartOfTrackingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -23,7 +24,7 @@ public class RaceLogStartOfTrackingEventDeserializer extends BaseRaceLogEventDes protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - return factory.createStartOfTrackingEvent(timePoint, author, id, competitors, passId); + return new RaceLogStartOfTrackingEventImpl(createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartProcedureChangedEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartProcedureChangedEventDeserializer.java index 954cbf98acc..bf0b3cec0a7 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartProcedureChangedEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartProcedureChangedEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.racelog.RacingProcedureType; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -24,7 +25,7 @@ public class RaceLogStartProcedureChangedEventDeserializer extends BaseRaceLogEv protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { RacingProcedureType type = RacingProcedureType.valueOf(object.get(RaceLogStartProcedureChangedEventSerializer.FIELD_START_PROCEDURE_TYPE).toString()); - return factory.createStartProcedureChangedEvent(createdAt, author, timePoint, id, competitors, passId, type); + return new RaceLogStartProcedureChangedEventImpl(createdAt, timePoint, author, id, passId, type); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTimeEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTimeEventDeserializer.java index 86503eeb308..617db8edf1e 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTimeEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTimeEventDeserializer.java @@ -8,6 +8,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -26,8 +27,7 @@ public class RaceLogStartTimeEventDeserializer extends RaceLogRaceStatusEventDes throws JsonDeserializationException { long startTime = (Long) object.get(RaceLogStartTimeEventSerializer.FIELD_START_TIME); RaceLogRaceStatusEvent event = (RaceLogRaceStatusEvent) super.deserialize(object, id, createdAt, author, timePoint, passId, competitors); - return factory.createStartTimeEvent(event.getCreatedAt(), author, event.getLogicalTimePoint(), event.getId(), event.getInvolvedBoats(), - event.getPassId(), new MillisecondsTimePoint(startTime), event.getNextStatus()); + return new RaceLogStartTimeEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), author, event.getId(), event.getPassId(), new MillisecondsTimePoint(startTime), event.getNextStatus()); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTrackingEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTrackingEventDeserializer.java index e69461d0de0..624a1fb532b 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTrackingEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogStartTrackingEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -20,6 +21,6 @@ public class RaceLogStartTrackingEventDeserializer extends BaseRaceLogEventDeser @Override protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { - return factory.createStartTrackingEvent(createdAt, author, timePoint, id, passId); + return new RaceLogStartTrackingEventImpl(createdAt, timePoint, author, id, passId); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogSuppressedMarkPassingsEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogSuppressedMarkPassingsEventDeserializer.java index 0826c463213..124ef6e6352 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogSuppressedMarkPassingsEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogSuppressedMarkPassingsEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.JsonDeserializer; @@ -23,6 +24,6 @@ public class RaceLogSuppressedMarkPassingsEventDeserializer extends BaseRaceLogE protected RaceLogEvent deserialize(JSONObject object, Serializable id, TimePoint createdAt, AbstractLogEventAuthor author, TimePoint timePoint, int passId, List competitors) throws JsonDeserializationException { Integer indexOfFirstWaypoint = (Integer) object.get(RaceLogSuppressedMarkPassingsEventSerializer.FIELD_INDEX_OF_FIRST_SUPPRESSED_WAYPOINTS); - return factory.createSuppressedMarkPassingsEvent(timePoint, author, id, competitors, passId, indexOfFirstWaypoint); + return new RaceLogSuppressedMarkPassingsEventImpl(createdAt, timePoint, author, id, competitors, passId, indexOfFirstWaypoint); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java index 98848155cc9..c3d59ac1481 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/RaceLogWindFixEventDeserializer.java @@ -7,6 +7,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -30,7 +31,7 @@ public class RaceLogWindFixEventDeserializer extends BaseRaceLogEventDeserialize final JSONObject windJsonObject = Helpers.getNestedObjectSafe(object, RaceLogWindFixEventSerializer.FIELD_WIND); final Wind wind = windDeserializer.deserialize(windJsonObject); final Boolean isMagnetic = (Boolean) object.get(RaceLogWindFixEventSerializer.FIELD_MAGNETIC); - return factory.createWindFixEvent(createdAt, author, timePoint, id, competitors, passId, wind, isMagnetic == null ? true : isMagnetic); + return new RaceLogWindFixEventImpl(createdAt, timePoint, author, id, passId, wind, isMagnetic == null ? true : isMagnetic); } } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/EventBaseJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/EventBaseJsonSerializer.java index de6573793fc..2bc9d6e7800 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/EventBaseJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/impl/EventBaseJsonSerializer.java @@ -9,8 +9,8 @@ import com.sap.sailing.domain.base.EventBase; import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.Venue; import com.sap.sailing.server.gateway.serialization.JsonSerializer; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class EventBaseJsonSerializer implements JsonSerializer { public static final String FIELD_ID = "id"; diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java index b106079a7fc..13b39ac2c7c 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogEventSerializer.java @@ -2,15 +2,15 @@ package com.sap.sailing.server.gateway.serialization.racelog.impl; import org.json.simple.JSONObject; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseAreaChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogPassChangeEvent; @@ -21,8 +21,8 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogRevokeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDefineMarkEvent; diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFixedMarkPassingEventSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFixedMarkPassingEventSerializer.java index 7346758cffc..8cb34df4b99 100644 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFixedMarkPassingEventSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/RaceLogFixedMarkPassingEventSerializer.java @@ -2,8 +2,8 @@ package com.sap.sailing.server.gateway.serialization.racelog.impl; import org.json.simple.JSONObject; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.server.gateway.serialization.JsonSerializer; diff --git a/java/com.sap.sailing.server.gateway.serialization.test/.classpath b/java/com.sap.sailing.server.gateway.serialization.test/.classpath index eca7bdba8f0..110168ffa19 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/.classpath +++ b/java/com.sap.sailing.server.gateway.serialization.test/.classpath @@ -3,5 +3,6 @@ + diff --git a/java/com.sap.sailing.server.gateway.serialization.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization.test/META-INF/MANIFEST.MF index 552bcdbed5f..8a479508c89 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization.test/META-INF/MANIFEST.MF @@ -14,4 +14,5 @@ Require-Bundle: com.sap.sailing.domain;bundle-version="1.0.0", org.json.simple, org.mockito.mockito-core;bundle-version="1.9.5", org.objenesis;bundle-version="1.3.0", - com.sap.sse.common + com.sap.sse.common, + com.sap.sse.shared.android diff --git a/java/com.sap.sailing.server.gateway.serialization.test/build.properties b/java/com.sap.sailing.server.gateway.serialization.test/build.properties index 41eb6ade2b4..a2e16dfebcd 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/build.properties +++ b/java/com.sap.sailing.server.gateway.serialization.test/build.properties @@ -1,4 +1,5 @@ -source.. = src/ +source.. = src/,\ + resources/ output.. = bin/ bin.includes = META-INF/,\ . diff --git a/java/com.sap.sailing.server.gateway.serialization.test/resources/racelog.json b/java/com.sap.sailing.server.gateway.serialization.test/resources/racelog.json new file mode 100644 index 00000000000..e00d793293f --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.test/resources/racelog.json @@ -0,0 +1,1543 @@ +{ +"events": [ +{ +"@class": "RaceLogPassChangeEvent", +"id": "01a5fd6d-7b47-450d-bced-0b9e27540577", +"createdAt": 1423107377658, +"timestamp": 1423107377657, +"passId": 1, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "ebd60d8a-a8a8-4e09-ad1d-2bc8920ad61e", +"createdAt": 1423107377679, +"timestamp": 1423107377657, +"passId": 1, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "0a8d6c02-4f99-4cef-bac7-d94a941377e3", +"createdAt": 1423107377698, +"timestamp": 1423107377657, +"passId": 1, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423117800000 +}, +{ +"@class": "RaceLogFlagEvent", +"id": "8c06b01c-fa24-47b1-bc77-c768e49799fb", +"createdAt": 1423107384197, +"timestamp": 1423107384196, +"passId": 1, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "AP", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "d5b9bb62-a4db-4485-ba33-e80eb7e6137d", +"createdAt": 1423107384211, +"timestamp": 1423107384196, +"passId": 2, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "fcf85749-24de-403d-8aae-f8240706ca2a", +"createdAt": 1423107436814, +"timestamp": 1423107436814, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "76251f44-a33f-4e1b-bda7-a904724ba25d", +"createdAt": 1423107436835, +"timestamp": 1423107436814, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "7c8153d2-3354-4f68-bb23-c64828f26ad2", +"createdAt": 1423107436856, +"timestamp": 1423107436814, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423117800000 +}, +{ +"@class": "RaceLogCourseDesignChangedEvent", +"id": "975e34ac-2dbe-477b-964a-635fa8ad8fbf", +"createdAt": 1423107463987, +"timestamp": 1423107463987, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"courseDesign": { +"name": "Course", +"waypoints": [ +{ +"name": "ControlPointWithTwoMarks Race Committee / Black Cylinder", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Race Committee / Black Cylinder", +"left": { +"@class": "Mark", +"name": "Race Committee", +"id": "3e6c1c94-83bf-11e2-88c0-10bf48d758ce", +"type": "STARTBOAT" +}, +"right": { +"@class": "Mark", +"name": "Black Cylinder", +"id": "b153dfd6-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Cylinder", +"type": "BUOY" +} +} +}, +{ +"name": "Red", +"passingInstruction": "Port", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Blue", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Blue", +"id": "1286f15e-83be-11e2-88c0-10bf48d758ce", +"color": "Blue", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Green", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Green", +"id": "785c3e44-83be-11e2-88c0-10bf48d758ce", +"color": "Green", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks White P / White S", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks White P / White S", +"left": { +"@class": "Mark", +"name": "White P", +"id": "e9ec42f8-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +}, +"right": { +"@class": "Mark", +"name": "White S", +"id": "bf6777e6-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Yellow", +"passingInstruction": "Port", +"controlPoint": { +"@class": "Mark", +"name": "Yellow", +"id": "3fdd2402-83be-11e2-88c0-10bf48d758ce", +"color": "Yellow", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks Finish Pole / Black Conical", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Finish Pole / Black Conical", +"left": { +"@class": "Mark", +"name": "Finish Pole", +"id": "3240586c-83c0-11e2-88c0-10bf48d758ce", +"color": "Black", +"type": "LANDMARK" +}, +"right": { +"@class": "Mark", +"name": "Black Conical", +"id": "d78695ea-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Conical", +"type": "BUOY" +} +} +} +] +} +}, +{ +"@class": "RaceLogCourseDesignChangedEvent", +"id": "ec7e158f-98c7-4e6d-b6e0-a93d82fa8cee", +"createdAt": 1423117447335, +"timestamp": 1423117447335, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"courseDesign": { +"name": "Course", +"waypoints": [ +{ +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"left": { +"@class": "Mark", +"name": "Race Committee", +"id": "3e6c1c94-83bf-11e2-88c0-10bf48d758ce", +"type": "STARTBOAT" +}, +"right": { +"@class": "Mark", +"name": "Black Conical", +"id": "d78695ea-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Green", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Green", +"id": "785c3e44-83be-11e2-88c0-10bf48d758ce", +"color": "Green", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Red", +"passingInstruction": "Port", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Green", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Green", +"id": "785c3e44-83be-11e2-88c0-10bf48d758ce", +"color": "Green", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks White P / White S", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks White P / White S", +"left": { +"@class": "Mark", +"name": "White P", +"id": "e9ec42f8-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +}, +"right": { +"@class": "Mark", +"name": "White S", +"id": "bf6777e6-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Green", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Green", +"id": "785c3e44-83be-11e2-88c0-10bf48d758ce", +"color": "Green", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Red", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "Green", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Green", +"id": "785c3e44-83be-11e2-88c0-10bf48d758ce", +"color": "Green", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"left": { +"@class": "Mark", +"name": "Finish Pole", +"id": "3240586c-83c0-11e2-88c0-10bf48d758ce", +"color": "Black", +"type": "LANDMARK" +}, +"right": { +"@class": "Mark", +"name": "Black Cylinder", +"id": "b153dfd6-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Cylinder", +"type": "BUOY" +} +} +} +] +} +}, +{ +"@class": "RaceLogFlagEvent", +"id": "a5c73de6-39c7-4b65-9237-67efa87407a1", +"createdAt": 1423117461037, +"timestamp": 1423117461037, +"passId": 3, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "AP", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "34159312-ac38-4ead-9c38-c365ea8837f7", +"createdAt": 1423117461050, +"timestamp": 1423117461037, +"passId": 4, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "8f487b41-eda6-483b-a3b6-271ac5f1c1b7", +"createdAt": 1423117469402, +"timestamp": 1423117469401, +"passId": 5, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "1dd3eda1-4e97-4526-8148-b3e5b76c5dc6", +"createdAt": 1423117469427, +"timestamp": 1423117469401, +"passId": 5, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "832babce-2272-4267-9eb8-91d434d08e88", +"createdAt": 1423117469449, +"timestamp": 1423117469401, +"passId": 5, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423118700000 +}, +{ +"@class": "RaceLogCourseDesignChangedEvent", +"id": "55322a06-0e83-4fe0-a086-c0cc8eb45f4c", +"createdAt": 1423117559442, +"timestamp": 1423117559442, +"passId": 5, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"courseDesign": { +"name": "Course", +"waypoints": [ +{ +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"left": { +"@class": "Mark", +"name": "Race Committee", +"id": "3e6c1c94-83bf-11e2-88c0-10bf48d758ce", +"type": "STARTBOAT" +}, +"right": { +"@class": "Mark", +"name": "Black Conical", +"id": "d78695ea-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Red", +"passingInstruction": "Port", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks White P / White S", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks White P / White S", +"left": { +"@class": "Mark", +"name": "White P", +"id": "e9ec42f8-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +}, +"right": { +"@class": "Mark", +"name": "White S", +"id": "bf6777e6-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Red", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"left": { +"@class": "Mark", +"name": "Finish Pole", +"id": "3240586c-83c0-11e2-88c0-10bf48d758ce", +"color": "Black", +"type": "LANDMARK" +}, +"right": { +"@class": "Mark", +"name": "Black Cylinder", +"id": "b153dfd6-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Cylinder", +"type": "BUOY" +} +} +} +] +} +}, +{ +"@class": "RaceLogFlagEvent", +"id": "73f137a8-6fda-4ed3-b887-2cdc90f31b07", +"createdAt": 1423117577181, +"timestamp": 1423117577180, +"passId": 5, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "AP", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "10eb3ada-9fd8-42a4-bad7-ca66b10a0a4b", +"createdAt": 1423117577197, +"timestamp": 1423117577180, +"passId": 6, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "8ea5ef0a-4d78-4a9c-acc0-43cfbed195b5", +"createdAt": 1423117584106, +"timestamp": 1423117584106, +"passId": 7, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "61badd3b-152e-41cc-a834-ff466b389fd8", +"createdAt": 1423117584134, +"timestamp": 1423117584106, +"passId": 7, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "1a42be34-143e-4a2a-b5eb-73c3ae91f4a0", +"createdAt": 1423117584158, +"timestamp": 1423117584106, +"passId": 7, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423118700000 +}, +{ +"@class": "RaceLogCourseDesignChangedEvent", +"id": "b406fe97-23bf-4631-9482-bd46397e6eec", +"createdAt": 1423117608140, +"timestamp": 1423117608140, +"passId": 7, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"courseDesign": { +"name": "Course", +"waypoints": [ +{ +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Race Committee / Black Conical", +"left": { +"@class": "Mark", +"name": "Race Committee", +"id": "3e6c1c94-83bf-11e2-88c0-10bf48d758ce", +"type": "STARTBOAT" +}, +"right": { +"@class": "Mark", +"name": "Black Conical", +"id": "d78695ea-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Red", +"passingInstruction": "Port", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks White P / White S", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks White P / White S", +"left": { +"@class": "Mark", +"name": "White P", +"id": "e9ec42f8-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +}, +"right": { +"@class": "Mark", +"name": "White S", +"id": "bf6777e6-83bd-11e2-88c0-10bf48d758ce", +"color": "White", +"shape": "Conical", +"type": "BUOY" +} +} +}, +{ +"name": "Red", +"passingInstruction": "Starboard", +"controlPoint": { +"@class": "Mark", +"name": "Red", +"id": "5427c7d2-83be-11e2-88c0-10bf48d758ce", +"color": "Red", +"shape": "Conical", +"type": "BUOY" +} +}, +{ +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"passingInstruction": "Gate", +"controlPoint": { +"@class": "ControlPointWithTwoMarks", +"name": "ControlPointWithTwoMarks Finish Pole / Black Cylinder", +"left": { +"@class": "Mark", +"name": "Finish Pole", +"id": "3240586c-83c0-11e2-88c0-10bf48d758ce", +"color": "Black", +"type": "LANDMARK" +}, +"right": { +"@class": "Mark", +"name": "Black Cylinder", +"id": "b153dfd6-83be-11e2-88c0-10bf48d758ce", +"color": "Black", +"pattern": "Checkered", +"shape": "Cylinder", +"type": "BUOY" +} +} +} +] +} +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "e5b7ceda-54ac-4c64-ba87-3a4a0544b3a3", +"createdAt": 1423118288283, +"timestamp": 1423118288282, +"passId": 8, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "dddc4f3d-eff3-4183-bd32-1c76075ffe7e", +"createdAt": 1423118288313, +"timestamp": 1423118288282, +"passId": 8, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "a28e4656-1fa1-4229-9106-87c435e9d638", +"createdAt": 1423118288343, +"timestamp": 1423118288282, +"passId": 8, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423118528282 +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "aa69491d-360c-4810-82d8-28c5023bcc76", +"createdAt": 1423118459330, +"timestamp": 1423118459330, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "46997e13-a445-4442-a7c8-d5894557977b", +"createdAt": 1423118459357, +"timestamp": 1423118459330, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "41ab547d-362c-4dae-83d9-34cd1f9152ed", +"createdAt": 1423118459388, +"timestamp": 1423118459330, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1423118519330 +}, +{ +"@class": "RaceLogRaceStatusEvent", +"id": "acc4df30-2122-46b5-9bdd-ea4927206830", +"createdAt": 1423119156823, +"timestamp": 1423119156823, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "FINISHING" +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "17ec061a-ce68-4425-8243-1464c51faca6", +"createdAt": 1423119194333, +"timestamp": 1423119194333, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "e95294b5-d240-418d-90f6-6378b6dfb151", +"createdAt": 1423119199327, +"timestamp": 1423119199327, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "6349878d-e319-4114-b0cd-5e713fcec66f", +"createdAt": 1423119201903, +"timestamp": 1423119201903, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "ab05cf79-8998-4f1b-99db-e8a9f5384da4", +"createdAt": 1423119205872, +"timestamp": 1423119205871, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "009f46a9-0800-4038-a3b2-c81883e2aeda", +"createdAt": 1423119275124, +"timestamp": 1423119275123, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "68ecbedd-8595-4e40-9f7d-632576e93623", +"createdAt": 1423119281232, +"timestamp": 1423119281232, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "6a4e849b-397b-4de4-914b-70101baf9d91", +"createdAt": 1423119283110, +"timestamp": 1423119283110, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "90f04917-7ee9-4e08-bcba-1fb0dcdf9769", +"createdAt": 1423119284281, +"timestamp": 1423119284281, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "da6f8b98-cf23-4c6e-8440-fba744e69e34", +"createdAt": 1423119311959, +"timestamp": 1423119311959, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "657fa5a0-83db-11e2-88c0-10bf48d758ce", +"competitorName": "The Wave, Muscat", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "bc13fc88-293b-4b49-90d8-113b3c527bc3", +"createdAt": 1423119316068, +"timestamp": 1423119316068, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "657fa5a0-83db-11e2-88c0-10bf48d758ce", +"competitorName": "The Wave, Muscat", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "84e68b70-7ada-0131-e5b7-60a44ce903c3", +"competitorName": "Oman Air", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogFinishPositioningListChangedEvent", +"id": "3d088c22-e194-4e80-a2db-e789d0d09afd", +"createdAt": 1423119317012, +"timestamp": 1423119317012, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "657fa5a0-83db-11e2-88c0-10bf48d758ce", +"competitorName": "The Wave, Muscat", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "84e68b70-7ada-0131-e5b7-60a44ce903c3", +"competitorName": "Oman Air", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "e442a414-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Team Aberdeen", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogRaceStatusEvent", +"id": "dad64fc9-ede4-4426-95a1-cdedfed8893d", +"createdAt": 1423119356092, +"timestamp": 1423119356092, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "FINISHED" +}, +{ +"@class": "RaceLogFinishPositioningConfirmedEvent", +"id": "addd714b-31c5-49cd-9c71-eff2921a1c1a", +"createdAt": 1423119365353, +"timestamp": 1423119365353, +"passId": 9, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"positionedCompetitors": [ +{ +"competitorId": "64bbff7e-83db-11e2-88c0-10bf48d758ce", +"competitorName": "GAC Pindar", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "d6c80fc0-8ab6-0132-440c-448a5b8481d8", +"competitorName": "Lino Sonego Team Italia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "65322500-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Red Bull Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "f097f4f0-7ad9-0131-e5b4-60a44ce903c3", +"competitorName": "Gazprom Team Russia", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "655bd56c-83db-11e2-88c0-10bf48d758ce", +"competitorName": "SAP Extreme Sailing Team", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "8dd098a0-8ab6-0132-440b-448a5b8481d8", +"competitorName": "Beko Team Turx", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "657fa5a0-83db-11e2-88c0-10bf48d758ce", +"competitorName": "The Wave, Muscat", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "84e68b70-7ada-0131-e5b7-60a44ce903c3", +"competitorName": "Oman Air", +"maxPointsReason": "NONE" +}, +{ +"competitorId": "e442a414-83db-11e2-88c0-10bf48d758ce", +"competitorName": "Team Aberdeen", +"maxPointsReason": "NONE" +} +] +}, +{ +"@class": "RaceLogPassChangeEvent", +"id": "c01e97a1-d4f4-48a2-a191-0d6cff641e05", +"createdAt": 1434822148262, +"timestamp": 1434822148261, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "cf071a03-def4-44c1-b1c6-4613d25656ee", +"createdAt": 1434822163517, +"timestamp": 1434822163516, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "ESS" +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "547b3955-6a48-4f23-b1d1-e3af59ed2f18", +"createdAt": 1434822167246, +"timestamp": 1434822167246, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogFlagEvent", +"id": "81a61916-cd59-4dc0-9943-e7ce188f0942", +"createdAt": 1434822174067, +"timestamp": 1434822174064, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "INDIA", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogCourseDesignChangedEvent", +"id": "2241738c-d19e-4cbd-8f17-19f303c66584", +"createdAt": 1434822178020, +"timestamp": 1434822178019, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"courseDesign": { +"name": "O2", +"waypoints": [] +} +}, +{ +"@class": "RaceLogWindFixEvent", +"id": "b5bc664d-8f29-45cf-bd3a-5fea78f4b114", +"createdAt": 1434822203426, +"timestamp": 1434822203421, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"wind": { +"position": { +"latitude_deg": 53.2548194, +"longitude_deg": 10.4268592 +}, +"timepoint": 1434822203421, +"speedinknots": 6, +"direction": 275.0006408691406 +}, +"magnetic": true +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "97d3703d-835b-459b-ad7a-ae3065c682fc", +"createdAt": 1434822206193, +"timestamp": 1434822206193, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "081dac9f-b8e6-4ab5-afcf-d48faa5662d2", +"createdAt": 1434822206214, +"timestamp": 1434822206193, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822600000 +}, +{ +"@class": "RaceLogFlagEvent", +"id": "1f7713d8-bd04-4a56-a53d-852d0e1a14ab", +"createdAt": 1434822206262, +"timestamp": 1434822206262, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "INDIA", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "f761bcfb-990b-4b49-8994-97b41c5bcf66", +"createdAt": 1434822219266, +"timestamp": 1434822219263, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "fa90e08f-379d-4e32-9069-c51d6b25b9fd", +"createdAt": 1434822219287, +"timestamp": 1434822219287, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822577561 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "48036626-1083-4a0c-9d72-4318d69d32bf", +"createdAt": 1434822226241, +"timestamp": 1434822226241, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "59af7562-4558-43c3-93f1-5f48c4bee1d4", +"createdAt": 1434822226264, +"timestamp": 1434822226264, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822525417 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "0c9b4e1b-6839-4cdf-805e-32b50ae520f7", +"createdAt": 1434822245101, +"timestamp": 1434822245099, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "df4bd8fb-6624-4afd-a183-1da78115a550", +"createdAt": 1434822245123, +"timestamp": 1434822245123, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822424290 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "eededc2c-c410-4ecb-93a8-01f161565c1d", +"createdAt": 1434822255598, +"timestamp": 1434822255597, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "4aba00f9-07ca-4acf-b7e0-5fd8fa20f65a", +"createdAt": 1434822255622, +"timestamp": 1434822255622, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822314559 +}, +{ +"@class": "RaceLogStartProcedureChangedEvent", +"id": "fb495017-b14e-4047-9467-197bd6ebbec8", +"createdAt": 1434822264172, +"timestamp": 1434822264172, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"startProcedureType": "RRS26" +}, +{ +"@class": "RaceLogStartTimeEvent", +"id": "866c1489-220d-4ad1-9d0c-3f99ab0c1296", +"createdAt": 1434822264198, +"timestamp": 1434822264198, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "SCHEDULED", +"startTime": 1434822263525 +}, +{ +"@class": "RaceLogFlagEvent", +"id": "92ba184f-c6dc-4191-acde-97349441f736", +"createdAt": 1434822284470, +"timestamp": 1434822284470, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "XRAY", +"lowerFlag": "NONE", +"displayed": true +}, +{ +"@class": "RaceLogFlagEvent", +"id": "5b2581df-9155-4c78-bde0-66e4ebbd09f7", +"createdAt": 1434822314815, +"timestamp": 1434822314814, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"upperFlag": "XRAY", +"lowerFlag": "NONE", +"displayed": false +}, +{ +"@class": "RaceLogRaceStatusEvent", +"id": "b4850525-1581-48f7-949b-5e6616c7c2b5", +"createdAt": 1434822335198, +"timestamp": 1434822335197, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "FINISHING" +}, +{ +"@class": "RaceLogRaceStatusEvent", +"id": "173b43e7-f5a8-4233-81a9-6d42b9f7127e", +"createdAt": 1434822340073, +"timestamp": 1434822340072, +"passId": 10, +"competitors": [], +"authorName": "Race Officer on Start Vessel", +"authorPriority": 0, +"nextStatus": "FINISHED" +} +], +"racelog_id": "[ESS 2015 Singapore, R1, Default]" +} \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogDeserializationTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogDeserializationTest.java new file mode 100644 index 00000000000..ec2c2f18d17 --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/deserialization/test/racelog/RaceLogDeserializationTest.java @@ -0,0 +1,56 @@ +package com.sap.sailing.server.gateway.deserialization.test.racelog; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; +import org.junit.Before; +import org.junit.Test; + +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.base.DomainFactory; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.server.gateway.deserialization.impl.Helpers; +import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogDeserializer; +import com.sap.sailing.server.gateway.deserialization.racelog.impl.RaceLogEventDeserializer; + +public class RaceLogDeserializationTest { + private RaceLog parsedRaceLog; + + @Before + public void setUp() throws IOException, ParseException { + parsedRaceLog = deserializeFromFile(); + } + + private static RaceLog deserializeFromFile() throws IOException, ParseException { + InputStream raceLogStream = RaceLogDeserializationTest.class.getResourceAsStream("/racelog.json"); + RaceLogDeserializer deserializer = new RaceLogDeserializer(RaceLogEventDeserializer.create(DomainFactory.INSTANCE)); + + Object parsedRaceLog = JSONValue.parseWithException(new InputStreamReader(raceLogStream)); + JSONObject parsedRaceLogJson = Helpers.toJSONObjectSafe(parsedRaceLog); + + return deserializer.deserialize(parsedRaceLogJson); + } + + @Test + public void testNextStatusDeserialization() throws IOException, ParseException { + parsedRaceLog.lockForRead(); + for (RaceLogEvent event : parsedRaceLog.getFixes()) { + if (event instanceof RaceLogRaceStatusEvent) { + RaceLogRaceStatus status = ((RaceLogRaceStatusEvent) event).getNextStatus(); + if (status == null) { + System.out.println(event); + } + assertNotNull(status); + } + } + parsedRaceLog.unlockAfterRead(); + } +} diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerTest.java index 0ea003c6dfd..d609c0cc48d 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerTest.java @@ -32,8 +32,8 @@ import com.sap.sailing.server.gateway.serialization.impl.LeaderboardGroupBaseJso import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class EventDataJsonSerializerTest { protected final UUID expectedId = UUID.randomUUID(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithImagesAndVideosTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithImagesAndVideosTest.java index c0f07f06ca5..e786c182920 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithImagesAndVideosTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithImagesAndVideosTest.java @@ -36,11 +36,11 @@ import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.ImageDescriptorImpl; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.media.VideoDescriptorImpl; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.shared.media.impl.ImageDescriptorImpl; +import com.sap.sse.shared.media.impl.VideoDescriptorImpl; public class EventDataJsonSerializerWithImagesAndVideosTest { private final UUID expectedId = UUID.randomUUID(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithNullValuesTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithNullValuesTest.java index b9622aeda1c..c62aec309b4 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithNullValuesTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventDataJsonSerializerWithNullValuesTest.java @@ -32,8 +32,8 @@ import com.sap.sailing.server.gateway.serialization.impl.LeaderboardGroupBaseJso import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class EventDataJsonSerializerWithNullValuesTest { protected final UUID expectedId = UUID.randomUUID(); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventWithNullStartAndEndDataJsonSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventWithNullStartAndEndDataJsonSerializerTest.java index 6caf3c22561..f3350335915 100755 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventWithNullStartAndEndDataJsonSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/EventWithNullStartAndEndDataJsonSerializerTest.java @@ -31,8 +31,8 @@ import com.sap.sailing.server.gateway.serialization.impl.EventBaseJsonSerializer import com.sap.sailing.server.gateway.serialization.impl.LeaderboardGroupBaseJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.VenueJsonSerializer; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class EventWithNullStartAndEndDataJsonSerializerTest { diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java index 3786e43665b..aa606905231 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogCourseDesignChangedEventSerializerTest.java @@ -13,7 +13,7 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.DomainFactory; @@ -63,7 +63,7 @@ public class RaceLogCourseDesignChangedEventSerializerTest { factory), new GateDeserializer(factory, new MarkDeserializer(factory)))))); now = MillisecondsTimePoint.now(); - event = RaceLogEventFactory.INSTANCE.createCourseDesignChangedEvent(now, author, 0, createCourseData()); + event = new RaceLogCourseDesignChangedEventImpl(now, author, 0, createCourseData()); } @Test diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java index 93d712b2bc2..ac829c9c22d 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogEventSerializerTest.java @@ -11,8 +11,27 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseAreaChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPassChangeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogCloseOpenEndedDeviceMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; @@ -52,7 +71,6 @@ public class RaceLogEventSerializerTest { private JsonSerializer startOfTrackingEventSerializer; private JsonSerializer endOfTrackingEventSerializer; - private RaceLogEventFactory factory; private AbstractLogEventAuthor author = new LogEventAuthorImpl("Test Author", 1); @SuppressWarnings("unchecked") @@ -97,14 +115,12 @@ public class RaceLogEventSerializerTest { closeOpenEndedDeviceMappingEventSerializer, fixedMarkPassingEventSerializer, suppressedMarkPassingsSerializer, additionalScoringInformationSerializer, dependentStartTimeEventSerializer, startOfTrackingEventSerializer, endOfTrackingEventSerializer); - - factory = RaceLogEventFactory.INSTANCE; } @Test public void testChoosesFlagEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFlagEvent(null, author, 0, null, null, false); + RaceLogEvent event = new RaceLogFlagEventImpl(null, author, 0, null, null, false); serializer.serialize(event); verify(flagEventSerializer).serialize(event); } @@ -112,7 +128,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesStartTimeSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createStartTimeEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogStartTimeEventImpl(null, author, 0, null); serializer.serialize(event); verify(startTimeSerializer).serialize(event); } @@ -120,7 +136,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesRaceStatusSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createRaceStatusEvent(null, author, 0, RaceLogRaceStatus.SCHEDULED); + RaceLogEvent event = new RaceLogRaceStatusEventImpl(null, author, 0, RaceLogRaceStatus.SCHEDULED); serializer.serialize(event); verify(raceStatusSerializer).serialize(event); } @@ -128,7 +144,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesCourseAreaChangedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createCourseAreaChangedEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogCourseAreaChangeEventImpl(null, author, 0, null); serializer.serialize(event); verify(courseAreaChangedEventSerializer).serialize(event); } @@ -136,7 +152,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesPassChangedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createPassChangeEvent(null, author, 0); + RaceLogEvent event = new RaceLogPassChangeEventImpl(null, author, 0); serializer.serialize(event); verify(passChangedSerializer).serialize(event); } @@ -144,7 +160,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesCourseDesignChangedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createCourseDesignChangedEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(null, author, 0, null); serializer.serialize(event); verify(courseDesignChangedEventSerializer).serialize(event); } @@ -152,7 +168,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesFinishPositioningListChangedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFinishPositioningListChangedEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogFinishPositioningListChangedEventImpl(null, author, 0, null); serializer.serialize(event); verify(finishPositioningListChangedEventSerializer).serialize(event); } @@ -160,7 +176,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesFinishPositioningConfirmedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createFinishPositioningConfirmedEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogFinishPositioningConfirmedEventImpl(null, author, 0, null); serializer.serialize(event); verify(finishPositioningConfirmedEventSerializer).serialize(event); } @@ -168,7 +184,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesPathfinderSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createPathfinderEvent(null, author, 0, "GER 20"); + RaceLogEvent event = new RaceLogPathfinderEventImpl(null, author, 0, "GER 20"); serializer.serialize(event); verify(pathfinderEventSerializer).serialize(event); } @@ -176,7 +192,7 @@ public class RaceLogEventSerializerTest { @Test public void testChoosesGateLineOpeningTimeSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createGateLineOpeningTimeEvent(null, author, 0, 2l, 1l); + RaceLogEvent event = new RaceLogGateLineOpeningTimeEventImpl(null, author, 0, 2l, 1l); serializer.serialize(event); verify(gateLineOpeningTimeEventSerializer).serialize(event); } @@ -184,7 +200,7 @@ public class RaceLogEventSerializerTest { @Test public void testStartProcedureTypeChangedSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createStartProcedureChangedEvent(null, author, 0, RacingProcedureType.ESS); + RaceLogEvent event = new RaceLogStartProcedureChangedEventImpl(null, author, 0, RacingProcedureType.ESS); serializer.serialize(event); verify(startProcedureTypeChangedEventSerializer).serialize(event); } @@ -192,7 +208,7 @@ public class RaceLogEventSerializerTest { @Test public void testProtestStartTimeSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createProtestStartTimeEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogProtestStartTimeEventImpl(null, author, 0, null); serializer.serialize(event); verify(protestStartTimeEventSerializer).serialize(event); } @@ -200,7 +216,7 @@ public class RaceLogEventSerializerTest { @Test public void testWindFixSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createWindFixEvent(null, author, 0, null, /* isMagnetic */ false); + RaceLogEvent event = new RaceLogWindFixEventImpl(null, author, 0, null, /* isMagnetic */ false); serializer.serialize(event); verify(windFixEventSerializer).serialize(event); } @@ -208,7 +224,7 @@ public class RaceLogEventSerializerTest { @Test public void testDeviceCompetitorMappingSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createDeviceCompetitorMappingEvent(null, author, null, null, 0, null, null); + RaceLogEvent event = new RaceLogDeviceCompetitorMappingEventImpl(null, author, 0, null, null, null, null); serializer.serialize(event); verify(deviceCompetitorMappingEventSerializer).serialize(event); } @@ -216,7 +232,7 @@ public class RaceLogEventSerializerTest { @Test public void testDeviceMarkMappingSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createDeviceMarkMappingEvent(null, author, null, null, 0, null, null); + RaceLogEvent event = new RaceLogDeviceMarkMappingEventImpl(null, author, 0, null, null, null, null); serializer.serialize(event); verify(deviceMarkMappingEventSerializer).serialize(event); } @@ -224,7 +240,7 @@ public class RaceLogEventSerializerTest { @Test public void testDenoteForTrackingSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createDenoteForTrackingEvent(null, author, 0, "", null, null); + RaceLogEvent event = new RaceLogDenoteForTrackingEventImpl(null, author, 0, "", null, null); serializer.serialize(event); verify(denoteForTrackingEventSerializer).serialize(event); } @@ -232,7 +248,7 @@ public class RaceLogEventSerializerTest { @Test public void testCreateRaceSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createStartTrackingEvent(null, author, 0); + RaceLogEvent event = new RaceLogStartTrackingEventImpl(null, author, 0); serializer.serialize(event); verify(startTrackingEventSerializer).serialize(event); } @@ -240,8 +256,8 @@ public class RaceLogEventSerializerTest { @Test public void testRevokeEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = RaceLogEventRestoreFactory.INSTANCE.createRevokeEvent(MillisecondsTimePoint.now(), author, - MillisecondsTimePoint.now(), 0, 0, UUID.randomUUID(), "type", "short info", "reason"); + RaceLogEvent event = new RaceLogRevokeEventImpl(MillisecondsTimePoint.now(), MillisecondsTimePoint.now(), + author, 0, 0, UUID.randomUUID(), "type", "short info", "reason"); serializer.serialize(event); verify(revokeEventSerializer).serialize(event); } @@ -249,7 +265,7 @@ public class RaceLogEventSerializerTest { @Test public void testRegisterCompetitorEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createRegisterCompetitorEvent(null, author, 0, + RaceLogEvent event = new RaceLogRegisterCompetitorEventImpl(null, author, 0, DomainFactory.INSTANCE .getOrCreateCompetitor("comp", "comp", null, null, null, null, null, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */ null)); @@ -260,7 +276,7 @@ public class RaceLogEventSerializerTest { @Test public void testDefineMarkEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createDefineMarkEvent(null, author, 0, null); + RaceLogEvent event = new RaceLogDefineMarkEventImpl(null, author, 0, null); serializer.serialize(event); verify(defineMarkEventSerializer).serialize(event); } @@ -268,7 +284,7 @@ public class RaceLogEventSerializerTest { @Test public void testCloseOpenEndedDeviceMappingEventSerializer() { // we use the real event type here because we do not want to re-implement the dispatching. - RaceLogEvent event = factory.createCloseOpenEndedDeviceMappingEvent(null, author, 0, null, null); + RaceLogEvent event = new RaceLogCloseOpenEndedDeviceMappingEventImpl(null, author, 0, null, null); serializer.serialize(event); verify(closeOpenEndedDeviceMappingEventSerializer).serialize(event); } diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java index 61eeec67fcd..74e560a6bfd 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogFinishPositioningConfirmedEventSerializerTest.java @@ -14,9 +14,9 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.common.MaxPointsReason; @@ -56,7 +56,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEvent() throws JsonDeserializationException { positioningList.add(new com.sap.sse.common.Util.Triple(UUID.randomUUID(), "SAP Extreme", MaxPointsReason.NONE)); - event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, positioningList); + event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, positioningList); JSONObject jsonConfirmationEvent = serializer.serialize(event); RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer .deserialize(jsonConfirmationEvent); @@ -81,7 +81,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { @Test public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEventWithoutPositioningBackwardsCompatible() throws JsonDeserializationException { - event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, null); + event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, null); JSONObject jsonConfirmationEvent = serializer.serialize(event); RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer .deserialize(jsonConfirmationEvent); @@ -99,7 +99,7 @@ public class RaceLogFinishPositioningConfirmedEventSerializerTest { @Test public void testSerializeAndDeserializeRaceLogFinishPositioningConfirmedEventWithEmptyPositioning() throws JsonDeserializationException { - event = RaceLogEventFactory.INSTANCE.createFinishPositioningConfirmedEvent(now, author, 0, positioningList); + event = new RaceLogFinishPositioningConfirmedEventImpl(now, author, 0, positioningList); JSONObject jsonConfirmationEvent = serializer.serialize(event); RaceLogFinishPositioningConfirmedEvent deserializedEvent = (RaceLogFinishPositioningConfirmedEvent) deserializer .deserialize(jsonConfirmationEvent); diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java index 3b4763ee7a2..adabeedbc05 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/RaceLogWindFixEventSerializerTest.java @@ -9,8 +9,8 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.SharedDomainFactory; import com.sap.sailing.domain.common.Bearing; @@ -56,7 +56,7 @@ public class RaceLogWindFixEventSerializerTest { now = MillisecondsTimePoint.now(); - event = RaceLogEventFactory.INSTANCE.createWindFixEvent(now, author, 0, createWindFix(), /* isMagnetic */ false); + event = new RaceLogWindFixEventImpl(now, author, 0, createWindFix(), /* isMagnetic */ false); } @Test diff --git a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java index a1549d3363d..368d8c554b7 100644 --- a/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java +++ b/java/com.sap.sailing.server.gateway.serialization.test/src/com/sap/sailing/server/gateway/serialization/test/racelog/TrackingTimesEventSerializerTest.java @@ -3,16 +3,15 @@ package com.sap.sailing.server.gateway.serialization.test.racelog; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import java.util.UUID; - import org.json.simple.JSONObject; import org.junit.Test; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventRestoreFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -61,8 +60,8 @@ public class TrackingTimesEventSerializerTest { @Test public void testNullStartOfTrackingTimeAttributeDeserialization() throws JsonDeserializationException { - final RaceLogStartOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createStartOfTrackingEvent(/* startOfTracking */null, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogStartOfTrackingEvent event = new RaceLogStartOfTrackingEventImpl(/* startOfTracking */null, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createStartOfTrackingEventSerializer().serialize(event); RaceLogEvent deserialized = createStartOfTrackingEventDeserializer().deserialize(json); assertNull(deserialized.getLogicalTimePoint()); @@ -70,8 +69,8 @@ public class TrackingTimesEventSerializerTest { @Test public void testNullEndOfTrackingTimeAttributeDeserialization() throws JsonDeserializationException { - final RaceLogEndOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createEndOfTrackingEvent(/* endOfTracking */null, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogEndOfTrackingEvent event = new RaceLogEndOfTrackingEventImpl(/* endOfTracking */null, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createStartOfTrackingEventSerializer().serialize(event); RaceLogEvent deserialized = createEndOfTrackingEventDeserializer().deserialize(json); assertNull(deserialized.getLogicalTimePoint()); @@ -79,16 +78,16 @@ public class TrackingTimesEventSerializerTest { @Test public void testNullStartOfTrackingTimeAttribute() { - final RaceLogStartOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createStartOfTrackingEvent(/* startOfTracking */null, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogStartOfTrackingEvent event = new RaceLogStartOfTrackingEventImpl(/* startOfTracking */null, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createStartOfTrackingEventSerializer().serialize(event); assertNull(json.get(RaceLogStartOfTrackingEventSerializer.FIELD_TIMESTAMP)); } @Test public void testNullEndOfTrackingTimeAttribute() { - final RaceLogEndOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createEndOfTrackingEvent(/* endOfTracking */null, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogEndOfTrackingEvent event = new RaceLogEndOfTrackingEventImpl(/* endOfTracking */null, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createEndOfTrackingEventSerializer().serialize(event); assertNull(json.get(RaceLogEndOfTrackingEventSerializer.FIELD_TIMESTAMP)); } @@ -96,8 +95,8 @@ public class TrackingTimesEventSerializerTest { @Test public void testNonNullStartOfTrackingTimeAttribute() { final TimePoint now = MillisecondsTimePoint.now(); - final RaceLogStartOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createStartOfTrackingEvent(/* startOfTracking */now, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogStartOfTrackingEvent event = new RaceLogStartOfTrackingEventImpl(/* startOfTracking */now, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createStartOfTrackingEventSerializer().serialize(event); assertEquals(now.asMillis(), json.get(RaceLogStartOfTrackingEventSerializer.FIELD_TIMESTAMP)); } @@ -105,8 +104,8 @@ public class TrackingTimesEventSerializerTest { @Test public void testNonNullEndOfTrackingTimeAttribute() { final TimePoint now = MillisecondsTimePoint.now(); - final RaceLogEndOfTrackingEvent event = RaceLogEventRestoreFactory.INSTANCE.createEndOfTrackingEvent(/* endOfTracking */now, - new LogEventAuthorImpl("Axel", 0), UUID.randomUUID(), /* competitors */null, /* passId */1); + final RaceLogEndOfTrackingEvent event = new RaceLogEndOfTrackingEventImpl(/* endOfTracking */now, + new LogEventAuthorImpl("Axel", 0), /* passId */1); JSONObject json = createEndOfTrackingEventSerializer().serialize(event); assertEquals(now.asMillis(), json.get(RaceLogEndOfTrackingEventSerializer.FIELD_TIMESTAMP)); } diff --git a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF index 4db310dafb9..bb906883cfa 100644 --- a/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.server.gateway.serialization/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Require-Bundle: com.sap.sailing.domain.common, com.sap.sse.common, com.sap.sailing.server.gateway.serialization.shared.android Export-Package: com.sap.sailing.server.gateway.deserialization.impl, + com.sap.sailing.server.gateway.serialization, com.sap.sailing.server.gateway.serialization.impl, com.sap.sailing.server.gateway.serialization.racelog.tracking, com.sap.sailing.server.gateway.serialization.racelog.tracking.impl diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/LeaderboardSearchResultBaseJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/LeaderboardSearchResultBaseJsonDeserializer.java index a2a7f6df5ea..441566dc6ec 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/LeaderboardSearchResultBaseJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/LeaderboardSearchResultBaseJsonDeserializer.java @@ -1,6 +1,8 @@ package com.sap.sailing.server.gateway.deserialization.impl; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; import org.json.simple.JSONArray; @@ -29,12 +31,21 @@ public class LeaderboardSearchResultBaseJsonDeserializer implements JsonDeserial @Override public LeaderboardSearchResultBase deserialize(JSONObject object) throws JsonDeserializationException { - final JSONObject eventJson = (JSONObject) object.get(LeaderboardSearchResultJsonSerializer.FIELD_EVENT); - final EventBase event; - if (eventJson != null) { - event = eventDeserializer.deserialize(eventJson); + final JSONArray eventsJson = (JSONArray) object.get(LeaderboardSearchResultJsonSerializer.FIELD_EVENTS); + Collection events = new ArrayList<>(); + if (eventsJson != null) { + for (Object eventJson : eventsJson) { + final EventBase event = eventDeserializer.deserialize((JSONObject) eventJson); + events.add(event); + } } else { - event = null; + // for backward compatibility try the FIELD_EVENT approach: + JSONObject deprecatedEventJson = (JSONObject) object.get("event"); + if (deprecatedEventJson == null) { + events = Collections.emptySet(); + } else { + events = Collections.singleton(eventDeserializer.deserialize(deprecatedEventJson)); + } } JSONObject leaderboardJson = Helpers.getNestedObjectSafe(object, LeaderboardSearchResultJsonSerializer.FIELD_LEADERBOARD); String leaderboardName = (String) leaderboardJson.get(LeaderboardSearchResultJsonSerializer.FIELD_LEADERBOARD_NAME); @@ -47,7 +58,7 @@ public class LeaderboardSearchResultBaseJsonDeserializer implements JsonDeserial leaderboardGroups.add(leaderboardGroupDeserializer.deserialize((JSONObject) leaderboardGroupJson)); } return new LeaderboardSearchResultBaseImpl(new LeaderboardBaseImpl(leaderboardName, leaderboardDisplayName), - regattaName, boatClassName, leaderboardGroups, event); + regattaName, boatClassName, leaderboardGroups, events); } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/NotJsonSerializableException.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/NotJsonSerializableException.java new file mode 100644 index 00000000000..7e5a212bc5e --- /dev/null +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/NotJsonSerializableException.java @@ -0,0 +1,19 @@ +package com.sap.sailing.server.gateway.serialization; + +import java.io.NotSerializableException; + +public class NotJsonSerializableException extends NotSerializableException { + private static final long serialVersionUID = 7890086707210316414L; + + private Class notSerializableClass; + + public NotJsonSerializableException(Class notSerializableClass) { + super(notSerializableClass.getName()); + this.notSerializableClass = notSerializableClass; + } + + public Class getNotSerializableClass() { + return notSerializableClass; + } + +} diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/LeaderboardSearchResultJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/LeaderboardSearchResultJsonSerializer.java index e2dbf1cd2f2..4c100b15a3f 100755 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/LeaderboardSearchResultJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/serialization/impl/LeaderboardSearchResultJsonSerializer.java @@ -3,6 +3,7 @@ package com.sap.sailing.server.gateway.serialization.impl; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.EventBase; import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.LeaderboardSearchResult; @@ -14,7 +15,7 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer; public class LeaderboardSearchResultJsonSerializer implements JsonSerializer { public static final String FIELD_SERVER_BASE_URL = "serverBaseURL"; - public static final String FIELD_EVENT = "event"; + public static final String FIELD_EVENTS = "events"; public static final String FIELD_LEADERBOARD = "leaderboard"; public static final String FIELD_LEADERBOARD_NAME = "name"; public static final String FIELD_LEADERBOARD_DISPLAY_NAME = "displayName"; @@ -33,10 +34,11 @@ public class LeaderboardSearchResultJsonSerializer implements JsonSerializer distanceMetersExtractor = (distance) -> distance.getMeters(); public DataMiningServer getDataMiningServer() { @SuppressWarnings("unchecked") @@ -116,7 +120,7 @@ public class DataMiningResource extends AbstractSailingServerResource { HashMap> race_FilterSelection = new HashMap<>(); race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + response = runQuery(queryDefinitionDTO, regattaName, null, null, "kn", 2); } return response; } @@ -140,7 +144,7 @@ public class DataMiningResource extends AbstractSailingServerResource { race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); race_FilterSelection.put(getRaceName, getRaceName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + response = runQuery(queryDefinitionDTO, regattaName, raceName, null, "kn", 2); } return response; } @@ -159,7 +163,7 @@ public class DataMiningResource extends AbstractSailingServerResource { HashMap> race_FilterSelection = new HashMap<>(); race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + response = runQuery(queryDefinitionDTO, regattaName, null, distanceMetersExtractor, "m", 2); } return response; } @@ -183,7 +187,7 @@ public class DataMiningResource extends AbstractSailingServerResource { race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); race_FilterSelection.put(getRaceName, getRaceName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + response = runQuery(queryDefinitionDTO, regattaName, raceName, distanceMetersExtractor, "m", 2); } return response; } @@ -202,7 +206,7 @@ public class DataMiningResource extends AbstractSailingServerResource { HashMap> race_FilterSelection = new HashMap<>(); race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + response = runQuery(queryDefinitionDTO, regattaName, null, null, null, 0); } return response; } @@ -226,7 +230,8 @@ public class DataMiningResource extends AbstractSailingServerResource { race_FilterSelection.put(getRegattaName, getRegattaName_FilterSelection); race_FilterSelection.put(getRaceName, getRaceName_FilterSelection); queryDefinitionDTO.setFilterSelectionFor(queryDefinitionDTO.getDataRetrieverChainDefinition().getRetrieverLevel(2), race_FilterSelection); - response = runQuery(queryDefinitionDTO); + + response = runQuery(queryDefinitionDTO, regattaName, raceName, null, null, 0); } return response; } @@ -237,7 +242,8 @@ public class DataMiningResource extends AbstractSailingServerResource { return dataMiningServer.getPredefinedQueryDefinitionDTO(queryIdentifier); } - private Response runQuery(ModifiableStatisticQueryDefinitionDTO queryDefinitionDTO) { + private Response runQuery(ModifiableStatisticQueryDefinitionDTO queryDefinitionDTO, String regattaName, String raceName, + Function numberExtractor, String resultUnit, int resultPlaces) { Response response; DataMiningServer dataMiningServer = getDataMiningServer(); @@ -247,7 +253,9 @@ public class DataMiningResource extends AbstractSailingServerResource { response = getBadQueryDefinitionErrorResponse(queryDefinitionDTO); } else { DataMiningSession session = new UUIDDataMiningSession(UUID.randomUUID()); - QueryResult result = dataMiningServer.runNewQueryAndAbortPreviousQueries(session, query); + long requestTimepoint = System.currentTimeMillis(); + @SuppressWarnings("unchecked") + QueryResult result = (QueryResult) dataMiningServer.runNewQueryAndAbortPreviousQueries(session, query); if (result == null || result.isEmpty()) { response = getNoDataFoundErrorResponse(); @@ -255,66 +263,62 @@ public class DataMiningResource extends AbstractSailingServerResource { try { JSONObject jsonResult = new JSONObject(); jsonResult.put("state", result.getState()); - jsonResult.put("signifier", result.getResultSignifier()); - jsonResult.put("resultType", result.getResultType().getSimpleName()); - jsonResult.put("results", resultValuesToJSON(result.getResultType(), result.getResults())); + jsonResult.put("requestTimepoint", requestTimepoint); + jsonResult.put("calculationDuration-s", roundDouble(result.getCalculationTimeInSeconds(), 2)); + jsonResult.put("description", result.getResultSignifier()); + if (regattaName != null && !regattaName.isEmpty()) { + jsonResult.put("regatta", regattaName); + } + if (raceName != null && !raceName.isEmpty()) { + jsonResult.put("race", raceName); + } + jsonResult.put("resultUnit", resultUnit != null && !resultUnit.isEmpty() ? resultUnit : "None"); + jsonResult.put("results", resultValuesToJSON(result, numberExtractor, resultPlaces)); response = Response.ok(jsonResult.toJSONString(), MediaType.APPLICATION_JSON).build(); - } catch (NotSerializableException e) { - response = getNotSerializableErrorResponse(result.getResultType()); + } catch (NotJsonSerializableException e) { + response = getNotSerializableErrorResponse(e.getNotSerializableClass()); } } } return response; } - @SuppressWarnings("unchecked") - private JSONArray resultValuesToJSON(Class resultType, Map resultValues) throws NotSerializableException { - // TODO see Bug 3334 - if (Number.class.isAssignableFrom(resultType)) { - return numericalResultValuesToJSON((Map) resultValues); + private JSONArray resultValuesToJSON(QueryResult result, Function numberExtractor, + int places) throws NotJsonSerializableException { + if (!Number.class.isAssignableFrom(result.getResultType()) && numberExtractor == null) { + throw new NotJsonSerializableException(result.getResultType()); } - if (Distance.class.isAssignableFrom(resultType)) { - return distanceResultValuesToJSON((Map) resultValues); - } - throw new NotSerializableException(resultType.getName()); - } - - private JSONArray numericalResultValuesToJSON(Map resultValues) { - JSONArray jsonResultValues = new JSONArray(); - for (GroupKey groupKey : resultValues.keySet()) { - JSONObject jsonResultEntry = new JSONObject(); - jsonResultEntry.put("groupKey", groupKeyToJSON(groupKey)); - jsonResultEntry.put("value", resultValues.get(groupKey)); - jsonResultValues.add(jsonResultEntry); - } - return jsonResultValues; - } - - private JSONArray distanceResultValuesToJSON(Map resultValues) { - DistanceJsonSerializer distanceSerializer = new DistanceJsonSerializer(); + // TODO see Bug 3334 + Map values = result.getResults(); JSONArray jsonResultValues = new JSONArray(); - for (GroupKey groupKey : resultValues.keySet()) { + for (GroupKey groupKey : values.keySet()) { JSONObject jsonResultEntry = new JSONObject(); jsonResultEntry.put("groupKey", groupKeyToJSON(groupKey)); - jsonResultEntry.put("value", distanceSerializer.serialize(resultValues.get(groupKey))); + Number value = numberExtractor != null ? numberExtractor.apply(values.get(groupKey)) : (Number) values.get(groupKey); + jsonResultEntry.put("value", roundDouble(value.doubleValue(), places)); jsonResultValues.add(jsonResultEntry); } return jsonResultValues; } - private JSONArray groupKeyToJSON(GroupKey groupKey) { + private JSONArray groupKeyToJSON(GroupKey groupKey) throws NotJsonSerializableException { // TODO Convert the concrete key values and not just the string represantation JSONArray jsonResultEntryGroupKeys = new JSONArray(); - List resultEntryGroupKeys = new ArrayList<>(); - resultEntryGroupKeys.add(groupKey.getMainKey()); - if (groupKey.hasSubKeys()) { - resultEntryGroupKeys.addAll(groupKey.getSubKeys()); - } - for (GroupKey resultEntryGroupKey : resultEntryGroupKeys) { - jsonResultEntryGroupKeys.add(resultEntryGroupKey.asString()); + if (groupKey instanceof GenericGroupKey) { + jsonResultEntryGroupKeys.add(simpleGroupKeyToJSON(groupKey)); + } else if (groupKey instanceof CompoundGroupKey) { + for (GroupKey key : groupKey.getKeys()) { + jsonResultEntryGroupKeys.add(groupKeyToJSON(key)); + } + } else { + throw new NotJsonSerializableException(groupKey.getClass()); } return jsonResultEntryGroupKeys; } + + private Object simpleGroupKeyToJSON(GroupKey groupKey) { + return groupKey.asString(); + } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java index 7c45bcc8234..b399c213d41 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java @@ -1,6 +1,12 @@ package com.sap.sailing.server.gateway.jaxrs.api; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -16,6 +22,7 @@ import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; @@ -25,6 +32,7 @@ import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; @Path("/v1/leaderboardgroups") @@ -83,51 +91,62 @@ public class LeaderboardGroupsResource extends AbstractSailingServerResource { jsonLeaderboard.put("lastScoringUpdate", null); } + final LinkedHashMap> fleetsBySeriesName = new LinkedHashMap<>(); + final Map medalSeriesNames = new HashMap<>(); if (isRegattaLeaderboard) { RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; Regatta regatta = regattaLeaderboard.getRegatta(); jsonLeaderboard.put("scoringScheme", leaderboard.getScoringScheme().getType()); jsonLeaderboard.put("regattaName", regatta.getName()); + for (final Series series : regatta.getSeries()) { + List fleets = new ArrayList<>(); + Util.addAll(series.getFleets(), fleets); + fleetsBySeriesName.put(series.getName(), fleets); + medalSeriesNames.put(series.getName(), series.isMedal()); + } } else { jsonLeaderboard.put("scoringScheme", leaderboard.getScoringScheme().getType()); jsonLeaderboard.put("regattaName", null); - JSONArray jsonSeriesEntries = new JSONArray(); - jsonLeaderboard.put("series", jsonSeriesEntries); - // write a 'default' series to be conform with our common regatta structure + fleetsBySeriesName.put(LeaderboardNameConstants.DEFAULT_SERIES_NAME, Collections.singleton(leaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME))); + } + JSONArray jsonSeriesEntries = new JSONArray(); + jsonLeaderboard.put("series", jsonSeriesEntries); + for (final Entry> e : fleetsBySeriesName.entrySet()) { JSONObject jsonSeries = new JSONObject(); jsonSeriesEntries.add(jsonSeries); - jsonSeries.put("name", LeaderboardNameConstants.DEFAULT_SERIES_NAME); - jsonSeries.put("isMedalSeries", null); + jsonSeries.put("name", e.getKey()); + jsonSeries.put("isMedalSeries", medalSeriesNames.get(e.getKey())); JSONArray jsonFleetsEntries = new JSONArray(); jsonSeries.put("fleets", jsonFleetsEntries); - Fleet fleet = leaderboard.getFleet(LeaderboardNameConstants.DEFAULT_FLEET_NAME); - if (fleet != null) { - JSONObject jsonFleet = new JSONObject(); - jsonFleet.put("name", fleet.getName()); - jsonFleet.put("color", fleet.getColor() != null ? fleet.getColor().getAsHtml() : null); - jsonFleet.put("ordering", fleet.getOrdering()); - jsonFleetsEntries.add(jsonFleet); - JSONArray jsonRacesEntries = new JSONArray(); - jsonFleet.put("races", jsonRacesEntries); - for (RaceColumn raceColumn: leaderboard.getRaceColumns()) { - JSONObject jsonRaceColumn = new JSONObject(); - jsonRaceColumn.put("name", raceColumn.getName()); - jsonRaceColumn.put("isMedalRace" , raceColumn.isMedalRace()); - TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - if (trackedRace != null) { - jsonRaceColumn.put("isTracked", true); - jsonRaceColumn.put("regattaName", trackedRace.getTrackedRegatta().getRegatta().getName()); - jsonRaceColumn.put("trackedRaceName", trackedRace.getRace().getName()); - jsonRaceColumn.put("hasGpsData", trackedRace.hasGPSData()); - jsonRaceColumn.put("hasWindData", trackedRace.hasWindData()); - } else { - jsonRaceColumn.put("isTracked", false); - jsonRaceColumn.put("trackedRaceName", null); - jsonRaceColumn.put("hasGpsData", false); - jsonRaceColumn.put("hasWindData", false); + for (final Fleet fleet : e.getValue()) { + if (fleet != null) { + JSONObject jsonFleet = new JSONObject(); + jsonFleet.put("name", fleet.getName()); + jsonFleet.put("color", fleet.getColor() != null ? fleet.getColor().getAsHtml() : null); + jsonFleet.put("ordering", fleet.getOrdering()); + jsonFleetsEntries.add(jsonFleet); + JSONArray jsonRacesEntries = new JSONArray(); + jsonFleet.put("races", jsonRacesEntries); + for (RaceColumn raceColumn: leaderboard.getRaceColumns()) { + JSONObject jsonRaceColumn = new JSONObject(); + jsonRaceColumn.put("name", raceColumn.getName()); + jsonRaceColumn.put("isMedalRace" , raceColumn.isMedalRace()); + TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); + if (trackedRace != null) { + jsonRaceColumn.put("isTracked", true); + jsonRaceColumn.put("regattaName", trackedRace.getTrackedRegatta().getRegatta().getName()); + jsonRaceColumn.put("trackedRaceName", trackedRace.getRace().getName()); + jsonRaceColumn.put("hasGpsData", trackedRace.hasGPSData()); + jsonRaceColumn.put("hasWindData", trackedRace.hasWindData()); + } else { + jsonRaceColumn.put("isTracked", false); + jsonRaceColumn.put("trackedRaceName", null); + jsonRaceColumn.put("hasGpsData", false); + jsonRaceColumn.put("hasWindData", false); + } + jsonRacesEntries.add(jsonRaceColumn); } - jsonRacesEntries.add(jsonRaceColumn); } } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 6c63dbb1d0b..36faf045c2e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -409,11 +409,11 @@ public class LeaderboardsResource extends AbstractSailingServerResource { Set registered = new RegisteredCompetitorsAnalyzer<>(isRegattaLike.getRegattaLog()).analyze(); if (!registered.contains(mappedTo)) { isRegattaLike.getRegattaLog().add( - new RegattaLogRegisterCompetitorEventImpl(now, author, now, UUID.randomUUID(), mappedTo)); + new RegattaLogRegisterCompetitorEventImpl(now, now, author, UUID.randomUUID(), mappedTo)); } DeviceIdentifier device = new SmartphoneUUIDIdentifierImpl(UUID.fromString(deviceUuid)); TimePoint from = new MillisecondsTimePoint(fromMillis); - event = new RegattaLogDeviceCompetitorMappingEventImpl(now, author, now, UUID.randomUUID(), mappedTo, device, + event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), mappedTo, device, from, null); isRegattaLike.getRegattaLog().add(event); logger.fine("Successfully checked in competitor " + mappedTo.getName()); @@ -496,8 +496,8 @@ public class LeaderboardsResource extends AbstractSailingServerResource { .type(MediaType.TEXT_PLAIN).build(); } - RegattaLogCloseOpenEndedDeviceMappingEventImpl event = new RegattaLogCloseOpenEndedDeviceMappingEventImpl(now, - author, now, UUID.randomUUID(), deviceMappingEventId, closingTimePoint); + RegattaLogCloseOpenEndedDeviceMappingEventImpl event = new RegattaLogCloseOpenEndedDeviceMappingEventImpl( + author, now, deviceMappingEventId, closingTimePoint); isRegattaLike.getRegattaLog().add(event); logger.fine("Successfully checked out competitor " + mappedTo.getName()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index c74feb8756e..f20ceb6899e 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -952,9 +952,7 @@ public class RegattasResource extends AbstractSailingServerResource { Course course = trackedRace.getRace().getCourse(); Waypoint lastWaypoint = course.getLastWaypoint(); - TimePoint timePoint = trackedRace.getTimePointOfNewestEvent() == null ? MillisecondsTimePoint.now() - : trackedRace.getTimePointOfNewestEvent(); - // if(trackedRace.isLive(timePoint)) { + TimePoint timePoint = MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()); final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); JSONObject jsonLiveData = new JSONObject(); jsonLiveData.put("name", trackedRace.getRace().getName()); @@ -1034,7 +1032,6 @@ public class RegattasResource extends AbstractSailingServerResource { jsonCompetitors.add(jsonCompetitorInLeg); } jsonLiveData.put("competitors", jsonCompetitors); - String json = jsonLiveData.toJSONString(); return Response.ok(json, MediaType.APPLICATION_JSON).build(); } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java index 7adb6f42e4b..87887b692ed 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/InitialLoadReplicationObjectIdentityTest.java @@ -24,7 +24,7 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventFactoryImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -150,7 +150,7 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl assertNotNull(masterR1RaceLog); final WindImpl masterWindFix = new WindImpl(new DegreePosition(12, 13), MillisecondsTimePoint.now(), new KnotSpeedWithBearingImpl(12.7, new DegreeBearingImpl(123))); - masterR1RaceLog.add(RaceLogEventFactoryImpl.INSTANCE.createWindFixEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), + masterR1RaceLog.add(new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), /* passId */ 1, masterWindFix, /* isMagnetic */ false)); // assert that the wind fix shows up in the tracked race now because the tracked race has the DynamicTrackedRaceLogListener // propagating the wind fix race log event into the wind track for source RACECOMMITTEE @@ -223,7 +223,7 @@ public class InitialLoadReplicationObjectIdentityTest extends AbstractServerRepl // now (see bug 2506) add a wind fix event to the race log and check that it arrived at the wind track final WindImpl replicaWindFix = new WindImpl(new DegreePosition(14, 15), MillisecondsTimePoint.now(), new KnotSpeedWithBearingImpl(22.9, new DegreeBearingImpl(155))); - replicaR1RaceLog.add(RaceLogEventFactoryImpl.INSTANCE.createWindFixEvent(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), + replicaR1RaceLog.add(new RaceLogWindFixEventImpl(MillisecondsTimePoint.now(), new LogEventAuthorImpl("Me", 0), /* passId */ 1, replicaWindFix, /* isMagnetic */ false)); // assert that the wind fix shows up in the tracked race now because the tracked race has the DynamicTrackedRaceLogListener // propagating the wind fix race log event into the wind track for source RACECOMMITTEE diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java index d991e1f7291..1c639b6bf6e 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java @@ -17,9 +17,10 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; import com.sap.sailing.domain.base.ControlPointWithTwoMarks; import com.sap.sailing.domain.base.CourseBase; import com.sap.sailing.domain.base.Fleet; @@ -54,8 +55,8 @@ public class RaceLogReplicationTest extends AbstractLogReplicationTest() { + @Override + public void executed(OperationWithResult operation) { + if (operation instanceof CreateTrackedRace) { + synchronized (notifier) { + notifier[0] = true; + notifier.notifyAll(); + } + } + } + }); + trackingParams = com.sap.sailing.domain.tractracadapter.DomainFactory.INSTANCE + .createTrackingConnectivityParameters(paramURL, liveURI, storedURI, courseDesignUpdateURI, + startOfTracking, endOfTracking, /* delayToLiveInMillis */ + 0l, /* offsetToStartTimeOfSimulatedRace */null, /*ignoreTracTracMarkPassings*/ false, EmptyRaceLogStore.INSTANCE, + EmptyRegattaLogStore.INSTANCE, tracTracUsername, tracTracPassword, "", ""); + } + + private void startTracking() throws Exception, InterruptedException { + startTrackingOnMaster(); + waitForTrackRaceReplicationTrigger(); + raceIdentifier = racesHandle.getRaceTracker().getRaceIdentifiers().iterator().next(); + masterTrackedRace = master.getTrackedRace(raceIdentifier); + } + + private void startTrackingOnMaster() throws Exception { + racesHandle = master.addRace(/* regattaToAddTo */ null, trackingParams, /* timeoutInMilliseconds */ 60000); + } + + private void waitForTrackRaceReplicationTrigger() throws InterruptedException, IllegalAccessException { + while (!notifier[0]) { + synchronized (notifier) { + notifier.wait(); + } + } + replicaReplicator.waitUntilQueueIsEmpty(); + } + + @Test + public void testStartTrackingRaceReplication() throws Exception { + final String boat1CompetitorName = "CYC"; + final String boat1Name = "Boot 1"; + final String boat1Color = "#FF0000"; + + final String boat2CompetitorName = "SVI"; + final String boat2Name = "Boot 2"; + final String boat2Color = "#FFFF00"; + + final String boat3CompetitorName = "BYCÜ"; + final String boat3Name = "Boot 3"; + final String boat3Color = "#FF00FF"; + + startTracking(); + Thread.sleep(5000); + TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier); + assertNotNull(replicaTrackedRace); + + Iterable masterCompetitors = masterTrackedRace.getRace().getCompetitors(); + Iterable replicaCompetitors = replicaTrackedRace.getRace().getCompetitors(); + + assertNotSame(masterTrackedRace, replicaTrackedRace); + assertNotSame(masterTrackedRace.getRace(), replicaTrackedRace.getRace()); + assertEquals(Util.size(masterCompetitors), 6); + assertEquals(Util.size(masterCompetitors), Util.size(replicaCompetitors)); + + for (Competitor competitor : masterCompetitors) { + Competitor replicaCompetitor = findCompetitor(replicaCompetitors, competitor); + switch (competitor.getBoat().getSailID()) { + case boat1CompetitorName: + compareBoatOfCompetitors(masterTrackedRace.getRace().getBoatOfCompetitorById(competitor.getId()), + replicaTrackedRace.getRace().getBoatOfCompetitorById(replicaCompetitor.getId()), boat1Name, boat1Color); + break; + case boat2CompetitorName: + compareBoatOfCompetitors(masterTrackedRace.getRace().getBoatOfCompetitorById(competitor.getId()), + replicaTrackedRace.getRace().getBoatOfCompetitorById(replicaCompetitor.getId()), boat2Name, boat2Color); + break; + case boat3CompetitorName: + compareBoatOfCompetitors(masterTrackedRace.getRace().getBoatOfCompetitorById(competitor.getId()), + replicaTrackedRace.getRace().getBoatOfCompetitorById(replicaCompetitor.getId()), boat3Name, boat3Color); + break; + } + } + } + + private void compareBoatOfCompetitors(Boat masterBoat, Boat replicaBoat, String expectedBoatName, String expectedBoatColor) { + assertNotNull(masterBoat); + assertNotNull(replicaBoat); + assertEquals(masterBoat.getName(), replicaBoat.getName()); + assertEquals(masterBoat.getColor(), replicaBoat.getColor()); + assertEquals(replicaBoat.getName(), expectedBoatName); + assertEquals(replicaBoat.getColor().getAsHtml(), expectedBoatColor); + } + + private Competitor findCompetitor(Iterable competitors, Competitor otherCompetitor) { + for (Competitor competitor : competitors) { + if(competitor.getId().equals(otherCompetitor.getId())) { + return competitor; + } + } + return null; + } + + @After + @Override + public void tearDown() throws Exception { + if (racesHandle != null) { + racesHandle.getRaceTracker().stop(/* preemptive */ false); + } + super.tearDown(); + } +} diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java index ea4a2adaf5b..4d29a1a5927 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java @@ -40,12 +40,11 @@ import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.CompetitorResults; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.impl.CompetitorResultsImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventFactoryImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; @@ -95,6 +94,7 @@ import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.common.impl.WindSourceWithAdditionalID; import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; @@ -129,11 +129,11 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; import com.sap.sse.common.media.MimeType; -import com.sap.sse.common.media.VideoDescriptor; import com.sap.sse.mongodb.MongoDBConfiguration; import com.sap.sse.mongodb.MongoDBService; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class MasterDataImportTest { @@ -149,7 +149,7 @@ public class MasterDataImportTest { private final TimePoint eventStartDate = new MillisecondsTimePoint(new Date()); private final TimePoint eventEndDate = new MillisecondsTimePoint(new Date()); - + private final UUID raceId = UUID.randomUUID(); /** @@ -186,7 +186,8 @@ public class MasterDataImportTest { // Setup source service MockSmartphoneImeiServiceFinderFactory serviceFinderFactory = new MockSmartphoneImeiServiceFinderFactory(); RacingEventService sourceService = new RacingEventServiceImpl(null, null, serviceFinderFactory); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -205,9 +206,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -221,7 +223,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); event.addLeaderboardGroup(group); // Set tracked Race with competitors @@ -235,7 +237,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -245,8 +248,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null,null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -256,29 +259,30 @@ public class MasterDataImportTest { // Set log event TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); - RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, logTimePoint, 1, new ArrayList(), 0, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, logTimePoint, author, 1, + 0, logTimePoint, RaceLogRaceStatus.SCHEDULED); raceColumn.getRaceLog(testFleet1).add(logEvent); Position p = new DegreePosition(3, 3); Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); - RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, author, logTimePoint2, - UUID.randomUUID(), new ArrayList(), 2, wind, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, logTimePoint2, author, + UUID.randomUUID(), 2, wind, /* isMagnetic */false); raceColumn.getRaceLog(testFleet1).add(windEvent); storedLogUUIDs.add(logEvent.getId()); storedLogUUIDs.add(windEvent.getId()); - + // Set RegattaLog event TimePoint regattaLogTimepoint = new MillisecondsTimePoint(84392048L); - RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl(regattaLogTimepoint, - author, regattaLogTimepoint, UUID.randomUUID(), competitor); + RegattaLogRegisterCompetitorEvent registerEvent = new RegattaLogRegisterCompetitorEventImpl( + regattaLogTimepoint, regattaLogTimepoint, author, UUID.randomUUID(), competitor); regatta.getRegattaLog().add(registerEvent); - + // Add some racelogtracking stuff TimePoint logTimePoint3 = new MillisecondsTimePoint(1372489210000L); TimePoint logTimePoint4 = new MillisecondsTimePoint(1372489200020L); DeviceIdentifier deviceIdentifier = new SmartphoneImeiIdentifier("a"); RegattaLogDeviceCompetitorMappingEvent mappingEvent = new RegattaLogDeviceCompetitorMappingEventImpl( - logTimePoint4, author, logTimePoint4, UUID.randomUUID(), competitor, - deviceIdentifier, logTimePoint, logTimePoint3); + logTimePoint4, logTimePoint4, author, UUID.randomUUID(), competitor, deviceIdentifier, logTimePoint, + logTimePoint3); regatta.getRegattaLog().add(mappingEvent); GPSFix gpsFix = new GPSFixMovingImpl(new DegreePosition(54.333, 10.133), logTimePoint2, new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(90))); @@ -354,8 +358,8 @@ public class MasterDataImportTest { Assert.assertNotNull(raceColumnOnTarget); Assert.assertNull(raceColumnOnTarget.getTrackedRace(raceColumnOnTarget.getFleetByName(testFleet1Name))); - raceColumnOnTarget.setTrackedRace(raceColumnOnTarget.getFleets().iterator().next(), new DummyTrackedRace(raceId, - competitors, regattaOnTarget, null, sourceService.getWindStore())); + raceColumnOnTarget.setTrackedRace(raceColumnOnTarget.getFleets().iterator().next(), new DummyTrackedRace( + raceId, competitors, regattaOnTarget, null, sourceService.getWindStore())); Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); @@ -363,7 +367,8 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, null, sourceService.getWindStore()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -404,22 +409,21 @@ public class MasterDataImportTest { Assert.assertNotNull(raceColumnOnTarget.getRaceLog(fleet1OnTarget).getFirstFixAtOrAfter(logTimePoint2)); Assert.assertEquals(wind, ((RaceLogWindFixEvent) raceColumnOnTarget.getRaceLog(fleet1OnTarget) .getFirstFixAtOrAfter(logTimePoint2)).getWindFix()); - + // Add new event to check persistence of post-import events (see bug 3230) TimePoint logTimePoint5 = new MillisecondsTimePoint(1372489310000L); UUID postImportEventId = UUID.randomUUID(); - RaceLogStartTimeEventImpl postImportLogEvent = new RaceLogStartTimeEventImpl(logTimePoint5, author, logTimePoint5, postImportEventId, - new ArrayList(), 3, logTimePoint5); - raceColumnOnTarget.getRaceLog(fleet1OnTarget).add( - postImportLogEvent); - + RaceLogStartTimeEventImpl postImportLogEvent = new RaceLogStartTimeEventImpl(logTimePoint5, logTimePoint5, + author, postImportEventId, 3, logTimePoint5, RaceLogRaceStatus.SCHEDULED); + raceColumnOnTarget.getRaceLog(fleet1OnTarget).add(postImportLogEvent); + // Check for regatta log event - RegattaLogRegisterCompetitorEvent registerEventOnTarget = (RegattaLogRegisterCompetitorEvent) - regattaOnTarget.getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); + RegattaLogRegisterCompetitorEvent registerEventOnTarget = (RegattaLogRegisterCompetitorEvent) regattaOnTarget + .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); Assert.assertNotNull(registerEventOnTarget); Assert.assertEquals(registerEvent.getId(), registerEventOnTarget.getId()); Assert.assertEquals(competitor.getId(), registerEventOnTarget.getCompetitor().getId()); - + // Check for import of racelogtracking fix Assert.assertTrue(destService.getGPSFixStore().getNumberOfFixes(deviceIdentifier) == 1); @@ -429,14 +433,14 @@ public class MasterDataImportTest { RaceColumn raceColumn2 = lb2.getRaceColumns().iterator().next(); RaceLog raceLog2 = raceColumn2.getRaceLog(raceColumn2.getFleetByName(fleet1OnTarget.getName())); Assert.assertEquals(logEvent.getId(), raceLog2.getFirstRawFixAtOrAfter(logTimePoint).getId()); - + RaceLogEvent postImportLogEventFromDB = raceLog2.getFirstRawFixAtOrAfter(logTimePoint5); Assert.assertEquals(postImportEventId, postImportLogEventFromDB.getId()); - + // Check for persisting of regatta log events Regatta regattaOnTarget2 = dest2.getRegattaByName(TEST_LEADERBOARD_NAME); - RegattaLogRegisterCompetitorEvent registerEventOnTarget2 = (RegattaLogRegisterCompetitorEvent) - regattaOnTarget2.getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); + RegattaLogRegisterCompetitorEvent registerEventOnTarget2 = (RegattaLogRegisterCompetitorEvent) regattaOnTarget2 + .getRegattaLog().getFirstFixAtOrAfter(regattaLogTimepoint); Assert.assertNotNull(registerEventOnTarget2); Assert.assertEquals(registerEvent.getId(), registerEventOnTarget2.getId()); } @@ -446,7 +450,8 @@ public class MasterDataImportTest { InterruptedException, ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -464,9 +469,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -478,7 +484,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -491,7 +497,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -499,7 +506,8 @@ public class MasterDataImportTest { DynamicPerson coach2 = new PersonImpl("Max Test", new NationalityImpl("GER"), new Date(645487200000L), "desc"); DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); - CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, null, team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor2 = new CompetitorImpl(competitor2UUID, "Froderik", Color.RED, null, null, team2, + boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -507,9 +515,8 @@ public class MasterDataImportTest { raceColumn.setTrackedRace(testFleet1, trackedRace); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -574,7 +581,8 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, null, sourceService.getWindStore()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -603,7 +611,8 @@ public class MasterDataImportTest { ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -619,9 +628,9 @@ public class MasterDataImportTest { fleets.add(testFleet1); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, true, new LowPoint(), - courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName("testRegatta", "29er"), "29er", + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -633,7 +642,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -646,12 +655,14 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); - + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); DynamicTrackedRegatta trackedRegatta = sourceService.getOrCreateTrackedRegatta(regatta); - TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, trackedRegatta, sourceService.getWindStore()); + TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, trackedRegatta, + sourceService.getWindStore()); regatta.addRace(trackedRace.getRace()); // make sure the competitor is serialized together with the regatta raceColumn.setTrackedRace(testFleet1, trackedRace); WindSource windSource = new WindSourceWithAdditionalID(WindSourceType.EXPEDITION, "Igtimi1"); @@ -716,7 +727,8 @@ public class MasterDataImportTest { Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); DynamicTrackedRegatta trackedRegattaForTarget = destService.getOrCreateTrackedRegatta(regattaOnTarget); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, trackedRegattaForTarget, sourceService.getWindStore()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + trackedRegattaForTarget, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -734,8 +746,9 @@ public class MasterDataImportTest { } finally { windTrackOnDest.unlockAfterRead(); } - - //Reimport again to see if db throws exceptions (see console for error for now, since exception is caught deep inside) + + // Reimport again to see if db throws exceptions (see console for error for now, since exception is caught deep + // inside) try { streamingOutput.write(os); os.flush(); @@ -754,12 +767,13 @@ public class MasterDataImportTest { public void testMasterDataImportForRaceLogEventsReferencingCompetitors() throws MalformedURLException, IOException, InterruptedException, ClassNotFoundException { // Setup source service - DomainFactory sourceDomainFactory = new DomainFactoryImpl((srlid)->null); + DomainFactory sourceDomainFactory = new DomainFactoryImpl((srlid) -> null); RacingEventService sourceService = new RacingEventServiceImpl( PersistenceFactory.INSTANCE.getDomainObjectFactory(MongoDBService.INSTANCE, sourceDomainFactory), PersistenceFactory.INSTANCE.getMongoObjectFactory(MongoDBService.INSTANCE), MediaDBFactory.INSTANCE.getDefaultMediaDB(), EmptyWindStore.INSTANCE, EmptyGPSFixStore.INSTANCE); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -777,9 +791,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -791,7 +806,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -804,8 +819,9 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, "noone@nowhere.de", null, team, - boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + Competitor competitor = sourceDomainFactory.getOrCreateCompetitor(competitorUUID, "Froderik", Color.RED, + "noone@nowhere.de", null, team, boat, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null); competitors.add(competitor); UUID competitor2UUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -814,7 +830,8 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Pros2", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("FastBoat", boatClass, "GER70133"); Competitor competitor2 = sourceDomainFactory.getCompetitorStore().getOrCreateCompetitor(competitor2UUID, - "Froderik", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + "Froderik", Color.RED, "noone@nowhere.de", null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null); competitors.add(competitor2); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -822,9 +839,8 @@ public class MasterDataImportTest { raceColumn.setTrackedRace(testFleet1, trackedRace); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -833,10 +849,10 @@ public class MasterDataImportTest { CompetitorResults positionedCompetitors = new CompetitorResultsImpl(); positionedCompetitors.add(new Util.Triple(competitor.getId(), competitor .getName(), MaxPointsReason.DNS)); - positionedCompetitors.add(new Util.Triple(competitor2.getId(), competitor2 - .getName(), MaxPointsReason.NONE)); - RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = factory - .createFinishPositioningConfirmedEvent(logTimePoint2, author, 1, positionedCompetitors); + positionedCompetitors.add(new Util.Triple(competitor2.getId(), + competitor2.getName(), MaxPointsReason.NONE)); + RaceLogFinishPositioningConfirmedEvent finishPositioningConfirmedEvent = new RaceLogFinishPositioningConfirmedEventImpl( + logTimePoint2, author, 1, positionedCompetitors); raceColumn.getRaceLog(testFleet1).add(finishPositioningConfirmedEvent); storedLogUUIDs.add(finishPositioningConfirmedEvent.getId()); @@ -894,7 +910,8 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Fleet fleet1OnTarget = raceColumnOnTarget.getFleetByName(testFleet1.getName()); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, null, sourceService.getWindStore()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(fleet1OnTarget, trackedRaceForTarget); @@ -915,7 +932,8 @@ public class MasterDataImportTest { InterruptedException, ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -933,9 +951,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -947,7 +966,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -960,7 +979,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -970,8 +990,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -979,9 +999,8 @@ public class MasterDataImportTest { raceColumn.setTrackedRace(testFleet1, trackedRace); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -1030,8 +1049,8 @@ public class MasterDataImportTest { domainFactory = destService.getBaseDomainFactory(); // Create existing data on target venueNameNotToOverride = "doNotOverride"; - Event eventNotToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, venueNameNotToOverride, - false, eventUUID); + Event eventNotToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, + eventStartDate, eventEndDate, venueNameNotToOverride, false, eventUUID); courseAreaNotToOverride = new CourseAreaImpl("testAreaNotToOverride", courseAreaUUID); eventNotToOverride.getVenue().addCourseArea(courseAreaNotToOverride); @@ -1047,20 +1066,21 @@ public class MasterDataImportTest { seriesNotToOverride.add(new SeriesImpl("testSeries", false, fleetsNotToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaNotToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /*startDate*/ null, /*endDate*/ null, - regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesNotToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); event.addRegatta(regattaNotToOverride); for (String name : raceColumnNamesNotToOverride) { seriesNotToOverride.get(0).addRaceColumn(name, destService); } - leaderboardNotToOverride = destService.addRegattaLeaderboard( - regattaNotToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); + leaderboardNotToOverride = destService.addRegattaLeaderboard(regattaNotToOverride.getRegattaIdentifier(), + "testDisplayNameNotToOverride", discardRule); List leaderboardNamesNotToOverride = new ArrayList(); leaderboardNamesNotToOverride.add(leaderboardNotToOverride.getName()); - groupNotToOverride = destService.addLeaderboardGroup(UUID.randomUUID(), - TEST_GROUP_NAME, "testGroupDescNotToOverride", /* displayName */ null, false, leaderboardNamesNotToOverride, null, null); + groupNotToOverride = destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDescNotToOverride", /* displayName */null, false, leaderboardNamesNotToOverride, null, + null); inputStream = new ByteArrayInputStream(os.toByteArray()); MasterDataImporter importer = new MasterDataImporter(domainFactory, destService); @@ -1114,7 +1134,8 @@ public class MasterDataImportTest { InterruptedException, ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -1132,9 +1153,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -1146,7 +1168,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -1159,7 +1181,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1170,7 +1193,7 @@ public class MasterDataImportTest { DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, - null, team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1178,9 +1201,8 @@ public class MasterDataImportTest { raceColumn.setTrackedRace(testFleet1, trackedRace); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -1225,7 +1247,8 @@ public class MasterDataImportTest { domainFactory = destService.getBaseDomainFactory(); // Create existing data on target String venueNameToOverride = "Override"; - Event eventToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, venueNameToOverride, false, eventUUID); + Event eventToOverride = destService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, + eventEndDate, venueNameToOverride, false, eventUUID); CourseArea courseAreaToOverride = new CourseAreaImpl("testAreaToOverride", courseAreaUUID); eventToOverride.getVenue().addCourseArea(courseAreaToOverride); @@ -1241,8 +1264,8 @@ public class MasterDataImportTest { seriesToOverride.add(new SeriesImpl("testSeries", false, fleetsToOverride, emptyRaceColumnNamesList, destService)); Regatta regattaToOverride = destService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /*startDate*/ null, /*endDate*/ null, - regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesToOverride, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); event.addRegatta(regattaToOverride); for (String name : raceColumnNamesToOverride) { @@ -1261,19 +1284,21 @@ public class MasterDataImportTest { DynamicBoat boatToOverride = new BoatImpl("Wingy", boatClassToOverride, "GER70133"); String competitorOldName = "oldName"; Competitor competitorToOverride = domainFactory.getOrCreateCompetitor(competitorUUID, competitorOldName, - Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ null); + Color.BLUE, "noone@nowhere.de", null, teamToOverride, boatToOverride, /* timeOnTimeFactor */null, /* timeOnDistanceAllowanceInSecondsPerNauticalMile */ + null); competitorsToOverride.add(competitorToOverride); Leaderboard leaderboardToOverride = destService.addRegattaLeaderboard( regattaToOverride.getRegattaIdentifier(), "testDisplayNameNotToOverride", discardRule); - TrackedRace trackedRace2 = new DummyTrackedRace(raceId, competitorsToOverride, regattaToOverride, null, sourceService.getWindStore()); + TrackedRace trackedRace2 = new DummyTrackedRace(raceId, competitorsToOverride, regattaToOverride, null, + sourceService.getWindStore()); RaceColumn columnToOverride = leaderboardToOverride.getRaceColumns().iterator().next(); columnToOverride.setTrackedRace(testFleet1ToOverride, trackedRace2); - identifierOfRegattaTrackedRace = regattaToOverride - .getRaceIdentifier(columnToOverride.getRaceDefinition(testFleet1ToOverride)); + identifierOfRegattaTrackedRace = regattaToOverride.getRaceIdentifier(columnToOverride + .getRaceDefinition(testFleet1ToOverride)); - destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDescToOverride", /* displayName */ null, - false, new ArrayList(), null, null); + destService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDescToOverride", /* displayName */ + null, false, new ArrayList(), null, null); destService.getLeaderboardGroupByName(TEST_GROUP_NAME).addLeaderboard(leaderboardToOverride); destService.addLeaderboard(leaderboardToOverride); inputStream = new ByteArrayInputStream(os.toByteArray()); @@ -1340,15 +1365,18 @@ public class MasterDataImportTest { InterruptedException, ClassNotFoundException { RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */ null, + Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), - /* officialWebsiteURL */ null, /* sailorsInfoWebsiteURL */ null, - /* images */Collections. emptyList(), /* videos */Collections. emptyList()); - CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] {"ECHO"}, new UUID[] {UUID.randomUUID()})[0]; + /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, + /* images */Collections. emptyList(), /* videos */ + Collections. emptyList()); + CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, + new UUID[] { UUID.randomUUID() })[0]; Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /*startDate*/ null, /*endDate*/ null, - UUID.randomUUID(), new ArrayList(), true, new LowPoint(), defaultCourseArea.getId(), /* useStartTimeInference */ true, OneDesignRankingMetric::new); + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, UUID.randomUUID(), new ArrayList(), true, new LowPoint(), + defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); // Let's use the setters directly because we are not testing replication RegattaConfigurationImpl configuration = new RegattaConfigurationImpl(); configuration.setDefaultCourseDesignerMode(CourseDesignerMode.BY_MAP); @@ -1359,7 +1387,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Serialize List groupNamesToExport = new ArrayList(); @@ -1405,11 +1433,13 @@ public class MasterDataImportTest { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */ null, - new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), - /* officialWebsiteURL */ null, /* sailorsInfoWebsiteURL */ null, - /* images */Collections. emptyList(), /* videos */Collections. emptyList()); - CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] {"ECHO"}, new UUID[] {UUID.randomUUID()})[0]; + Event event = sourceService.createEventWithoutReplication("Test Event", /* eventDescription */null, + new MillisecondsTimePoint(0), new MillisecondsTimePoint(10), "testvenue", false, UUID.randomUUID(), + /* officialWebsiteURL */null, /* sailorsInfoWebsiteURL */null, + /* images */Collections. emptyList(), /* videos */ + Collections. emptyList()); + CourseArea defaultCourseArea = sourceService.addCourseAreas(event.getId(), new String[] { "ECHO" }, + new UUID[] { UUID.randomUUID() })[0]; List raceColumnNames = new ArrayList(); String raceColumnName = "T1"; @@ -1425,9 +1455,10 @@ public class MasterDataImportTest { series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), defaultCourseArea.getId(), /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), + defaultCourseArea.getId(), /* useStartTimeInference */true, OneDesignRankingMetric::new); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); } @@ -1437,7 +1468,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -1450,7 +1481,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1460,8 +1492,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null,null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1469,9 +1501,8 @@ public class MasterDataImportTest { raceColumn.setTrackedRace(testFleet1, trackedRace); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -1538,7 +1569,8 @@ public class MasterDataImportTest { IOException, InterruptedException, ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -1557,9 +1589,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -1571,7 +1604,7 @@ public class MasterDataImportTest { List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -1584,7 +1617,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1594,8 +1628,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -1605,9 +1639,8 @@ public class MasterDataImportTest { sourceService.setRegattaForRace(regatta, "dummy2"); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); raceColumn.getRaceLog(testFleet1).add(logEvent); storedLogUUIDs.add(logEvent.getId()); @@ -1704,28 +1737,30 @@ public class MasterDataImportTest { assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName4)); assignedRaces.add(new RegattaNameAndRaceName(regattaName2, raceName5)); assignedRaces.add(new RegattaNameAndRaceName(missingRegattaName, missingRaceName)); - MediaTrack trackOnSource = new MediaTrack("testTitle", "http://test/test.mp4", new MillisecondsTimePoint(0), MillisecondsDurationImpl.ONE_HOUR, - MimeType.mp4, assignedRaces); + MediaTrack trackOnSource = new MediaTrack("testTitle", "http://test/test.mp4", new MillisecondsTimePoint(0), + MillisecondsDurationImpl.ONE_HOUR, MimeType.mp4, assignedRaces); sourceService.mediaTrackAdded(trackOnSource); - + Collection raceColumnNames = Arrays.asList(raceName1, raceName2, raceName3, raceName4, raceName5); Regatta regatta = MediaMasterDataExportTest.createTestRegatta(regattaName1, raceColumnNames); sourceService.addRegattaWithoutReplication(regatta); int[] discardThresholds = new int[0]; - RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "leaderboard display name", discardThresholds); - Collection raceIdentifiers = Arrays.asList( - new RegattaNameAndRaceName(regattaName1, raceName1), + RegattaLeaderboard leaderboard = sourceService.addRegattaLeaderboard(regatta.getRegattaIdentifier(), + "leaderboard display name", discardThresholds); + Collection raceIdentifiers = Arrays.asList(new RegattaNameAndRaceName(regattaName1, raceName1), new RegattaNameAndRaceName(regattaName1, raceName2), new RegattaNameAndRaceName(regattaName1, raceName3), new RegattaNameAndRaceName(regattaName2, raceName4), - new RegattaNameAndRaceName(regattaName2, raceName5) - ); + new RegattaNameAndRaceName(regattaName2, raceName5)); MediaMasterDataExportTest.assignRacesToRegattaLeaderboardColumns(leaderboard, raceIdentifiers); boolean displayGroupsInReverseOrder = false; int[] overallLeaderboardDiscardThresholds = new int[0]; UUID leaderboardGropuUuid = UUID.randomUUID(); - LeaderboardGroup leaderboardGroup = sourceService.addLeaderboardGroup(leaderboardGropuUuid , "leaderboard group name", "leaderboard group description", "leaderboard group display name", displayGroupsInReverseOrder, Collections.singletonList(leaderboard.getName()), overallLeaderboardDiscardThresholds, ScoringSchemeType.LOW_POINT); - + LeaderboardGroup leaderboardGroup = sourceService.addLeaderboardGroup(leaderboardGropuUuid, + "leaderboard group name", "leaderboard group description", "leaderboard group display name", + displayGroupsInReverseOrder, Collections.singletonList(leaderboard.getName()), + overallLeaderboardDiscardThresholds, ScoringSchemeType.LOW_POINT); + // Serialize List groupNamesToExport = Collections.singletonList(leaderboardGroup.getName()); @@ -1781,7 +1816,8 @@ public class MasterDataImportTest { InterruptedException, ClassNotFoundException { // Setup source service RacingEventService sourceService = new RacingEventServiceImpl(); - Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */ null, eventStartDate, eventEndDate, "testVenue", false, eventUUID); + Event event = sourceService.addEvent(TEST_EVENT_NAME, /* eventDescription */null, eventStartDate, eventEndDate, + "testVenue", false, eventUUID); UUID courseAreaUUID = UUID.randomUUID(); CourseArea courseArea = new CourseAreaImpl("testArea", courseAreaUUID); event.getVenue().addCourseArea(courseArea); @@ -1799,9 +1835,10 @@ public class MasterDataImportTest { fleets.add(new FleetImpl("testFleet2")); series.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); - Regatta regatta = sourceService.createRegatta(RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, series, - true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ true, OneDesignRankingMetric::new); + Regatta regatta = sourceService.createRegatta( + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, + /* startDate */null, /* endDate */null, regattaUUID, series, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); event.addRegatta(regatta); for (String name : raceColumnNames) { series.get(0).addRaceColumn(name, sourceService); @@ -1812,10 +1849,12 @@ public class MasterDataImportTest { "testDisplayName", discardRule); List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); - LeaderboardGroup group1 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); - LeaderboardGroup group2 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME2, "testGroupDesc2", - /* displayName */ null, false, leaderboardNames, null, null); + LeaderboardGroup group1 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDesc", + /* displayName */null, false, leaderboardNames, null, null); + LeaderboardGroup group2 = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME2, + "testGroupDesc2", + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors Set competitors = new HashSet(); @@ -1828,7 +1867,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -1838,8 +1878,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); @@ -1908,8 +1948,9 @@ public class MasterDataImportTest { int[] discardRule = { 1, 2, 3, 4 }; ScoringScheme scheme = new LowPoint(); List leaderboardNames = new ArrayList(); - LeaderboardGroup sourceGroup = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, discardRule, scheme.getType()); + LeaderboardGroup sourceGroup = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, + "testGroupDesc", + /* displayName */null, false, leaderboardNames, discardRule, scheme.getType()); FlexibleLeaderboard sourceLeaderboard1 = new FlexibleLeaderboardImpl("Leaderboard1", null, scheme, null); sourceService.addLeaderboard(sourceLeaderboard1); sourceGroup.addLeaderboard(sourceLeaderboard1); @@ -2026,8 +2067,9 @@ public class MasterDataImportTest { seriesOnTarget.add(new SeriesImpl("testSeries", false, fleets, emptyRaceColumnNamesList, sourceService)); UUID regattaUUID = UUID.randomUUID(); Regatta regatta = sourceService.createRegatta( - RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /*startDate*/ null, /*endDate*/ null, regattaUUID, - seriesOnSource, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); + RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, /* startDate */ + null, /* endDate */null, regattaUUID, seriesOnSource, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */ + true, OneDesignRankingMetric::new); for (String name : raceColumnNames) { seriesOnSource.get(0).addRaceColumn(name, sourceService); } @@ -2038,13 +2080,11 @@ public class MasterDataImportTest { ScoringScheme scoringScheme = new LowPoint(); String flexLeaderboardName = "FlexName"; FlexibleLeaderboard leaderboard = sourceService.addFlexibleLeaderboard(flexLeaderboardName, "TestFlex", - discardRule, - scoringScheme, courseAreaUUID); + discardRule, scoringScheme, courseAreaUUID); List leaderboardNames = new ArrayList(); leaderboardNames.add(leaderboard.getName()); LeaderboardGroup group = sourceService.addLeaderboardGroup(UUID.randomUUID(), TEST_GROUP_NAME, "testGroupDesc", - /* displayName */ null, false, leaderboardNames, null, null); - + /* displayName */null, false, leaderboardNames, null, null); // Set tracked Race with competitors List competitors = new ArrayList(); @@ -2057,7 +2097,8 @@ public class MasterDataImportTest { DynamicTeam team = new TeamImpl("Pros", sailors, coach); BoatClass boatClass = new BoatClassImpl("H16", true); DynamicBoat boat = new BoatImpl("Wingy", boatClass, "GER70133"); - CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitor = new CompetitorImpl(competitorUUID, "Froderik", Color.RED, null, null, team, boat, /* timeOnTimeFactor */ + null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitor); UUID competitorToSuppressUUID = UUID.randomUUID(); Set sailors2 = new HashSet(); @@ -2067,8 +2108,8 @@ public class MasterDataImportTest { "Bester Coach"); DynamicTeam team2 = new TeamImpl("Noobs", sailors2, coach2); DynamicBoat boat2 = new BoatImpl("LahmeEnte", boatClass, "GER1337"); - CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, null, - team2, boat2, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null); + CompetitorImpl competitorToSuppress = new CompetitorImpl(competitorToSuppressUUID, "Merkel", Color.RED, null, + null, team2, boat2, /* timeOnTimeFactor */null, /* timeOnDistanceAllowancePerNauticalMile */null); competitors.add(competitorToSuppress); TrackedRace trackedRace = new DummyTrackedRace(raceId, competitors, regatta, null, sourceService.getWindStore()); @@ -2077,16 +2118,14 @@ public class MasterDataImportTest { raceColumnOnLeaderboard.setFactor(3.0); // Set log event - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); TimePoint logTimePoint = new MillisecondsTimePoint(1372489200000L); TimePoint logTimePoint2 = new MillisecondsTimePoint(1372489201000L); - RaceLogStartTimeEvent logEvent = factory.createStartTimeEvent(logTimePoint, author, 1, logTimePoint); + RaceLogStartTimeEvent logEvent = new RaceLogStartTimeEventImpl(logTimePoint, author, 1, logTimePoint); Fleet defaultFleet = leaderboard.getFleet(null); raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(logEvent); Position p = new DegreePosition(3, 3); Wind wind = new WindImpl(p, logTimePoint2, new KnotSpeedWithBearingImpl(5, new DegreeBearingImpl(12))); - RaceLogWindFixEvent windEvent = factory.createWindFixEvent(logTimePoint2, author, UUID.randomUUID(), - new ArrayList(), 2, wind, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent = new RaceLogWindFixEventImpl(logTimePoint2, author, 2, wind, /* isMagnetic */false); raceColumnOnLeaderboard.getRaceLog(defaultFleet).add(windEvent); storedLogUUIDs.add(logEvent.getId()); storedLogUUIDs.add(windEvent.getId()); @@ -2157,12 +2196,11 @@ public class MasterDataImportTest { Regatta regattaOnTarget = destService.createRegatta( RegattaImpl.getDefaultName(TEST_REGATTA_NAME, TEST_BOAT_CLASS_NAME), TEST_BOAT_CLASS_NAME, - /*startDate*/ null, /*endDate*/ null, regattaUUID, - seriesOnTarget, true, new LowPoint(), courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); + /* startDate */null, /* endDate */null, regattaUUID, seriesOnTarget, true, new LowPoint(), + courseAreaUUID, /* useStartTimeInference */true, OneDesignRankingMetric::new); - raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, - new DummyTrackedRace(raceId, - competitors, regattaOnTarget, null, sourceService.getWindStore())); + raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, new DummyTrackedRace(raceId, competitors, + regattaOnTarget, null, sourceService.getWindStore())); Assert.assertTrue(leaderboardOnTarget.getScoreCorrection().hasCorrectionFor(raceColumnOnTarget)); Competitor competitorOnTarget = domainFactory.getExistingCompetitorById(competitorUUID); @@ -2170,7 +2208,8 @@ public class MasterDataImportTest { competitorsCreatedOnTarget.add(competitorOnTarget); Assert.assertEquals(defaultFleetOnTarget, leaderboardOnTarget.getFleet(null)); - TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, null, sourceService.getWindStore()); + TrackedRace trackedRaceForTarget = new DummyTrackedRace(raceId, competitorsCreatedOnTarget, regattaOnTarget, + null, sourceService.getWindStore()); raceColumnOnTarget.setTrackedRace(defaultFleetOnTarget, trackedRaceForTarget); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogInRaceColumnTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogInRaceColumnTest.java index bedb32a86d3..16dada2c90e 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogInRaceColumnTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogInRaceColumnTest.java @@ -9,7 +9,7 @@ import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.racelog.Flags; @@ -61,7 +61,7 @@ public class RaceLogInRaceColumnTest { server.apply(addLeaderboardColumn); TimePoint t1 = MillisecondsTimePoint.now(); - RaceLogEvent rlEvent = RaceLogEventFactory.INSTANCE.createFlagEvent( + RaceLogEvent rlEvent = new RaceLogFlagEventImpl( t1, author, 0, Flags.CLASS, Flags.NONE, true); Leaderboard leaderboard = racingEventServiceServer.getLeaderboardByName(LEADERBOARDNAME); @@ -118,8 +118,8 @@ public class RaceLogInRacingEventServiceImplTest { TimePoint t2 = new MillisecondsTimePoint(t1.asMillis() + 1000); int passId = 0; boolean isDisplayed = true; - RaceLogFlagEvent rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); - RaceLogFlagEvent rcEvent2 = RaceLogEventFactory.INSTANCE.createFlagEvent(t2, passId, Flags.AP, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent = new RaceLogFlagEventImpl(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent2 = new RaceLogFlagEventImpl(t2, passId, Flags.AP, Flags.NONE, isDisplayed); Leaderboard leaderboard = racingEventServiceServer.getLeaderboardByName(LEADERBOARDNAME); RaceColumn raceColumn = leaderboard.getRaceColumnByName("newColumn"); @@ -197,8 +197,8 @@ public class RaceLogInRacingEventServiceImplTest { TimePoint t2 = new MillisecondsTimePoint(t1.asMillis() + 1000); int passId = 0; boolean isDisplayed = true; - RaceLogFlagEvent rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); - RaceLogFlagEvent rcEvent2 = RaceLogEventFactory.INSTANCE.createFlagEvent(t2, passId, Flags.AP, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent = new RaceLogFlagEventImpl(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent2 = new RaceLogFlagEventImpl(t2, passId, Flags.AP, Flags.NONE, isDisplayed); Leaderboard leaderboard = racingEventServiceServer.getLeaderboardByName(regattaLeaderboardName); RaceColumn raceColumn = leaderboard.getRaceColumnByName("R1"); @@ -276,8 +276,8 @@ public class RaceLogInRacingEventServiceImplTest { TimePoint t2 = new MillisecondsTimePoint(t1.asMillis() + 1000); int passId = 0; boolean isDisplayed = true; - RaceLogFlagEvent rcEvent = RaceLogEventFactory.INSTANCE.createFlagEvent(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); - RaceLogFlagEvent rcEvent2 = RaceLogEventFactory.INSTANCE.createFlagEvent(t2, passId, Flags.AP, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent = new RaceLogFlagEventImpl(t1, passId, Flags.CLASS, Flags.NONE, isDisplayed); + RaceLogFlagEvent rcEvent2 = new RaceLogFlagEventImpl(t2, passId, Flags.AP, Flags.NONE, isDisplayed); Leaderboard leaderboard = racingEventServiceServer.getLeaderboardByName(regattaLeaderboardName); RaceColumn raceColumn = leaderboard.getRaceColumnByName("R1"); diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogOperationalTransformationTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogOperationalTransformationTest.java index 8bfb9aa4db3..25430a3b5d0 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogOperationalTransformationTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/RaceLogOperationalTransformationTest.java @@ -3,7 +3,6 @@ package com.sap.sailing.server.test; import static org.junit.Assert.assertEquals; import java.util.Calendar; -import java.util.Collections; import java.util.GregorianCalendar; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -17,7 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; -import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.server.operationaltransformation.racelog.RaceLogEventWithTransformationSupport; import com.sap.sailing.server.operationaltransformation.racelog.RaceLogStartTimeEventWithTransformationSupport; import com.sap.sse.common.TimePoint; @@ -96,7 +95,7 @@ public class RaceLogOperationalTransformationTest { public void testSimpleApply() { Calendar c = new GregorianCalendar(2013, 6, 7, 13, 59, 33); final MillisecondsTimePoint startTime = new MillisecondsTimePoint(c.getTime()); - RaceLogStartTimeEvent startTimeEvent = new RaceLogStartTimeEventImpl(MillisecondsTimePoint.now(), author, startTime, UUID.randomUUID(), Collections. emptyList(), /* pass ID */ 1, startTime); + RaceLogStartTimeEvent startTimeEvent = new RaceLogStartTimeEventImpl(startTime, author, /* pass ID */ 1, startTime); RaceLogStartTimeEventWithTransformationSupport e = new RaceLogStartTimeEventWithTransformationSupport(startTimeEvent); server.apply(e); serverLatch.countDown(); @@ -140,8 +139,8 @@ public class RaceLogOperationalTransformationTest { final TimePoint createdAt = MillisecondsTimePoint.now(); { RaceLogStartTimeEvent startTimeEventServer = new RaceLogStartTimeEventImpl(createdAt, - author, startTimeServer, UUID.randomUUID(), Collections. emptyList(), /* pass ID */1, - startTimeServer); + startTimeServer, author, UUID.randomUUID(), /* pass ID */1, + startTimeServer, RaceLogRaceStatus.SCHEDULED); RaceLogStartTimeEventWithTransformationSupport eServer = new RaceLogStartTimeEventWithTransformationSupport( startTimeEventServer); server.apply(eServer); @@ -150,8 +149,8 @@ public class RaceLogOperationalTransformationTest { Calendar cClient1 = new GregorianCalendar(2013, 6, 7, 13, 59, 33); final MillisecondsTimePoint startTimeClient1 = new MillisecondsTimePoint(cClient1.getTime()); RaceLogStartTimeEvent startTimeEventClient1 = new RaceLogStartTimeEventImpl(createdAt, - author, startTimeClient1, UUID.randomUUID(), Collections. emptyList(), /* pass ID */1, - startTimeClient1); + startTimeClient1, author, UUID.randomUUID(), /* pass ID */1, + startTimeClient1, RaceLogRaceStatus.SCHEDULED); final RaceLogStartTimeEventWithTransformationSupport eClient1 = new RaceLogStartTimeEventWithTransformationSupport( startTimeEventClient1); client1.apply(eClient1); // this call won't block because server calls apply(Peer, O, int) which first waits for the latch before synchronizing diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java index 1e325949fc2..94b5884d201 100755 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java @@ -72,10 +72,10 @@ import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; import com.sap.sse.common.search.KeywordQuery; import com.sap.sse.common.search.Result; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; public class SearchServiceTest { private RacingEventService server; @@ -267,11 +267,11 @@ public class SearchServiceTest { final LeaderboardSearchResult firstMatch = iterator.next(); Regatta firstFoundRegatta = firstMatch.getRegatta(); assertSame(pfingstbusch29er, firstFoundRegatta); - assertSame(pfingstbusch, firstMatch.getEvent()); + assertSame(pfingstbusch, firstMatch.getEvents().iterator().next()); final LeaderboardSearchResult secondMatch = iterator.next(); Regatta secondFoundRegatta = secondMatch.getRegatta(); assertSame(pfingstbusch470, secondFoundRegatta); - assertSame(pfingstbusch, secondMatch.getEvent()); + assertSame(pfingstbusch, secondMatch.getEvents().iterator().next()); } @Test @@ -282,11 +282,11 @@ public class SearchServiceTest { final LeaderboardSearchResult firstMatch = iter.next(); Regatta earlierStartRegatta = firstMatch.getRegatta(); assertSame(pfingstbusch470, earlierStartRegatta); - assertSame(pfingstbusch, firstMatch.getEvent()); + assertSame(pfingstbusch, firstMatch.getEvents().iterator().next()); final LeaderboardSearchResult secondMatch = iter.next(); Regatta laterStartRegatta = secondMatch.getRegatta(); assertSame(aalRegatta, laterStartRegatta); - assertSame(aalEvent, secondMatch.getEvent()); + assertSame(aalEvent, secondMatch.getEvents().iterator().next()); } @Test @@ -303,11 +303,11 @@ public class SearchServiceTest { final LeaderboardSearchResult expected = searchResults.getHits().iterator().next(); LeaderboardSearchResultBase deserialized = deserializer.deserialize(serializer.serialize(expected)); assertEquals("Pfingstbusch (470)", deserialized.getRegattaName()); - assertEquals(expected.getEvent().getName(), deserialized.getEvent().getName()); - assertEquals(expected.getEvent().getId(), deserialized.getEvent().getId()); - assertEquals(expected.getEvent().getStartDate(), deserialized.getEvent().getStartDate()); - assertEquals(expected.getEvent().getEndDate(), deserialized.getEvent().getEndDate()); - assertEquals(expected.getEvent().getVenue().getName(), deserialized.getEvent().getVenue().getName()); + assertEquals(expected.getEvents().iterator().next().getName(), deserialized.getEvents().iterator().next().getName()); + assertEquals(expected.getEvents().iterator().next().getId(), deserialized.getEvents().iterator().next().getId()); + assertEquals(expected.getEvents().iterator().next().getStartDate(), deserialized.getEvents().iterator().next().getStartDate()); + assertEquals(expected.getEvents().iterator().next().getEndDate(), deserialized.getEvents().iterator().next().getEndDate()); + assertEquals(expected.getEvents().iterator().next().getVenue().getName(), deserialized.getEvents().iterator().next().getVenue().getName()); Iterator expectedLGs = expected.getLeaderboardGroups().iterator(); Iterator deserializedLGs = deserialized.getLeaderboardGroups().iterator(); while (expectedLGs.hasNext()) { diff --git a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java index bf44848d496..d4e925cb997 100644 --- a/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java +++ b/java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/WindByRaceLogTest.java @@ -15,8 +15,8 @@ import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; @@ -133,8 +133,8 @@ public class WindByRaceLogTest { new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); Wind wind2 = new WindImpl(new DegreePosition(49, 3), timeMinus2, new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); - RaceLogWindFixEvent windEvent1 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus3, author, 0, wind1, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent2 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus2, author, 0, wind2, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); raceLog.add(windEvent1); raceLog.add(windEvent2); @@ -163,7 +163,7 @@ public class WindByRaceLogTest { Wind wind1 = new WindImpl(new DegreePosition(50, 4), timeMinus3, new KnotSpeedWithBearingImpl(15, new DegreeBearingImpl(234))); - RaceLogWindFixEvent windEvent1 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); raceLog.add(windEvent1); WindSource source = new WindSourceImpl(WindSourceType.RACECOMMITTEE); @@ -192,9 +192,9 @@ public class WindByRaceLogTest { new KnotSpeedWithBearingImpl(12, new DegreeBearingImpl(123))); Wind wind3 = new WindImpl(new DegreePosition(48, 1), timeMinus2, new KnotSpeedWithBearingImpl(18, new DegreeBearingImpl(270))); - RaceLogWindFixEvent windEvent1 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus3, author, 0, wind1, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent2 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus2, author, 0, wind2, /* isMagnetic */ false); - RaceLogWindFixEvent windEvent3 = RaceLogEventFactory.INSTANCE.createWindFixEvent(timeMinus1, author, 0, wind3, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent1 = new RaceLogWindFixEventImpl(timeMinus3, author, 0, wind1, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent2 = new RaceLogWindFixEventImpl(timeMinus2, author, 0, wind2, /* isMagnetic */ false); + RaceLogWindFixEvent windEvent3 = new RaceLogWindFixEventImpl(timeMinus1, author, 0, wind3, /* isMagnetic */ false); raceLog.add(windEvent1); raceLog.add(windEvent2); diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch b/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch index d6d27bad076..b8211bfa0d2 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy OSX).launch @@ -1,38 +1,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy).launch b/java/com.sap.sailing.server/SailingServer (No Proxy).launch index 1778a15302f..c371bf053ec 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy).launch @@ -30,7 +30,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch index f11b6f01890..dc9901f3bf7 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Cached MTB).launch @@ -29,7 +29,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch index 5b90fb46a63..0007ae993b9 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch index 1ba0c37eca9..60f49469bef 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, Cached MTB).launch @@ -16,14 +16,14 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch index 95208b0b67f..1a60f889076 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate dev).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch index 7f23d8f0f96..8d5f888b611 100644 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8889, auto-replicate).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch index c3f340aee0b..f4451bddc7d 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Jetty on 8890).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch index d4348abb916..66bd4d05cb0 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, Remote Debug SAP VM).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch index a074e3f0d94..17ea3e4ef7f 100755 --- a/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (No Proxy, winddbTest).launch @@ -29,7 +29,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy).launch b/java/com.sap.sailing.server/SailingServer (Proxy).launch index 75e21f67046..011e7e3e70a 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy).launch @@ -30,7 +30,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch index 8b7d5ecf1b4..0b77ad158db 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Jetty on 8889).launch @@ -23,7 +23,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch index 0b255a60e78..28cd75d3397 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, Remote Debug SAP VM).launch @@ -17,13 +17,13 @@ - + - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch index 9402f031eef..5e511ea26f0 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, SwissTiming Live Simulation).launch @@ -22,7 +22,7 @@ - + diff --git a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch index 27a35e87d7a..9559877b5e8 100755 --- a/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch +++ b/java/com.sap.sailing.server/SailingServer (Proxy, winddbTest).launch @@ -24,7 +24,7 @@ - + diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java index 4621cda708a..17a03a3bf9b 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/RacingEventService.java @@ -1,623 +1,623 @@ -package com.sap.sailing.server; - -import java.io.IOException; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.SocketException; -import java.net.URI; -import java.net.URL; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.LeaderboardSearchResult; -import com.sap.sailing.domain.base.LeaderboardSearchResultBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.RegattaRegistry; -import com.sap.sailing.domain.base.RemoteSailingServerReference; -import com.sap.sailing.domain.base.SailingServerConfiguration; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.configuration.DeviceConfiguration; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; -import com.sap.sailing.domain.base.configuration.RegattaConfiguration; -import com.sap.sailing.domain.common.DataImportProgress; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RaceFetcher; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaFetcher; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.media.MediaTrack; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.leaderboard.EventResolver; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.LeaderboardGroupResolver; -import com.sap.sailing.domain.leaderboard.LeaderboardRegistry; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.persistence.DomainObjectFactory; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.polars.PolarDataService; -import com.sap.sailing.domain.racelog.tracking.GPSFixStore; -import com.sap.sailing.domain.ranking.RankingMetricConstructor; -import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.RaceListener; -import com.sap.sailing.domain.tracking.RaceTracker; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRegatta; -import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; -import com.sap.sailing.domain.tracking.TrackerManager; -import com.sap.sailing.domain.tracking.WindStore; -import com.sap.sailing.server.masterdata.DataImportLockWithProgress; -import com.sap.sailing.server.simulation.SimulationService; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.TypeBasedServiceFinderFactory; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Triple; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.search.KeywordQuery; -import com.sap.sse.common.search.Result; -import com.sap.sse.common.search.Searchable; -import com.sap.sse.filestorage.FileStorageManagementService; -import com.sap.sse.replication.impl.ReplicableWithObjectInputStream; - -/** - * An OSGi service that can be used to track boat races using a TracTrac connector that pushes live GPS boat location, - * waypoint, coarse and mark passing data. - *

    - * - * If a race/regatta is already being tracked, another {@link #addTracTracRace(URL, URI, URI, WindStore, long)} or - * {@link #addRegatta(URL, URI, URI, WindStore, long)} call will have no effect, even if a different {@link WindStore} - * is requested. - *

    - * - * When the tracking of a race/regatta is {@link #stopTracking(Regatta, RaceDefinition) stopped}, the next time it's - * started to be tracked, a new {@link TrackedRace} at least will be constructed. This also means that when a - * {@link TrackedRegatta} exists that still holds other {@link TrackedRace}s, the no longer tracked {@link TrackedRace} - * will be removed from the {@link TrackedRegatta}. corresponding information is removed also from the - * {@link DomainFactory}'s caches to ensure that clean, fresh data is received should another tracking request be issued - * later. - *

    - * - * During receiving the initial load for a replication in {@link #initiallyFillFromInternal(java.io.ObjectInputStream)}, - * tracked regattas read from the stream are observed (see {@link RaceListener}) by this object for automatic updates to - * the default leaderboard and for automatic linking to leaderboard columns. It is assumed that no explicit replication - * of these operations will happen based on the changes performed on the replication master. - * - * @author Axel Uhl (d043530) - * - */ -public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetcher, RegattaRegistry, RaceFetcher, - LeaderboardRegistry, EventResolver, LeaderboardGroupResolver, TrackerManager, Searchable, - ReplicableWithObjectInputStream>, RaceLogResolver { - @Override - Regatta getRegatta(RegattaName regattaName); - - @Override - RaceDefinition getRace(RegattaAndRaceIdentifier raceIdentifier); - - DynamicTrackedRace getTrackedRace(Regatta regatta, RaceDefinition race); - - DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier raceIdentifier); - - /** - * Obtains an unmodifiable map of the leaderboard configured in this service keyed by their names. - */ - Map getLeaderboards(); - - /** - * @return a leaderboard whose {@link Leaderboard#getName()} method returns the value of the name - * parameter, or null if no such leaderboard is known to this service - */ - Leaderboard getLeaderboardByName(String name); - - /** - * Looks at the mark tracks in the tracked races attached to the leaderboard. If it doesn't find a - * track for the mark requested there which has fixes before and after timePoint (to - * ensure that no track cropping has taken place, removing the fixes for the interesting time period), looks in the - * leaderboard's regatta log and the specific raceLog (if provided) or all race logs attached to the - * leaderboard (if not provided) for device mappings for the mark and tries to load fixes from the - * {@link GPSFixStore}. The latter is only necessary if the mark isn't found in any tracked race with fixes - * surrounding timePoint because should there be a tracked race in the leaderboard that has the mark - * then it will also have received the fixes from the {@link GPSFixStore} through the regatta log mapping. - *

    - * - * @return the position obtained by interpolation but never extrapolation from the track identified as described - * above - */ - Position getMarkPosition(Mark mark, LeaderboardThatHasRegattaLike leaderboard, TimePoint timePoint, RaceLog raceLog); - - /** - * Stops tracking all races of the regatta specified. This will also stop tracking wind for all races of this regatta. - * See {@link #stopTrackingWind(Regatta, RaceDefinition)}. If there were multiple calls to - * {@link #addTracTracRace(URL, URI, URI, WindStore, long)} with an equal combination of URLs/URIs, the {@link TracTracRaceTracker} - * already tracking the race was re-used. The trackers will be stopped by this call regardless of how many calls - * were made that ensured they were tracking. - */ - void stopTracking(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; - - /** - * Removes race and any corresponding {@link #getTrackedRace(Regatta, RaceDefinition) tracked race} - * from this service. If it was the last {@link RaceDefinition} in its {@link Regatta} and the regatta - * {@link Regatta#isPersistent() is not stored persistently}, the regatta is removed as well and will no - * longer be returned by {@link #getAllRegattas()}. The wind tracking is stopped for race. - *

    - * - * Any {@link RaceTracker} for which race is the last race tracked that is still reachable - * from {@link #getAllRegattas()} will be {@link RaceTracker#stop(boolean) stopped}. - * - * The race will be also removed from all leaderboards containing a column that has race's - * {@link #getTrackedRace(Regatta, RaceDefinition) corresponding} {@link TrackedRace} as its - * {@link RaceColumn#getTrackedRace(Fleet)}. - * - * @param regatta - * the regatta from which to remove the race - * @param race - * the race to remove - */ - void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,InterruptedException; - - /** - * @param port - * the UDP port on which to listen for incoming messages from Expedition clients - * @param correctByDeclination - * An optional service to convert the wind bearings (which the receiver may - * believe to be true bearings) from magnetic to true bearings. - * @throws SocketException - * thrown, e.g., in case there is already another listener on the port requested - */ - void startTrackingWind(Regatta regatta, RaceDefinition race, boolean correctByDeclination) throws Exception; - - void stopTrackingWind(Regatta regatta, RaceDefinition race) throws SocketException, IOException; - - /** - * The {@link Triple#getC() third component} of the triples returned is a wind tracker-specific - * comment where a wind tracker may provide information such as its type name or, if applicable, - * connectivity information such as the network port on which it receives wind information. - */ - Iterable> getWindTrackedRaces(); - - /** - * Creates a new leaderboard with the name specified. - * @param discardThresholds - * Tells the thresholds from which on a next higher number of worst races will be discarded per - * competitor. Example: [3, 6] means that starting from three races the single worst race - * will be discarded; starting from six races, the two worst races per competitor are discarded. - * - * @return the leaderboard created - */ - FlexibleLeaderboard addFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringScheme scoringScheme, Serializable courseAreaId); - - RegattaLeaderboard addRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds); - - void removeLeaderboard(String leaderboardName); - - /** - * Renames a leaderboard. If a leaderboard by the name oldName does not exist in {@link #getLeaderboards()}, - * or if a leaderboard with the name newName already exists, an {@link IllegalArgumentException} is thrown. - * If the method completes normally, the rename has been successful, and the leaderboard previously obtained by calling - * {@link #getLeaderboardByName(String) getLeaderboardByName(oldName)} can now be obtained by calling - * {@link #getLeaderboardByName(String) getLeaderboardByName(newName)}. - */ - void renameLeaderboard(String oldName, String newName); - - RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace); - - void moveLeaderboardColumnUp(String leaderboardName, String columnName); - - void moveLeaderboardColumnDown(String leaderboardName, String columnName); - - void removeLeaderboardColumn(String leaderboardName, String columnName); - - void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName); - - /** - * @see RaceColumn#setFactor(Double) - */ - void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double factor); - - /** - * Updates the leaderboard data in the persistent store - */ - void updateStoredLeaderboard(Leaderboard leaderboard); - - void updateStoredRegatta(Regatta regatta); - - void stopTrackingAndRemove(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; - - /** - * Removes the regatta as well as all regatta leaderboards for that regatta - */ - void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; - - /** - * Removes the given series - */ - void removeSeries(Series series) throws MalformedURLException, IOException, InterruptedException; - - DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier); - - /** - * Obtains an unmodifiable map of the leaderboard groups configured in this service keyed by their names. - */ - Map getLeaderboardGroups(); - - /** - * Creates a new group with the name groupName, the description desciption and the - * leaderboards with the names in leaderboardNames and saves it in the database. - * @param id TODO - * @param groupName - * The name of the new group - * @param description - * The description of the new group - * @param displayName TODO - * @param displayGroupsInReverseOrder TODO - * @param leaderboardNames - * The names of the leaderboards, which should be contained by the new group.
    - * If there isn't a leaderboard with one of these names an {@link IllegalArgumentException} is thrown. - * @return The new leaderboard group - */ - LeaderboardGroup addLeaderboardGroup(UUID id, String groupName, String description, - String displayName, boolean displayGroupsInReverseOrder, List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType); - - /** - * Removes the group with the name groupName from the service and the database. - * @param groupName The name of the group which shall be removed. - */ - void removeLeaderboardGroup(String groupName); - - /** - * Renames the group with the name oldName to the newName.
    - * If there's no group with the name oldName or there's already a group with the name - * newName a {@link IllegalArgumentException} is thrown. - * - * @param oldName The old name of the group - * @param newName The new name of the group - */ - void renameLeaderboardGroup(String oldName, String newName); - - /** - * Updates the group data in the persistant store. - */ - void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup); - - DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore, - long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator); - - Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id); - - /** - * @param series the series must not have any {@link RaceColumn}s yet - */ - Regatta createRegatta(String regattaName, String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, - boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, - boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor); - - Regatta updateRegatta(RegattaIdentifier regattaIdentifier, TimePoint startDate, TimePoint endDate, Serializable newDefaultCourseAreaId, RegattaConfiguration regattaConfiguration, Iterable series, boolean useStartTimeInference); - - /** - * Adds raceDefinition to the {@link Regatta} such that it will appear in {@link Regatta#getAllRaces()} - * and {@link Regatta#getRaceByName(String)}. - * - * @param addToRegatta identifier of an regatta that must exist already - */ - void addRace(RegattaIdentifier addToRegatta, RaceDefinition raceDefinition); - - void updateLeaderboardGroup(String oldName, String newName, String description, String displayName, - List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType); - - /** - * @return a thread-safe copy of the events currently known by the service; it's safe for callers to iterate over - * the iterable returned, and no risk of a {@link ConcurrentModificationException} exists - */ - Iterable getAllEvents(); - - /** - * Creates a new event with the name eventName, the venue venue and the regattas with the - * names in regattaNames, saves it in the database and replicates it. Use for TESTING only! - * - * @param eventName - * The name of the new event - * @param eventDescription TODO - * @param startDate - * The start date of the event - * @param endDate - * The end date of the event - * @param isPublic - * Indicates whether the event is public accessible via the publication URL or not - * @param id - * The id of the new event - * @param venue - * The name of the venue of the new event - * @return The new event - */ - Event addEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venueName, boolean isPublic, UUID id); - - /** - * Updates a sailing event with the name eventName, the venuevenue and the regattas with - * the names in regattaNames and updates it in the database. - * @param eventName - * The name of the event to update - * @param startDate - * The start date of the event - * @param endDate - * The end date of the event - * @param venueName - * The name of the venue of the event - * @param isPublic - * Indicates whether the event is public accessible via the publication URL or not - * @return The new event - */ - void updateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, - String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, - Iterable images, Iterable videos); - - /** - * Renames a sailing event. If a sailing event by the name oldName does not exist in {@link #getEvents()}, - * or if a event with the name newName already exists, an {@link IllegalArgumentException} is thrown. - * If the method completes normally, the rename has been successful, and the event previously obtained by calling - * {@link #getEventByName(String) getEventByName(oldName)} can now be obtained by calling - * {@link #getEventByName(String) getEventByName(newName)}. - */ - void renameEvent(UUID id, String newEventName); - - void removeEvent(UUID id); - - - /** - * @return a thread-safe copy of the events (or the exception that occurred trying to obtain the events; arranged in - * a {@link Util.Pair}) of from all sailing server instances currently known by the service; it's safe for - * callers to iterate over the iterable returned, and no risk of a {@link ConcurrentModificationException} - * exists - */ - Map, Exception>> getPublicEventsOfAllSailingServers(); - - RemoteSailingServerReference addRemoteSailingServerReference(String name, URL url); - - void removeRemoteSailingServerReference(String name); - - - CourseArea[] addCourseAreas(UUID eventId, String[] courseAreaNames, UUID[] courseAreaIds); - - com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory(); - - CourseArea getCourseArea(Serializable courseAreaId); - - /** - * Adds the specified mediaTrack to the in-memory media library. - * Important note: Only if mediaTrack.dbId != null the mediaTrack will be persisted in the the database. - * @param mediaTrack - */ - void mediaTrackAdded(MediaTrack mediaTrack); - - /** - * Calling mediaTrackAdded for every entry in the specified collection. - * @param mediaTracks - */ - void mediaTracksAdded(Collection mediaTracks); - - void mediaTrackTitleChanged(MediaTrack mediaTrack); - - void mediaTrackUrlChanged(MediaTrack mediaTrack); - - void mediaTrackStartTimeChanged(MediaTrack mediaTrack); - - void mediaTrackDurationChanged(MediaTrack mediaTrack); - - void mediaTrackAssignedRacesChanged(MediaTrack mediaTrack); - - void mediaTrackDeleted(MediaTrack mediaTrack); - - /** - * In contrast to mediaTracksAdded, this method takes mediaTracks with a given dbId. - * Checks if the track already exists in the library and the database and adds/stores it - * accordingly. If a track already exists and override, its properties are checked for changes - * @param mediaTrack - * @param override If true, track properties (title, url, start time, duration, not mime type!) will be - * overwritten with the values from the track to be imported. - */ - void mediaTracksImported(Collection mediaTracksToImport, boolean override); - - Collection getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier); - - Collection getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier); - - Collection getAllMediaTracks(); - - void reloadRaceLog(String leaderboardName, String raceColumnName, String fleetName); - - RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName); - - /** - * @param rankingMetricConstructor TODO - * @return a pair with the found or created regatta, and a boolean that tells whether the regatta was created during - * the call - */ - Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, String boatClassName, - TimePoint startDate, TimePoint endDate, Serializable id, - Iterable series, boolean persistent, ScoringScheme scoringScheme, - Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor); - - /** - * @return map where keys are the toString() representation of the {@link RaceDefinition#getId() IDs} of races passed to - * {@link #setRegattaForRace(Regatta, RaceDefinition)}. It helps remember the connection between races and regattas. - */ - ConcurrentHashMap getPersistentRegattasForRaceIDs(); - - Event createEventWithoutReplication(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venue, - boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, Iterable images, - Iterable videos); - - void setRegattaForRace(Regatta regatta, String raceIdAsString); - - CourseArea[] addCourseAreasWithoutReplication(UUID eventId, UUID[] courseAreaIds, String[] courseAreaNames); - - CourseArea[] removeCourseAreaWithoutReplication(UUID eventId, UUID[] courseAreaIds); - - /** - * Returns a mobile device's configuration. - * @param identifier of the client (may include event) - * @return the {@link DeviceConfiguration} - */ - DeviceConfiguration getDeviceConfiguration(DeviceConfigurationIdentifier identifier); - - /** - * Adds a device configuration. - * @param matcher defining for which the configuration applies. - * @param configuration of the device. - */ - void createOrUpdateDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration); - - /** - * Removes a configuration by its matching object. - * @param matcher - */ - void removeDeviceConfiguration(DeviceConfigurationMatcher matcher); - - /** - * Returns all configurations and their matching objects. - * @return the {@link DeviceConfiguration}s. - */ - Map getAllDeviceConfigurations(); - - /** - * Forces a new start time on the RaceLog identified by the passed parameters. - * @param leaderboardName name of the RaceLog's leaderboard. - * @param raceColumnName name of the RaceLog's column - * @param fleetName name of the RaceLog's fleet - * @param authorName name of the {@link AbstractLogEventAuthor} the {@link RaceLogStartTimeEvent} will be created with - * @param authorPriority priority of the author. - * @param passId Pass identifier of the new start time event. - * @param logicalTimePoint logical {@link TimePoint} of the new event. - * @param startTime the new Start-Time - * @return - */ - TimePoint setStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName, String authorName, - int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime, RacingProcedureType racingProcedure); - - /** - * Gets the start time, pass identifier and racing procedure for the queried race. Start time might be null. - */ - Util.Triple getStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName); - - MongoObjectFactory getMongoObjectFactory(); - - DomainObjectFactory getDomainObjectFactory(); - - WindStore getWindStore(); - - PolarDataService getPolarDataService(); - - SimulationService getSimulationService(); - - GPSFixStore getGPSFixStore(); - - RaceTracker getRaceTrackerById(Object id); - - AbstractLogEventAuthor getServerAuthor(); - - CompetitorStore getCompetitorStore(); - - TypeBasedServiceFinderFactory getTypeBasedServiceFinderFactory(); - - /** - * This lock exists to allow only one master data import at a time to avoid situation where multiple Imports - * override each other in unpredictable fashion - */ - DataImportLockWithProgress getDataImportLock(); - - DataImportProgress createOrUpdateDataImportProgressWithReplication(UUID importOperationId, - double overallProgressPct, - String subProgressName, double subProgressPct); - - DataImportProgress createOrUpdateDataImportProgressWithoutReplication(UUID importOperationId, - double overallProgressPct, - String subProgressName, double subProgressPct); - - void setDataImportFailedWithReplication(UUID importOperationId, String errorMessage); - - void setDataImportFailedWithoutReplication(UUID importOperationId, String errorMessage); - - void setDataImportDeleteProgressFromMapTimerWithReplication(UUID importOperationId); - - void setDataImportDeleteProgressFromMapTimerWithoutReplication(UUID importOperationId); - - /** - * For the reference to a remote sailing server, updates its events cache and returns the event list - * or, if fetching the event list from the remote server did fail, the exception for which it failed. - */ - Util.Pair, Exception> updateRemoteServerEventCacheSynchronously(RemoteSailingServerReference ref); - - /** - * Searches the content of this server, not that of any remote servers referenced by any {@link RemoteSailingServerReference}s. - */ - @Override - Result search(KeywordQuery query); - - /** - * Searches a specific remote server whose reference has the {@link RemoteSailingServerReference#getName() name} - * remoteServerReferenceName. If a remote server reference with that name is not known, - * null is returned. Otherwise, a non-null and possibly empty search result set is - * returned. - */ - Result searchRemotely(String remoteServerReferenceName, KeywordQuery query); - - /** - * Gets the configuration of the local sailing server instances. - */ - SailingServerConfiguration getSailingServerConfiguration(); - - void updateServerConfiguration(SailingServerConfiguration serverConfiguration); - - /** - * References to remote servers may be dead or alive. This is internally determined by regularly polling those - * servers for their events list. If the events list cannot be successfully retrieved, the server is considered "dead." - * This method returns the "live" server references. - */ - Iterable getLiveRemoteServerReferences(); - - RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName); - - void addRegattaWithoutReplication(Regatta regatta); - - void addEventWithoutReplication(Event event); - - /** - * Adds the leaderboard group to this service; if the group has an overall leaderboard, the overall leaderboard - * is added to this service as well. For both, the group and the overall leaderboard, any previously existing - * objects by the same name of that type will be replaced. - */ - void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup); - - /** - * @return {@code null} if no service can be found in the OSGi registry - */ - FileStorageManagementService getFileStorageManagementService(); - - ClassLoader getCombinedMasterDataClassLoader(); - - Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint); -} +package com.sap.sailing.server; + +import java.io.IOException; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.SocketException; +import java.net.URI; +import java.net.URL; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.LeaderboardSearchResult; +import com.sap.sailing.domain.base.LeaderboardSearchResultBase; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.RegattaRegistry; +import com.sap.sailing.domain.base.RemoteSailingServerReference; +import com.sap.sailing.domain.base.SailingServerConfiguration; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; +import com.sap.sailing.domain.base.configuration.RegattaConfiguration; +import com.sap.sailing.domain.common.DataImportProgress; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceFetcher; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaFetcher; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.domain.leaderboard.EventResolver; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.LeaderboardGroupResolver; +import com.sap.sailing.domain.leaderboard.LeaderboardRegistry; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.polars.PolarDataService; +import com.sap.sailing.domain.racelog.tracking.GPSFixStore; +import com.sap.sailing.domain.ranking.RankingMetricConstructor; +import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.RaceListener; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRegatta; +import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; +import com.sap.sailing.domain.tracking.TrackerManager; +import com.sap.sailing.domain.tracking.WindStore; +import com.sap.sailing.server.masterdata.DataImportLockWithProgress; +import com.sap.sailing.server.simulation.SimulationService; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.TypeBasedServiceFinderFactory; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.search.KeywordQuery; +import com.sap.sse.common.search.Result; +import com.sap.sse.common.search.Searchable; +import com.sap.sse.filestorage.FileStorageManagementService; +import com.sap.sse.replication.impl.ReplicableWithObjectInputStream; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +/** + * An OSGi service that can be used to track boat races using a TracTrac connector that pushes live GPS boat location, + * waypoint, coarse and mark passing data. + *

    + * + * If a race/regatta is already being tracked, another {@link #addTracTracRace(URL, URI, URI, WindStore, long)} or + * {@link #addRegatta(URL, URI, URI, WindStore, long)} call will have no effect, even if a different {@link WindStore} + * is requested. + *

    + * + * When the tracking of a race/regatta is {@link #stopTracking(Regatta, RaceDefinition) stopped}, the next time it's + * started to be tracked, a new {@link TrackedRace} at least will be constructed. This also means that when a + * {@link TrackedRegatta} exists that still holds other {@link TrackedRace}s, the no longer tracked {@link TrackedRace} + * will be removed from the {@link TrackedRegatta}. corresponding information is removed also from the + * {@link DomainFactory}'s caches to ensure that clean, fresh data is received should another tracking request be issued + * later. + *

    + * + * During receiving the initial load for a replication in {@link #initiallyFillFromInternal(java.io.ObjectInputStream)}, + * tracked regattas read from the stream are observed (see {@link RaceListener}) by this object for automatic updates to + * the default leaderboard and for automatic linking to leaderboard columns. It is assumed that no explicit replication + * of these operations will happen based on the changes performed on the replication master. + * + * @author Axel Uhl (d043530) + * + */ +public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetcher, RegattaRegistry, RaceFetcher, + LeaderboardRegistry, EventResolver, LeaderboardGroupResolver, TrackerManager, Searchable, + ReplicableWithObjectInputStream>, RaceLogResolver { + @Override + Regatta getRegatta(RegattaName regattaName); + + @Override + RaceDefinition getRace(RegattaAndRaceIdentifier raceIdentifier); + + DynamicTrackedRace getTrackedRace(Regatta regatta, RaceDefinition race); + + DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier raceIdentifier); + + /** + * Obtains an unmodifiable map of the leaderboard configured in this service keyed by their names. + */ + Map getLeaderboards(); + + /** + * @return a leaderboard whose {@link Leaderboard#getName()} method returns the value of the name + * parameter, or null if no such leaderboard is known to this service + */ + Leaderboard getLeaderboardByName(String name); + + /** + * Looks at the mark tracks in the tracked races attached to the leaderboard. If it doesn't find a + * track for the mark requested there which has fixes before and after timePoint (to + * ensure that no track cropping has taken place, removing the fixes for the interesting time period), looks in the + * leaderboard's regatta log and the specific raceLog (if provided) or all race logs attached to the + * leaderboard (if not provided) for device mappings for the mark and tries to load fixes from the + * {@link GPSFixStore}. The latter is only necessary if the mark isn't found in any tracked race with fixes + * surrounding timePoint because should there be a tracked race in the leaderboard that has the mark + * then it will also have received the fixes from the {@link GPSFixStore} through the regatta log mapping. + *

    + * + * @return the position obtained by interpolation but never extrapolation from the track identified as described + * above + */ + Position getMarkPosition(Mark mark, LeaderboardThatHasRegattaLike leaderboard, TimePoint timePoint, RaceLog raceLog); + + /** + * Stops tracking all races of the regatta specified. This will also stop tracking wind for all races of this regatta. + * See {@link #stopTrackingWind(Regatta, RaceDefinition)}. If there were multiple calls to + * {@link #addTracTracRace(URL, URI, URI, WindStore, long)} with an equal combination of URLs/URIs, the {@link TracTracRaceTracker} + * already tracking the race was re-used. The trackers will be stopped by this call regardless of how many calls + * were made that ensured they were tracking. + */ + void stopTracking(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; + + /** + * Removes race and any corresponding {@link #getTrackedRace(Regatta, RaceDefinition) tracked race} + * from this service. If it was the last {@link RaceDefinition} in its {@link Regatta} and the regatta + * {@link Regatta#isPersistent() is not stored persistently}, the regatta is removed as well and will no + * longer be returned by {@link #getAllRegattas()}. The wind tracking is stopped for race. + *

    + * + * Any {@link RaceTracker} for which race is the last race tracked that is still reachable + * from {@link #getAllRegattas()} will be {@link RaceTracker#stop(boolean) stopped}. + * + * The race will be also removed from all leaderboards containing a column that has race's + * {@link #getTrackedRace(Regatta, RaceDefinition) corresponding} {@link TrackedRace} as its + * {@link RaceColumn#getTrackedRace(Fleet)}. + * + * @param regatta + * the regatta from which to remove the race + * @param race + * the race to remove + */ + void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException,InterruptedException; + + /** + * @param port + * the UDP port on which to listen for incoming messages from Expedition clients + * @param correctByDeclination + * An optional service to convert the wind bearings (which the receiver may + * believe to be true bearings) from magnetic to true bearings. + * @throws SocketException + * thrown, e.g., in case there is already another listener on the port requested + */ + void startTrackingWind(Regatta regatta, RaceDefinition race, boolean correctByDeclination) throws Exception; + + void stopTrackingWind(Regatta regatta, RaceDefinition race) throws SocketException, IOException; + + /** + * The {@link Triple#getC() third component} of the triples returned is a wind tracker-specific + * comment where a wind tracker may provide information such as its type name or, if applicable, + * connectivity information such as the network port on which it receives wind information. + */ + Iterable> getWindTrackedRaces(); + + /** + * Creates a new leaderboard with the name specified. + * @param discardThresholds + * Tells the thresholds from which on a next higher number of worst races will be discarded per + * competitor. Example: [3, 6] means that starting from three races the single worst race + * will be discarded; starting from six races, the two worst races per competitor are discarded. + * + * @return the leaderboard created + */ + FlexibleLeaderboard addFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, int[] discardThresholds, ScoringScheme scoringScheme, Serializable courseAreaId); + + RegattaLeaderboard addRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, int[] discardThresholds); + + void removeLeaderboard(String leaderboardName); + + /** + * Renames a leaderboard. If a leaderboard by the name oldName does not exist in {@link #getLeaderboards()}, + * or if a leaderboard with the name newName already exists, an {@link IllegalArgumentException} is thrown. + * If the method completes normally, the rename has been successful, and the leaderboard previously obtained by calling + * {@link #getLeaderboardByName(String) getLeaderboardByName(oldName)} can now be obtained by calling + * {@link #getLeaderboardByName(String) getLeaderboardByName(newName)}. + */ + void renameLeaderboard(String oldName, String newName); + + RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace); + + void moveLeaderboardColumnUp(String leaderboardName, String columnName); + + void moveLeaderboardColumnDown(String leaderboardName, String columnName); + + void removeLeaderboardColumn(String leaderboardName, String columnName); + + void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName); + + /** + * @see RaceColumn#setFactor(Double) + */ + void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double factor); + + /** + * Updates the leaderboard data in the persistent store + */ + void updateStoredLeaderboard(Leaderboard leaderboard); + + void updateStoredRegatta(Regatta regatta); + + void stopTrackingAndRemove(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; + + /** + * Removes the regatta as well as all regatta leaderboards for that regatta + */ + void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException; + + /** + * Removes the given series + */ + void removeSeries(Series series) throws MalformedURLException, IOException, InterruptedException; + + DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier); + + /** + * Obtains an unmodifiable map of the leaderboard groups configured in this service keyed by their names. + */ + Map getLeaderboardGroups(); + + /** + * Creates a new group with the name groupName, the description desciption and the + * leaderboards with the names in leaderboardNames and saves it in the database. + * @param id TODO + * @param groupName + * The name of the new group + * @param description + * The description of the new group + * @param displayName TODO + * @param displayGroupsInReverseOrder TODO + * @param leaderboardNames + * The names of the leaderboards, which should be contained by the new group.
    + * If there isn't a leaderboard with one of these names an {@link IllegalArgumentException} is thrown. + * @return The new leaderboard group + */ + LeaderboardGroup addLeaderboardGroup(UUID id, String groupName, String description, + String displayName, boolean displayGroupsInReverseOrder, List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType); + + /** + * Removes the group with the name groupName from the service and the database. + * @param groupName The name of the group which shall be removed. + */ + void removeLeaderboardGroup(String groupName); + + /** + * Renames the group with the name oldName to the newName.
    + * If there's no group with the name oldName or there's already a group with the name + * newName a {@link IllegalArgumentException} is thrown. + * + * @param oldName The old name of the group + * @param newName The new name of the group + */ + void renameLeaderboardGroup(String oldName, String newName); + + /** + * Updates the group data in the persistant store. + */ + void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup); + + DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, GPSFixStore gpsFixStore, + long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator); + + Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id); + + /** + * @param series the series must not have any {@link RaceColumn}s yet + */ + Regatta createRegatta(String regattaName, String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, Iterable series, + boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId, + boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor); + + Regatta updateRegatta(RegattaIdentifier regattaIdentifier, TimePoint startDate, TimePoint endDate, Serializable newDefaultCourseAreaId, RegattaConfiguration regattaConfiguration, Iterable series, boolean useStartTimeInference); + + /** + * Adds raceDefinition to the {@link Regatta} such that it will appear in {@link Regatta#getAllRaces()} + * and {@link Regatta#getRaceByName(String)}. + * + * @param addToRegatta identifier of an regatta that must exist already + */ + void addRace(RegattaIdentifier addToRegatta, RaceDefinition raceDefinition); + + void updateLeaderboardGroup(String oldName, String newName, String description, String displayName, + List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType); + + /** + * @return a thread-safe copy of the events currently known by the service; it's safe for callers to iterate over + * the iterable returned, and no risk of a {@link ConcurrentModificationException} exists + */ + Iterable getAllEvents(); + + /** + * Creates a new event with the name eventName, the venue venue and the regattas with the + * names in regattaNames, saves it in the database and replicates it. Use for TESTING only! + * + * @param eventName + * The name of the new event + * @param eventDescription TODO + * @param startDate + * The start date of the event + * @param endDate + * The end date of the event + * @param isPublic + * Indicates whether the event is public accessible via the publication URL or not + * @param id + * The id of the new event + * @param venue + * The name of the venue of the new event + * @return The new event + */ + Event addEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venueName, boolean isPublic, UUID id); + + /** + * Updates a sailing event with the name eventName, the venuevenue and the regattas with + * the names in regattaNames and updates it in the database. + * @param eventName + * The name of the event to update + * @param startDate + * The start date of the event + * @param endDate + * The end date of the event + * @param venueName + * The name of the venue of the event + * @param isPublic + * Indicates whether the event is public accessible via the publication URL or not + * @return The new event + */ + void updateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, + String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, + Iterable images, Iterable videos); + + /** + * Renames a sailing event. If a sailing event by the name oldName does not exist in {@link #getEvents()}, + * or if a event with the name newName already exists, an {@link IllegalArgumentException} is thrown. + * If the method completes normally, the rename has been successful, and the event previously obtained by calling + * {@link #getEventByName(String) getEventByName(oldName)} can now be obtained by calling + * {@link #getEventByName(String) getEventByName(newName)}. + */ + void renameEvent(UUID id, String newEventName); + + void removeEvent(UUID id); + + + /** + * @return a thread-safe copy of the events (or the exception that occurred trying to obtain the events; arranged in + * a {@link Util.Pair}) of from all sailing server instances currently known by the service; it's safe for + * callers to iterate over the iterable returned, and no risk of a {@link ConcurrentModificationException} + * exists + */ + Map, Exception>> getPublicEventsOfAllSailingServers(); + + RemoteSailingServerReference addRemoteSailingServerReference(String name, URL url); + + void removeRemoteSailingServerReference(String name); + + + CourseArea[] addCourseAreas(UUID eventId, String[] courseAreaNames, UUID[] courseAreaIds); + + com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory(); + + CourseArea getCourseArea(Serializable courseAreaId); + + /** + * Adds the specified mediaTrack to the in-memory media library. + * Important note: Only if mediaTrack.dbId != null the mediaTrack will be persisted in the the database. + * @param mediaTrack + */ + void mediaTrackAdded(MediaTrack mediaTrack); + + /** + * Calling mediaTrackAdded for every entry in the specified collection. + * @param mediaTracks + */ + void mediaTracksAdded(Collection mediaTracks); + + void mediaTrackTitleChanged(MediaTrack mediaTrack); + + void mediaTrackUrlChanged(MediaTrack mediaTrack); + + void mediaTrackStartTimeChanged(MediaTrack mediaTrack); + + void mediaTrackDurationChanged(MediaTrack mediaTrack); + + void mediaTrackAssignedRacesChanged(MediaTrack mediaTrack); + + void mediaTrackDeleted(MediaTrack mediaTrack); + + /** + * In contrast to mediaTracksAdded, this method takes mediaTracks with a given dbId. + * Checks if the track already exists in the library and the database and adds/stores it + * accordingly. If a track already exists and override, its properties are checked for changes + * @param mediaTrack + * @param override If true, track properties (title, url, start time, duration, not mime type!) will be + * overwritten with the values from the track to be imported. + */ + void mediaTracksImported(Collection mediaTracksToImport, boolean override); + + Collection getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier); + + Collection getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier); + + Collection getAllMediaTracks(); + + void reloadRaceLog(String leaderboardName, String raceColumnName, String fleetName); + + RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName); + + /** + * @param rankingMetricConstructor TODO + * @return a pair with the found or created regatta, and a boolean that tells whether the regatta was created during + * the call + */ + Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, String boatClassName, + TimePoint startDate, TimePoint endDate, Serializable id, + Iterable series, boolean persistent, ScoringScheme scoringScheme, + Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor); + + /** + * @return map where keys are the toString() representation of the {@link RaceDefinition#getId() IDs} of races passed to + * {@link #setRegattaForRace(Regatta, RaceDefinition)}. It helps remember the connection between races and regattas. + */ + ConcurrentHashMap getPersistentRegattasForRaceIDs(); + + Event createEventWithoutReplication(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venue, + boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, Iterable images, + Iterable videos); + + void setRegattaForRace(Regatta regatta, String raceIdAsString); + + CourseArea[] addCourseAreasWithoutReplication(UUID eventId, UUID[] courseAreaIds, String[] courseAreaNames); + + CourseArea[] removeCourseAreaWithoutReplication(UUID eventId, UUID[] courseAreaIds); + + /** + * Returns a mobile device's configuration. + * @param identifier of the client (may include event) + * @return the {@link DeviceConfiguration} + */ + DeviceConfiguration getDeviceConfiguration(DeviceConfigurationIdentifier identifier); + + /** + * Adds a device configuration. + * @param matcher defining for which the configuration applies. + * @param configuration of the device. + */ + void createOrUpdateDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration); + + /** + * Removes a configuration by its matching object. + * @param matcher + */ + void removeDeviceConfiguration(DeviceConfigurationMatcher matcher); + + /** + * Returns all configurations and their matching objects. + * @return the {@link DeviceConfiguration}s. + */ + Map getAllDeviceConfigurations(); + + /** + * Forces a new start time on the RaceLog identified by the passed parameters. + * @param leaderboardName name of the RaceLog's leaderboard. + * @param raceColumnName name of the RaceLog's column + * @param fleetName name of the RaceLog's fleet + * @param authorName name of the {@link AbstractLogEventAuthor} the {@link RaceLogStartTimeEvent} will be created with + * @param authorPriority priority of the author. + * @param passId Pass identifier of the new start time event. + * @param logicalTimePoint logical {@link TimePoint} of the new event. + * @param startTime the new Start-Time + * @return + */ + TimePoint setStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName, String authorName, + int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime, RacingProcedureType racingProcedure); + + /** + * Gets the start time, pass identifier and racing procedure for the queried race. Start time might be null. + */ + Util.Triple getStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName); + + MongoObjectFactory getMongoObjectFactory(); + + DomainObjectFactory getDomainObjectFactory(); + + WindStore getWindStore(); + + PolarDataService getPolarDataService(); + + SimulationService getSimulationService(); + + GPSFixStore getGPSFixStore(); + + RaceTracker getRaceTrackerById(Object id); + + AbstractLogEventAuthor getServerAuthor(); + + CompetitorStore getCompetitorStore(); + + TypeBasedServiceFinderFactory getTypeBasedServiceFinderFactory(); + + /** + * This lock exists to allow only one master data import at a time to avoid situation where multiple Imports + * override each other in unpredictable fashion + */ + DataImportLockWithProgress getDataImportLock(); + + DataImportProgress createOrUpdateDataImportProgressWithReplication(UUID importOperationId, + double overallProgressPct, + String subProgressName, double subProgressPct); + + DataImportProgress createOrUpdateDataImportProgressWithoutReplication(UUID importOperationId, + double overallProgressPct, + String subProgressName, double subProgressPct); + + void setDataImportFailedWithReplication(UUID importOperationId, String errorMessage); + + void setDataImportFailedWithoutReplication(UUID importOperationId, String errorMessage); + + void setDataImportDeleteProgressFromMapTimerWithReplication(UUID importOperationId); + + void setDataImportDeleteProgressFromMapTimerWithoutReplication(UUID importOperationId); + + /** + * For the reference to a remote sailing server, updates its events cache and returns the event list + * or, if fetching the event list from the remote server did fail, the exception for which it failed. + */ + Util.Pair, Exception> updateRemoteServerEventCacheSynchronously(RemoteSailingServerReference ref); + + /** + * Searches the content of this server, not that of any remote servers referenced by any {@link RemoteSailingServerReference}s. + */ + @Override + Result search(KeywordQuery query); + + /** + * Searches a specific remote server whose reference has the {@link RemoteSailingServerReference#getName() name} + * remoteServerReferenceName. If a remote server reference with that name is not known, + * null is returned. Otherwise, a non-null and possibly empty search result set is + * returned. + */ + Result searchRemotely(String remoteServerReferenceName, KeywordQuery query); + + /** + * Gets the configuration of the local sailing server instances. + */ + SailingServerConfiguration getSailingServerConfiguration(); + + void updateServerConfiguration(SailingServerConfiguration serverConfiguration); + + /** + * References to remote servers may be dead or alive. This is internally determined by regularly polling those + * servers for their events list. If the events list cannot be successfully retrieved, the server is considered "dead." + * This method returns the "live" server references. + */ + Iterable getLiveRemoteServerReferences(); + + RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName); + + void addRegattaWithoutReplication(Regatta regatta); + + void addEventWithoutReplication(Event event); + + /** + * Adds the leaderboard group to this service; if the group has an overall leaderboard, the overall leaderboard + * is added to this service as well. For both, the group and the overall leaderboard, any previously existing + * objects by the same name of that type will be replaced. + */ + void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup); + + /** + * @return {@code null} if no service can be found in the OSGi registry + */ + FileStorageManagementService getFileStorageManagementService(); + + ClassLoader getCombinedMasterDataClassLoader(); + + Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint); +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index cb54334f6f9..3fecb73db30 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -1,3343 +1,3344 @@ -package com.sap.sailing.server.impl; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.SocketException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; -import org.osgi.util.tracker.ServiceTracker; - -import com.sap.sailing.domain.abstractlog.AbstractLog; -import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; -import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -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.abstractlog.race.SimpleRaceLogIdentifier; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; -import com.sap.sailing.domain.abstractlog.race.state.RaceState; -import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; -import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; -import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.CompetitorStore.CompetitorUpdateListener; -import com.sap.sailing.domain.base.ControlPoint; -import com.sap.sailing.domain.base.CourseArea; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.domain.base.EventBase; -import com.sap.sailing.domain.base.EventFetcher; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.LeaderboardSearchResult; -import com.sap.sailing.domain.base.LeaderboardSearchResultBase; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceColumn; -import com.sap.sailing.domain.base.RaceColumnInSeries; -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.base.RemoteSailingServerReference; -import com.sap.sailing.domain.base.SailingServerConfiguration; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.Sideline; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.base.configuration.DeviceConfiguration; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; -import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; -import com.sap.sailing.domain.base.configuration.RegattaConfiguration; -import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMapImpl; -import com.sap.sailing.domain.base.impl.DynamicCompetitor; -import com.sap.sailing.domain.base.impl.EventImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.RemoteSailingServerReferenceImpl; -import com.sap.sailing.domain.common.DataImportProgress; -import com.sap.sailing.domain.common.Distance; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.Renamable; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.TrackedRaceStatusEnum; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; -import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; -import com.sap.sailing.domain.common.impl.DataImportProgressImpl; -import com.sap.sailing.domain.common.media.MediaTrack; -import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; -import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; -import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.LeaderboardGroup; -import com.sap.sailing.domain.leaderboard.LeaderboardRegistry; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; -import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; -import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; -import com.sap.sailing.domain.persistence.DomainObjectFactory; -import com.sap.sailing.domain.persistence.MongoObjectFactory; -import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; -import com.sap.sailing.domain.persistence.MongoRegattaLogStoreFactory; -import com.sap.sailing.domain.persistence.MongoWindStore; -import com.sap.sailing.domain.persistence.MongoWindStoreFactory; -import com.sap.sailing.domain.persistence.PersistenceFactory; -import com.sap.sailing.domain.persistence.media.MediaDB; -import com.sap.sailing.domain.persistence.media.MediaDBFactory; -import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFactory; -import com.sap.sailing.domain.polars.PolarDataService; -import com.sap.sailing.domain.racelog.RaceLogIdentifier; -import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.racelog.tracking.GPSFixStore; -import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; -import com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo; -import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; -import com.sap.sailing.domain.ranking.RankingMetricConstructor; -import com.sap.sailing.domain.regattalike.HasRegattaLike; -import com.sap.sailing.domain.regattalike.IsRegattaLike; -import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; -import com.sap.sailing.domain.regattalog.RegattaLogStore; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.RaceChangeListener; -import com.sap.sailing.domain.tracking.RaceHandle; -import com.sap.sailing.domain.tracking.RaceListener; -import com.sap.sailing.domain.tracking.RaceTracker; -import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRaceStatus; -import com.sap.sailing.domain.tracking.TrackedRegatta; -import com.sap.sailing.domain.tracking.WindStore; -import com.sap.sailing.domain.tracking.WindTracker; -import com.sap.sailing.domain.tracking.WindTrackerFactory; -import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; -import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; -import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; -import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; -import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.Replicator; -import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardSearchResultBaseJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer; -import com.sap.sailing.server.masterdata.DataImportLockWithProgress; -import com.sap.sailing.server.operationaltransformation.AddCourseAreas; -import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; -import com.sap.sailing.server.operationaltransformation.AddMediaTrackOperation; -import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; -import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; -import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.CreateEvent; -import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDataImportProgress; -import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDeviceConfiguration; -import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; -import com.sap.sailing.server.operationaltransformation.DataImportFailed; -import com.sap.sailing.server.operationaltransformation.RecordCompetitorGPSFix; -import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFix; -import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForExistingTrack; -import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForNewMarkTrack; -import com.sap.sailing.server.operationaltransformation.RecordWindFix; -import com.sap.sailing.server.operationaltransformation.RemoveDeviceConfiguration; -import com.sap.sailing.server.operationaltransformation.RemoveEvent; -import com.sap.sailing.server.operationaltransformation.RemoveMediaTrackOperation; -import com.sap.sailing.server.operationaltransformation.RemoveWindFix; -import com.sap.sailing.server.operationaltransformation.RenameEvent; -import com.sap.sailing.server.operationaltransformation.SetDataImportDeleteProgressFromMapTimer; -import com.sap.sailing.server.operationaltransformation.TrackRegatta; -import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; -import com.sap.sailing.server.operationaltransformation.UpdateEndOfTracking; -import com.sap.sailing.server.operationaltransformation.UpdateMarkPassings; -import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackDurationOperation; -import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackRacesOperation; -import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackStartTimeOperation; -import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackTitleOperation; -import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackUrlOperation; -import com.sap.sailing.server.operationaltransformation.UpdateRaceDelayToLive; -import com.sap.sailing.server.operationaltransformation.UpdateStartOfTracking; -import com.sap.sailing.server.operationaltransformation.UpdateStartTimeReceived; -import com.sap.sailing.server.operationaltransformation.UpdateTrackedRaceStatus; -import com.sap.sailing.server.operationaltransformation.UpdateWindAveragingTime; -import com.sap.sailing.server.operationaltransformation.UpdateWindSourcesToExclude; -import com.sap.sailing.server.simulation.SimulationService; -import com.sap.sailing.server.simulation.SimulationServiceFactory; -import com.sap.sse.ServerInfo; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.TypeBasedServiceFinderFactory; -import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.Util.Triple; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; -import com.sap.sse.common.search.KeywordQuery; -import com.sap.sse.common.search.Result; -import com.sap.sse.common.search.ResultImpl; -import com.sap.sse.concurrent.LockUtil; -import com.sap.sse.concurrent.NamedReentrantReadWriteLock; -import com.sap.sse.filestorage.FileStorageManagementService; -import com.sap.sse.replication.OperationExecutionListener; -import com.sap.sse.replication.OperationWithResult; -import com.sap.sse.replication.ReplicationMasterDescriptor; -import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; -import com.sap.sse.util.ClearStateTestSupport; -import com.sap.sse.util.JoinedClassLoader; -import com.sap.sse.util.impl.ThreadFactoryWithPriority; - -public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, - LeaderboardRegistry, Replicator, EventFetcher { - private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); - - /** - * A scheduler for the periodic checks of the paramURL documents for the advent of {@link ControlPoint}s with static - * position information otherwise not available through MarkPassingReceiver's events. - */ - private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true)); - - private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory; - - /** - * Holds the {@link Event} objects for those event registered with this service. Note that there may be - * {@link Event} objects that exist outside this service for events not (yet) registered here. - */ - private final ConcurrentHashMap eventsById; - - private final RemoteSailingServerSet remoteSailingServerSet; - - /** - * Holds the {@link Regatta} objects for those races registered with this service. Note that there may be - * {@link Regatta} objects that exist outside this service for regattas not (yet) registered here. - */ - protected final ConcurrentHashMap regattasByName; - - private final NamedReentrantReadWriteLock regattasByNameLock; - - private final ConcurrentHashMap courseListeners; - - protected final ConcurrentHashMap> raceTrackersByRegatta; - - /** - * Although {@link #raceTrackersByRegatta} is a concurrent hash map, entering sets as values needs to be - * synchronized using this lock's write lock to avoid two value sets overwriting each other. - */ - private final NamedReentrantReadWriteLock raceTrackersByRegattaLock; - - /** - * Remembers the trackers by paramURL/liveURI/storedURI to avoid duplication - */ - protected final ConcurrentHashMap raceTrackersByID; - - /** - * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} will check - * {@link #raceTrackersByID} for the presence of a tracker and won't create a new tracker if one for the - * connectivity parameters' ID already exists. This check and creation and addition to {@link #raceTrackersByID} - * requires locking in the face of concurrent calls to - * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)}. Using synchronized is - * not ideal due to its coarse-grained locking style which allows for little concurrency. Instead, this map is used - * to keep locks for any ID that any invocation of the - * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} method is currently working on. - * Fetching or creating and putting a lock to this map happens in ({@link #getOrCreateRaceTrackersByIdLock}) which - * takes care of managing concurrent access to this concurrent map. When done, the - * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} method cleans up by removing the - * lock again from this map, again using a synchronized method ( - * {@link #unlockRaceTrackersById(Object, NamedReentrantReadWriteLock)}). - */ - private final ConcurrentHashMap raceTrackersByIDLocks; - - /** - * Leaderboards managed by this racing event service - */ - private final ConcurrentHashMap leaderboardsByName; - - /** - * {@link #leaderboardsByName} is already a concurrent hash map; however, when renaming a leaderboard, this shall - * happen as an atomic transaction, not interruptible by other write accesses on the same map because otherwise - * assumptions made during the rename process wouldn't hold. See, in particular, - * {@link #renameLeaderboard(String, String)}. - */ - private final NamedReentrantReadWriteLock leaderboardsByNameLock; - - private final ConcurrentHashMap leaderboardGroupsByName; - - private final ConcurrentHashMap leaderboardGroupsByID; - - /** - * See {@link #leaderboardsByNameLock} - */ - private final NamedReentrantReadWriteLock leaderboardGroupsByNameLock; - - private final CompetitorStore competitorStore; - - /** - * A set based on a concurrent hash map, therefore being thread safe - */ - private Set regattasObservedForDefaultLeaderboard = Collections - .newSetFromMap(new ConcurrentHashMap()); - - private final MongoObjectFactory mongoObjectFactory; - - private final DomainObjectFactory domainObjectFactory; - - private final ConcurrentHashMap regattaTrackingCache; - - /** - * Protects write access transactions that do a previous read to {@link #regattaTrackingCache}; read-only access is - * already synchronized by using a concurrent hash map for {@link #regattaTrackingCache}. - */ - private final NamedReentrantReadWriteLock regattaTrackingCacheLock; - - private final ConcurrentHashMap, OperationExecutionListener> operationExecutionListeners; - - /** - * Keys are the toString() representation of the {@link RaceDefinition#getId() IDs} of races passed to - * {@link #setRegattaForRace(Regatta, RaceDefinition)}. - */ - private final ConcurrentHashMap persistentRegattasForRaceIDs; - - private final RaceLogReplicator raceLogReplicator; - private final RegattaLogReplicator regattaLogReplicator; - - private final RaceLogScoringReplicator raceLogScoringReplicator; - - private final MediaDB mediaDB; - - private final MediaLibrary mediaLibrary; - - /** - * Currently valid pairs of {@link DeviceConfigurationMatcher}s and {@link DeviceConfiguration}s. The contents of - * this map is persisted and replicated. See {@link DeviceConfigurationMapImpl}. - */ - protected final DeviceConfigurationMapImpl configurationMap; - - private final WindStore windStore; - private final GPSFixStore gpsFixStore; - - /** - * This author should be used for server generated race log events - */ - private final AbstractLogEventAuthor raceLogEventAuthorForServer = new LogEventAuthorImpl( - RacingEventService.class.getName(), 0); - - private PolarDataService polarDataService; - - private final SimulationService simulationService; - - /** - * Allow only one master data import at a time to avoid situation where multiple Imports override each other in - * unpredictable fashion - */ - private final DataImportLockWithProgress dataImportLock; - - /** - * If this service runs in the context of an OSGi environment, the activator should {@link #setBundleContext set the - * bundle context} on this object so that service lookups become possible. - */ - private BundleContext bundleContext; - - private TypeBasedServiceFinderFactory serviceFinderFactory; - - /** - * The master from which this replicable is currently replicating, or null if this replicable is not - * currently replicated from any master. - */ - private ReplicationMasterDescriptor replicatingFromMaster; - - private Set> operationsSentToMasterForReplication; - - private ThreadLocal currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster = ThreadLocal - .withInitial(() -> false); - - private final Set masterDataClassLoaders = new HashSet(); - - private final JoinedClassLoader joinedClassLoader; - - private SailingServerConfiguration sailingServerConfiguration; - - /** - * Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky - * in some cases because containment and initialization order of some types is fairly tightly coupled. - * There is a dependency of many such objects on an instance of {@link RaceLogResolver} which is implemented - * by {@link RacingEventServiceImpl}. However, therefore, this instance only becomes available in the - * innermost constructor. - * - * @author Axel Uhl (d043530) - * - */ - public static interface ConstructorParameters { - DomainObjectFactory getDomainObjectFactory(); - MongoObjectFactory getMongoObjectFactory(); - com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory(); - CompetitorStore getCompetitorStore(); - } - - /** - * Constructs a {@link DomainFactory base domain factory} that uses this object's {@link #competitorStore competitor - * store} for competitor management. This base domain factory is then also used for the construction of the - * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor collection, - * hence removes all previously persistent competitors. This is the default for testing and for backward - * compatibility with prior releases that did not support a persistent competitor collection. - */ - public RacingEventServiceImpl() { - this(true, null); - } - - public RacingEventServiceImpl(WindStore windStore, GPSFixStore gpsFixStore, - TypeBasedServiceFinderFactory serviceFinderFactory) { - this(true, windStore, gpsFixStore, serviceFinderFactory); - } - - void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - /** - * Like {@link #RacingEventServiceImpl()}, but allows callers to specify that the persistent competitor collection - * be cleared before the service starts. - * - * @param clearPersistentCompetitorStore - * if true, the {@link PersistentCompetitorStore} is created empty, with the corresponding - * database collection cleared as well. Use with caution! When used with false, competitors - * created and stored during previous service executions will initially be loaded. - */ - public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) { - this((final RaceLogResolver raceLogResolver)-> { - return new ConstructorParameters() { - private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); - private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( - PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory), - clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); - - @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } - @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } - @Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); } - @Override public CompetitorStore getCompetitorStore() { return competitorStore; } - }; - }, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory); - } - - private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore, - GPSFixStore gpsFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) { - this((final RaceLogResolver raceLogResolver)-> { - return new ConstructorParameters() { - private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); - private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( - mongoObjectFactory, - clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); - - @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } - @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } - @Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); } - @Override public CompetitorStore getCompetitorStore() { return competitorStore; } - }; - }, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, gpsFixStore, serviceFinderFactory); - } - - /** - * Uses the default factories for the tracking adapters and the {@link DomainFactory base domain factory} of the - * {@link PersistenceFactory#getDefaultDomainObjectFactory() default domain object factory}. This constructor should - * be used for testing because it provides a transient {@link CompetitorStore} as required for competitor - * persistence. - */ - public RacingEventServiceImpl(Function domainObjectFactoryProvider, - final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) { - this((final RaceLogResolver raceLogResolver)-> { - return new ConstructorParameters() { - private final DomainObjectFactory domainObjectFactory = domainObjectFactoryProvider.apply(raceLogResolver); - - @Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; } - @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } - @Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); } - @Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); } - }; - }, mediaDB, windStore, gpsFixStore, null); - } - - public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory, - MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) { - this((final RaceLogResolver raceLogResolver)-> { - return new ConstructorParameters() { - @Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; } - @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } - @Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); } - @Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); } - }; - }, mediaDB, windStore, gpsFixStore, null); - } - - /** - * @param windStore - * if null, a default {@link MongoWindStore} will be used, based on the persistence set-up - * of this service - * @param serviceFinderFactory - * used to find the services handling specific types of tracking devices, such as the persistent storage - * of {@link DeviceIdentifier}s of specific device types or the managing of the device-to-competitor - * associations per race tracked. - */ - public RacingEventServiceImpl(Function constructorParametersProvider, MediaDB mediaDb, - WindStore windStore, GPSFixStore gpsFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) { - logger.info("Created " + this); - final ConstructorParameters constructorParameters = constructorParametersProvider.apply(this); - this.domainObjectFactory = constructorParameters.getDomainObjectFactory(); - this.masterDataClassLoaders.add(this.getClass().getClassLoader()); - joinedClassLoader = new JoinedClassLoader(masterDataClassLoaders); - this.operationsSentToMasterForReplication = new HashSet<>(); - this.baseDomainFactory = constructorParameters.getBaseDomainFactory(); - this.mongoObjectFactory = constructorParameters.getMongoObjectFactory(); - this.mediaDB = mediaDb; - this.competitorStore = constructorParameters.getCompetitorStore(); - if (windStore == null) { - try { - windStore = MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - this.competitorStore.addCompetitorUpdateListener(new CompetitorUpdateListener() { - @Override - public void competitorUpdated(Competitor competitor) { - replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor - .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), - competitor.getTeam().getImage(), competitor.getFlagImage(), - competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile())); - } - }); - this.windStore = windStore; - this.dataImportLock = new DataImportLockWithProgress(); - - remoteSailingServerSet = new RemoteSailingServerSet(scheduler); - regattasByName = new ConcurrentHashMap(); - regattasByNameLock = new NamedReentrantReadWriteLock("regattasByName for " + this, /* fair */false); - eventsById = new ConcurrentHashMap(); - regattaTrackingCache = new ConcurrentHashMap<>(); - regattaTrackingCacheLock = new NamedReentrantReadWriteLock("regattaTrackingCache for " + this, /* fair */false); - raceTrackersByRegatta = new ConcurrentHashMap<>(); - raceTrackersByRegattaLock = new NamedReentrantReadWriteLock("raceTrackersByRegatta for " + this, /* fair */ - false); - raceTrackersByID = new ConcurrentHashMap<>(); - raceTrackersByIDLocks = new ConcurrentHashMap<>(); - leaderboardGroupsByName = new ConcurrentHashMap<>(); - leaderboardGroupsByID = new ConcurrentHashMap<>(); - leaderboardGroupsByNameLock = new NamedReentrantReadWriteLock("leaderboardGroupsByName for " + this, /* fair */ - false); - leaderboardsByName = new ConcurrentHashMap(); - leaderboardsByNameLock = new NamedReentrantReadWriteLock("leaderboardsByName for " + this, /* fair */false); - operationExecutionListeners = new ConcurrentHashMap<>(); - courseListeners = new ConcurrentHashMap<>(); - persistentRegattasForRaceIDs = new ConcurrentHashMap<>(); - final int SIMULATION_THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors()/3, 1); - Executor simulatorExecutor = new ThreadPoolExecutor(/* corePoolSize */SIMULATION_THREAD_POOL_SIZE, - /* maximumPoolSize */SIMULATION_THREAD_POOL_SIZE, - /* keepAliveTime */60, TimeUnit.SECONDS, - /* workQueue */new LinkedBlockingQueue()); - // TODO: initialize smart-future-cache for simulation-results and add to simulation-service - simulationService = SimulationServiceFactory.INSTANCE.getService(simulatorExecutor, this); - this.raceLogReplicator = new RaceLogReplicator(this); - this.regattaLogReplicator = new RegattaLogReplicator(this); - this.raceLogScoringReplicator = new RaceLogScoringReplicator(this); - this.mediaLibrary = new MediaLibrary(); - if (gpsFixStore == null) { - try { - gpsFixStore = MongoGPSFixStoreFactory.INSTANCE.getMongoGPSFixStore(mongoObjectFactory, - domainObjectFactory, serviceFinderFactory); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - this.gpsFixStore = gpsFixStore; - this.configurationMap = new DeviceConfigurationMapImpl(); - this.serviceFinderFactory = serviceFinderFactory; - - sailingServerConfiguration = domainObjectFactory.loadServerConfiguration(); - final Iterable> loadedEventsWithRequireStoreFlag = loadStoredEvents(); - loadStoredRegattas(); - loadRaceIDToRegattaAssociations(); - loadStoredLeaderboardsAndGroups(); - loadLinksFromEventsToLeaderboardGroups(); - loadMediaLibary(); - loadStoredDeviceConfigurations(); - loadAllRemoteSailingServersAndSchedulePeriodicEventCacheRefresh(); - - // Stores all events which run through a data migration - // Remark: must be called after loadLinksFromEventsToLeaderboardGroups(), otherwise would loose the Event -> LeaderboardGroup relation - for (Pair eventAndRequireStoreFlag : loadedEventsWithRequireStoreFlag) { - if (eventAndRequireStoreFlag.getB()) { - mongoObjectFactory.storeEvent(eventAndRequireStoreFlag.getA()); - } - } - } - - @Override - public boolean isCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster() { - return currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster.get(); - } - - @Override - public void setCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster( - boolean currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster) { - this.currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster - .set(currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster); - } - - @Override - public PolarDataService getPolarDataService() { - return polarDataService; - } - - @Override - public SimulationService getSimulationService() { - return simulationService; - } - - @Override - public void clearState() throws Exception { - for (String leaderboardGroupName : new ArrayList<>(this.leaderboardGroupsByName.keySet())) { - removeLeaderboardGroup(leaderboardGroupName); - } - for (String leaderboardName : new ArrayList<>(this.leaderboardsByName.keySet())) { - removeLeaderboard(leaderboardName); - } - for (Regatta regatta : new ArrayList<>(this.regattasByName.values())) { - stopTracking(regatta); - removeRegatta(regatta); - } - for (Event event : new ArrayList<>(this.eventsById.values())) { - removeEvent(event.getId()); - } - for (MediaTrack mediaTrack : this.mediaLibrary.allTracks()) { - mediaTrackDeleted(mediaTrack); - } - // TODO clear user store? See bug 2430. - this.competitorStore.clear(); - } - - @Override - public com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() { - return baseDomainFactory; - } - - @Override - public MongoObjectFactory getMongoObjectFactory() { - return mongoObjectFactory; - } - - @Override - public DomainObjectFactory getDomainObjectFactory() { - return domainObjectFactory; - } - - private void loadRaceIDToRegattaAssociations() { - persistentRegattasForRaceIDs.putAll(domainObjectFactory.loadRaceIDToRegattaAssociations(this)); - } - - private void loadStoredRegattas() { - LockUtil.lockForWrite(regattasByNameLock); - try { - for (Regatta regatta : domainObjectFactory.loadAllRegattas(this)) { - logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() - + ") into regattasByName"); - regattasByName.put(regatta.getName(), regatta); - regatta.addRegattaListener(this); - onRegattaLikeAdded(regatta); - regatta.addRaceColumnListener(raceLogReplicator); - regatta.addRaceColumnListener(raceLogScoringReplicator); - } - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - } - - private Iterable> loadStoredEvents() { - Iterable> loadedEventsWithRequireStoreFlag = domainObjectFactory.loadAllEvents(); - for (Pair eventAndFlag : loadedEventsWithRequireStoreFlag) { - Event event = eventAndFlag.getA(); - if (event.getId() != null) - eventsById.put(event.getId(), event); - } - return loadedEventsWithRequireStoreFlag; - } - - private void loadLinksFromEventsToLeaderboardGroups() { - domainObjectFactory.loadLeaderboardGroupLinksForEvents(/* eventResolver */this, /* leaderboardGroupResolver */ - this); - } - - private void loadAllRemoteSailingServersAndSchedulePeriodicEventCacheRefresh() { - for (RemoteSailingServerReference sailingServer : domainObjectFactory.loadAllRemoteSailingServerReferences()) { - remoteSailingServerSet.add(sailingServer); - } - } - - /** - * Collects media track references from the configured sources (mongo DB by default, ftp folder yet to be - * implemented). The method is expected to be called initially blocking the API until finished. - * - * Subsequent calls (assumed to be triggered from the admin console or in scheduled intervals) don't need to block. - * In that case, the API will simply serve the current state. - * - */ - private void loadMediaLibary() { - Collection allDbMediaTracks = mediaDB.loadAllMediaTracks(); - mediaTracksAdded(allDbMediaTracks); - } - - private void loadStoredDeviceConfigurations() { - for (Entry entry : domainObjectFactory - .loadAllDeviceConfigurations()) { - configurationMap.put(entry.getKey(), entry.getValue()); - } - } - - @Override - public void addLeaderboard(Leaderboard leaderboard) { - LockUtil.lockForWrite(leaderboardsByNameLock); - try { - leaderboardsByName.put(leaderboard.getName(), leaderboard); - } finally { - LockUtil.unlockAfterWrite(leaderboardsByNameLock); - } - // RaceColumns of RegattaLeaderboards are tracked via its Regatta! - if (leaderboard instanceof FlexibleLeaderboard) { - onRegattaLikeAdded(((FlexibleLeaderboard) leaderboard).getRegattaLike()); - leaderboard.addRaceColumnListener(raceLogReplicator); - leaderboard.addRaceColumnListener(raceLogScoringReplicator); - } - } - - private void loadStoredLeaderboardsAndGroups() { - logger.info("loading stored leaderboards and groups"); - // Loading all leaderboard groups and the contained leaderboards - for (LeaderboardGroup leaderboardGroup : domainObjectFactory.getAllLeaderboardGroups(this, this)) { - logger.info("loaded leaderboard group " + leaderboardGroup.getName() + " into " + this); - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - leaderboardGroupsByName.put(leaderboardGroup.getName(), leaderboardGroup); - leaderboardGroupsByID.put(leaderboardGroup.getId(), leaderboardGroup); - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - } - // Loading the remaining leaderboards - domainObjectFactory.getLeaderboardsNotInGroup(this, this); - logger.info("done with loading stored leaderboards and groups"); - } - - @Override - public FlexibleLeaderboard addFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, - int[] discardThresholds, ScoringScheme scoringScheme, Serializable courseAreaId) { - logger.info("adding flexible leaderboard " + leaderboardName); - CourseArea courseArea = getCourseArea(courseAreaId); - FlexibleLeaderboard result = new FlexibleLeaderboardImpl(getRaceLogStore(), getRegattaLogStore(), - leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardThresholds), scoringScheme, - courseArea); - result.setDisplayName(leaderboardDisplayName); - if (getLeaderboardByName(leaderboardName) != null) { - throw new IllegalArgumentException("Leaderboard with name " + leaderboardName + " already exists"); - } - addLeaderboard(result); - mongoObjectFactory.storeLeaderboard(result); - return result; - } - - @Override - public CourseArea getCourseArea(Serializable courseAreaId) { - for (Event event : getAllEvents()) { - for (CourseArea courseArea : event.getVenue().getCourseAreas()) { - if (courseArea.getId().equals(courseAreaId)) { - return courseArea; - } - } - } - return null; - } - - @Override - public RegattaLeaderboard addRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, - int[] discardThresholds) { - Regatta regatta = getRegatta(regattaIdentifier); - logger.info("adding regatta leaderboard for regatta " - + (regatta == null ? "null" : (regatta.getName() + " (" + regatta.hashCode() + ")")) + " to " + this); - RegattaLeaderboard result = null; - if (regatta != null) { - result = new RegattaLeaderboardImpl(regatta, new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); - result.setDisplayName(leaderboardDisplayName); - if (getLeaderboardByName(result.getName()) != null) { - throw new IllegalArgumentException("Leaderboard with name " + result.getName() + " already exists in " - + this); - } - addLeaderboard(result); - mongoObjectFactory.storeLeaderboard(result); - } else { - logger.warning("Cannot find regatta " + regattaIdentifier - + ". Hence, cannot create regatta leaderboard for it."); - } - return result; - } - - @Override - public RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - if (leaderboard instanceof FlexibleLeaderboard) { - // uses the default fleet as the single fleet for the new column - RaceColumn result = ((FlexibleLeaderboard) leaderboard).addRaceColumn(columnName, medalRace); - updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); - return result; - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName - + " is not a FlexibleLeaderboard"); - } - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } - } - - @Override - public void moveLeaderboardColumnUp(String leaderboardName, String columnName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { - ((FlexibleLeaderboard) leaderboard).moveRaceColumnUp(columnName); - updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } - } - - @Override - public void moveLeaderboardColumnDown(String leaderboardName, String columnName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { - ((FlexibleLeaderboard) leaderboard).moveRaceColumnDown(columnName); - updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } - } - - @Override - public void removeLeaderboardColumn(String leaderboardName, String columnName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard == null) { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } else if (!(leaderboard instanceof FlexibleLeaderboard)) { - throw new IllegalArgumentException("Columns cannot be removed from Leaderboard named " + leaderboardName); - } else { - ((FlexibleLeaderboard) leaderboard).removeRaceColumn(columnName); - updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); - } - } - - @Override - public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - final RaceColumn raceColumn = leaderboard.getRaceColumnByName(oldColumnName); - if (raceColumn instanceof FlexibleRaceColumn) { - // remove race log under old identifier; the race log identifier changes - for (Fleet fleet : raceColumn.getFleets()) { - getMongoObjectFactory().removeRaceLog(raceColumn.getRaceLogIdentifier(fleet)); - } - ((FlexibleRaceColumn) raceColumn).setName(newColumnName); - // store the race logs again under the new identifiers - storeRaceLogs(raceColumn); - updateStoredLeaderboard(leaderboard); - } else { - throw new IllegalArgumentException("Race column " + oldColumnName + " cannot be renamed"); - } - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } - } - - /** - * When a race column is renamed, its race log identifiers change. Therefore, the race logs need to be stored under - * the new identifier again to be consistent with the in-memory image again. - */ - private void storeRaceLogs(RaceColumn raceColumn) { - for (Fleet fleet : raceColumn.getFleets()) { - RaceLogIdentifier identifier = raceColumn.getRaceLogIdentifier(fleet); - RaceLogEventVisitor storeVisitor = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStoreVisitor( - identifier, getMongoObjectFactory()); - RaceLog raceLog = raceColumn.getRaceLog(fleet); - raceLog.lockForRead(); - try { - for (RaceLogEvent e : raceLog.getRawFixes()) { - e.accept(storeVisitor); - } - } finally { - raceLog.unlockAfterRead(); - } - } - } - - @Override - public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double factor) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - final RaceColumn raceColumn = leaderboard.getRaceColumnByName(columnName); - if (raceColumn != null) { - raceColumn.setFactor(factor); - updateStoredLeaderboard(leaderboard); - } else { - throw new IllegalArgumentException("Race column " + columnName + " not found in leaderboard " - + leaderboardName); - } - } else { - throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); - } - } - - @Override - public void renameLeaderboard(String oldName, String newName) { - final Leaderboard toRename = leaderboardsByName.get(oldName); - LockUtil.lockForWrite(leaderboardsByNameLock); - try { - if (toRename == null) { - throw new IllegalArgumentException("No leaderboard with name " + oldName + " found"); - } - if (leaderboardsByName.containsKey(newName)) { - throw new IllegalArgumentException("Leaderboard with name " + newName + " already exists"); - } - if (toRename instanceof Renamable) { - ((Renamable) toRename).setName(newName); - leaderboardsByName.remove(oldName); - leaderboardsByName.put(newName, toRename); - } else { - throw new IllegalArgumentException("Leaderboard with name " + newName + " is of type " - + toRename.getClass().getSimpleName() + " and therefore cannot be renamed"); - } - } finally { - LockUtil.unlockAfterWrite(leaderboardsByNameLock); - } - // don't need the lock anymore to update DB - if (toRename instanceof Renamable) { - mongoObjectFactory.renameLeaderboard(oldName, newName); - syncGroupsAfterLeaderboardChange(toRename, true); - } - } - - @Override - public void updateStoredLeaderboard(Leaderboard leaderboard) { - getMongoObjectFactory().storeLeaderboard(leaderboard); - syncGroupsAfterLeaderboardChange(leaderboard, true); - } - - @Override - public void updateStoredRegatta(Regatta regatta) { - if (regatta.isPersistent()) { - mongoObjectFactory.storeRegatta(regatta); - } - } - - /** - * Checks all groups, if they contain a leaderboard with the name of the updatedLeaderboard and - * replaces the one in the group with the updated one.
    - * This synchronizes things like the RaceIdentifier in the leaderboard columns. - */ - private void syncGroupsAfterLeaderboardChange(Leaderboard updatedLeaderboard, boolean doDatabaseUpdate) { - boolean groupNeedsUpdate = false; - for (LeaderboardGroup leaderboardGroup : leaderboardGroupsByName.values()) { - for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - if (leaderboard == updatedLeaderboard) { - int index = leaderboardGroup.getIndexOf(leaderboard); - leaderboardGroup.removeLeaderboard(leaderboard); - leaderboardGroup.addLeaderboardAt(updatedLeaderboard, index); - groupNeedsUpdate = true; - // TODO we assume that the leaderboard names are unique, so we can break the inner loop here - break; - } - } - - if (doDatabaseUpdate && groupNeedsUpdate) { - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - } - groupNeedsUpdate = false; - } - } - - @Override - public void removeLeaderboard(String leaderboardName) { - Leaderboard leaderboard = removeLeaderboardFromLeaderboardsByName(leaderboardName); - if (leaderboard != null) { - leaderboard.removeRaceColumnListener(raceLogReplicator); - leaderboard.removeRaceColumnListener(raceLogScoringReplicator); - mongoObjectFactory.removeLeaderboard(leaderboardName); - syncGroupsAfterLeaderboardRemove(leaderboardName, true); - if (leaderboard instanceof FlexibleLeaderboard) { - onRegattaLikeRemoved(((FlexibleLeaderboard) leaderboard).getRegattaLike()); - } - leaderboard.destroy(); - } - } - - private Leaderboard removeLeaderboardFromLeaderboardsByName(String leaderboardName) { - LockUtil.lockForWrite(leaderboardsByNameLock); - try { - return leaderboardsByName.remove(leaderboardName); - } finally { - LockUtil.unlockAfterWrite(leaderboardsByNameLock); - } - } - - /** - * Checks all groups, if they contain a leaderboard with the removedLeaderboardName and removes it from - * the group. - * - * @param removedLeaderboardName - */ - private void syncGroupsAfterLeaderboardRemove(String removedLeaderboardName, boolean doDatabaseUpdate) { - boolean groupNeedsUpdate = false; - for (LeaderboardGroup leaderboardGroup : leaderboardGroupsByName.values()) { - for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { - if (leaderboard.getName().equals(removedLeaderboardName)) { - leaderboardGroup.removeLeaderboard(leaderboard); - groupNeedsUpdate = true; - // TODO we assume that the leaderboard names are unique, so we can break the inner loop here - break; - } - } - - if (doDatabaseUpdate && groupNeedsUpdate) { - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - } - groupNeedsUpdate = false; - } - } - - @Override - public Leaderboard getLeaderboardByName(String name) { - return leaderboardsByName.get(name); - } - - @Override - public Position getMarkPosition(Mark mark, LeaderboardThatHasRegattaLike leaderboard, TimePoint timePoint, RaceLog raceLog) { - GPSFixTrack track = null; - // If no spanning track is found, the fix closest to the time point requested is used instead - GPSFix nonSpanningFallback = null; - for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) { - GPSFixTrack trackCandidate = trackedRace.getTrack(mark); - if (trackCandidate != null) { - if (spansTimePoint(trackCandidate, timePoint)) { - track = trackCandidate; - break; - } else { - nonSpanningFallback = improveTimewiseClosestFix(nonSpanningFallback, trackCandidate, timePoint); - } - } - } - if (track == null) { // no spanning track found in any tracked race, or no tracked races found - // try to load from store - DynamicGPSFixTrackImpl loadedTrack = new DynamicGPSFixTrackImpl(mark, 0); - track = loadedTrack; - Set> logs = new HashSet<>(); - logs.add(leaderboard.getRegattaLike().getRegattaLog()); - if (raceLog == null) { // no race log explicitly provided --> use all race logs - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - logs.add(raceColumn.getRaceLog(fleet)); - } - } - } else { - logs.add(raceLog); - } - for (AbstractLog log : logs) { - try { - getGPSFixStore().loadMarkTrack(loadedTrack, log, mark); - } catch (Exception e) { - logger.log(Level.WARNING, "Couldn't load mark track for mark " + mark + " from log " + log, e); - } - } - } - Position result = track.getEstimatedPosition(timePoint, /* extrapolate */ false); - if (result == null) { - result = nonSpanningFallback == null ? null : nonSpanningFallback.getPosition(); - } - return result; - } - - private GPSFix improveTimewiseClosestFix(GPSFix nonSpanningFallback, GPSFixTrack track, final TimePoint timePoint) { - GPSFix lastAtOrBefore = track.getLastFixAtOrBefore(timePoint); - GPSFix firstAtOrAfter = track.getFirstFixAtOrAfter(timePoint); - // find the fix closes to timePoint, sorting null values to the end and fixes near timePoint to the beginning - final List list = Arrays.asList(nonSpanningFallback, lastAtOrBefore, firstAtOrAfter); - list.sort(new Comparator() { - @Override - public int compare(GPSFix o1, GPSFix o2) { - final int result; - if (o1 == null) { - if (o2 == null) { - result = 0; - } else { - result = 1; - } - } else if (o2 == null) { - result = -1; - } else { - result = new Long(Math.abs(o1.getTimePoint().until(timePoint).asMillis())).compareTo( - Math.abs(o2.getTimePoint().until(timePoint).asMillis())); - } - return result; - } - }); - return list.get(0); - } - - private boolean spansTimePoint(GPSFixTrack track, TimePoint timePoint) { - return track.getLastFixAtOrBefore(timePoint) != null && track.getFirstFixAtOrAfter(timePoint) != null; - } - - @Override - public Map getLeaderboards() { - return Collections.unmodifiableMap(new HashMap(leaderboardsByName)); - } - - @Override - public SailingServerConfiguration getSailingServerConfiguration() { - return sailingServerConfiguration; - } - - @Override - public void updateServerConfiguration(SailingServerConfiguration serverConfiguration) { - this.sailingServerConfiguration = serverConfiguration; - mongoObjectFactory.storeServerConfiguration(serverConfiguration); - } - - @Override - public Map, Exception>> getPublicEventsOfAllSailingServers() { - return remoteSailingServerSet.getCachedEventsForRemoteSailingServers(); // FIXME should probably add our own - // stuff here... Is it enough to pass on - // the remote reference URL to the - // client for leaderboard group URL - // construction? - } - - @Override - public RemoteSailingServerReference addRemoteSailingServerReference(String name, URL url) { - RemoteSailingServerReference result = new RemoteSailingServerReferenceImpl(name, url); - remoteSailingServerSet.add(result); - mongoObjectFactory.storeSailingServer(result); - return result; - } - - @Override - public Iterable getLiveRemoteServerReferences() { - return remoteSailingServerSet.getLiveRemoteServerReferences(); - } - - @Override - public RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName) { - return remoteSailingServerSet.getServerReferenceByName(remoteServerReferenceName); - } - - @Override - public com.sap.sse.common.Util.Pair, Exception> updateRemoteServerEventCacheSynchronously( - RemoteSailingServerReference ref) { - return remoteSailingServerSet.getEventsOrException(ref); - } - - @Override - public void removeRemoteSailingServerReference(String name) { - remoteSailingServerSet.remove(name); - mongoObjectFactory.removeSailingServer(name); - } - - @Override - public Iterable getAllEvents() { - return Collections.unmodifiableCollection(new ArrayList(eventsById.values())); - } - - @Override - public Event getEvent(Serializable id) { - return id == null ? null : eventsById.get(id); - } - - @Override - public Iterable getAllRegattas() { - return Collections.unmodifiableCollection(new ArrayList(regattasByName.values())); - } - - @Override - public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) { - Set trackers = raceTrackersByRegatta.get(regattaContext); - if (trackers != null) { - for (RaceTracker tracker : trackers) { - final Set races = tracker.getRaces(); - if (races != null && races.contains(r)) { - return true; - } - } - } - return false; - } - - @Override - public Regatta getRegattaByName(String name) { - return name == null ? null : regattasByName.get(name); - } - - @Override - public Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id) { - Regatta result = regattasByName.get(name); - if (result == null) { - result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, getBaseDomainFactory() - .getOrCreateBoatClass(boatClassName), /* startDate */null, /* endDate */null, this, - getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), id, null); - logger.info("Created default regatta " + result.getName() + " (" + hashCode() + ") on " + this); - onRegattaLikeAdded(result); - cacheAndReplicateDefaultRegatta(result); - } - return result; - } - - private void onRegattaLikeAdded(IsRegattaLike isRegattaLike) { - isRegattaLike.addListener(regattaLogReplicator); - } - - private void onRegattaLikeRemoved(IsRegattaLike isRegattaLike) { - isRegattaLike.removeListener(regattaLogReplicator); - getRegattaLogStore().removeRegattaLog(isRegattaLike.getRegattaLikeIdentifier()); - } - - @Override - public Regatta createRegatta(String fullRegattaName, String boatClassName, TimePoint startDate, TimePoint endDate, - Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, - Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor) { - com.sap.sse.common.Util.Pair regattaWithCreatedFlag = getOrCreateRegattaWithoutReplication( - fullRegattaName, boatClassName, startDate, endDate, id, series, persistent, scoringScheme, - defaultCourseAreaId, useStartTimeInference, rankingMetricConstructor); - Regatta regatta = regattaWithCreatedFlag.getA(); - if (regattaWithCreatedFlag.getB()) { - onRegattaLikeAdded(regatta); - replicateSpecificRegattaWithoutRaceColumns(regatta); - } - return regatta; - } - - @Override - public void addRegattaWithoutReplication(Regatta regatta) { - UUID defaultCourseAreaId = null; - if (regatta.getDefaultCourseArea() != null) { - defaultCourseAreaId = regatta.getDefaultCourseArea().getId(); - } - boolean wasAdded = addAndConnectRegatta(regatta.isPersistent(), defaultCourseAreaId, regatta); - if (!wasAdded) { - logger.info("Regatta with name " + regatta.getName() + " already existed, so it hasn't been added."); - } - } - - private RaceLogStore getRaceLogStore() { - return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory); - } - - private RegattaLogStore getRegattaLogStore() { - return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory, domainObjectFactory); - } - - @Override - public com.sap.sse.common.Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, - String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, - Iterable series, boolean persistent, ScoringScheme scoringScheme, - Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor) { - CourseArea courseArea = getCourseArea(defaultCourseAreaId); - Regatta regatta = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), fullRegattaName, - getBaseDomainFactory().getOrCreateBoatClass(boatClassName), startDate, endDate, series, persistent, - scoringScheme, id, courseArea, useStartTimeInference, rankingMetricConstructor); - boolean wasCreated = addAndConnectRegatta(persistent, defaultCourseAreaId, regatta); - if (wasCreated) { - logger.info("Created regatta " + regatta.getName() + " (" + hashCode() + ") on " + this); - } - return new com.sap.sse.common.Util.Pair(regatta, wasCreated); - } - - private boolean addAndConnectRegatta(boolean persistent, Serializable defaultCourseAreaId, Regatta regatta) { - boolean wasCreated = false; - // try a quick read protected by the concurrent hash map implementation - if (!regattasByName.containsKey(regatta.getName())) { - LockUtil.lockForWrite(regattasByNameLock); - try { - // check again, now that we hold the exclusive write lock - if (!regattasByName.containsKey(regatta.getName())) { - wasCreated = true; - logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() - + ") into regattasByName of " + this); - regattasByName.put(regatta.getName(), regatta); - regatta.addRegattaListener(this); - regatta.addRaceColumnListener(raceLogReplicator); - regatta.addRaceColumnListener(raceLogScoringReplicator); - } - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - } - if (persistent) { - updateStoredRegatta(regatta); - } - for (Event event : getAllEvents()) { - for (CourseArea eventCourseArea : event.getVenue().getCourseAreas()) { - if (defaultCourseAreaId != null && eventCourseArea.getId().equals(defaultCourseAreaId)) { - event.addRegatta(regatta); - } - } - } - return wasCreated; - } - - @Override - public void addRace(RegattaIdentifier addToRegatta, RaceDefinition raceDefinition) { - Regatta regatta = getRegatta(addToRegatta); - regatta.addRace(raceDefinition); // will trigger the raceAdded operation because this service is listening on - // all its regattas - } - - /** - * If the regatta {@link Regatta#isPersistent() is a persistent one}, the association of the race with - * the regatta is remembered persistently so that {@link #getRememberedRegattaForRace(Serializable)} will provide - * it. - */ - @Override - public void raceAdded(Regatta regatta, RaceDefinition raceDefinition) { - if (regatta.isPersistent()) { - setRegattaForRace(regatta, raceDefinition); - } - final CourseChangeReplicator listener = new CourseChangeReplicator(this, regatta, raceDefinition); - courseListeners.put(raceDefinition, listener); - raceDefinition.getCourse().addCourseListener(listener); - replicate(new AddRaceDefinition(regatta.getRegattaIdentifier(), raceDefinition)); - } - - @Override - public void raceRemoved(Regatta regatta, RaceDefinition raceDefinition) { - raceDefinition.getCourse().removeCourseListener(courseListeners.remove(raceDefinition)); - } - - private NamedReentrantReadWriteLock lockRaceTrackersById(Object trackerId) { - NamedReentrantReadWriteLock lock; - synchronized (raceTrackersByIDLocks) { - lock = raceTrackersByIDLocks.get(trackerId); - if (lock == null) { - lock = new NamedReentrantReadWriteLock("raceTrackersByIDLock for " + trackerId, /* fair */false); - raceTrackersByIDLocks.put(trackerId, lock); - } - } - LockUtil.lockForWrite(lock); - return lock; - } - - /** - * @param lock - * need to pass the lock obtained from {@link #lockRaceTrackersById(Object)} because a competing thread - * may already have removed the lock from the {@link #raceTrackersByIDLocks} map - */ - private void unlockRaceTrackersById(Object trackerId, NamedReentrantReadWriteLock lock) { - LockUtil.unlockAfterWrite(lock); - synchronized (raceTrackersByIDLocks) { - raceTrackersByIDLocks.remove(trackerId); - } - } - - @Override - public RaceHandle addRace(RegattaIdentifier regattaToAddTo, RaceTrackingConnectivityParameters params, - long timeoutInMilliseconds) throws Exception { - final Object trackerID = params.getTrackerID(); - NamedReentrantReadWriteLock raceTrackersByIdLock = lockRaceTrackersById(trackerID); - try { - RaceTracker tracker = raceTrackersByID.get(trackerID); - if (tracker == null) { - Regatta regatta = regattaToAddTo == null ? null : getRegatta(regattaToAddTo); - if (regatta == null) { - // create tracker and use an existing or create a default regatta - tracker = params.createRaceTracker(this, windStore, gpsFixStore, /* raceLogResolver */ this); - } else { - // use the regatta selected by the RaceIdentifier regattaToAddTo - tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore, /* raceLogResolver */ this); - assert tracker.getRegatta() == regatta; - } - LockUtil.lockForWrite(raceTrackersByRegattaLock); - try { - raceTrackersByID.put(trackerID, tracker); - Set trackers = raceTrackersByRegatta.get(tracker.getRegatta()); - if (trackers == null) { - trackers = Collections.newSetFromMap(new ConcurrentHashMap()); - raceTrackersByRegatta.put(tracker.getRegatta(), trackers); - } - trackers.add(tracker); - } finally { - LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); - } - // TODO we assume here that the regatta name is unique which necessitates adding the boat class name to - // it in RegattaImpl constructor - String regattaName = tracker.getRegatta().getName(); - Regatta regattaWithName = regattasByName.get(regattaName); - // TODO we assume here that the regatta name is unique which necessitates adding the boat class name to - // it in RegattaImpl constructor - if (regattaWithName != null) { - if (regattaWithName != tracker.getRegatta()) { - if (Util.isEmpty(regattaWithName.getAllRaces())) { - // probably, tracker removed the last races from the old regatta and created a new one - LockUtil.lockForWrite(regattasByNameLock); - try { - regattasByName.remove(regattaName); - cacheAndReplicateDefaultRegatta(tracker.getRegatta()); - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - } else { - throw new RuntimeException("Internal error. Two regatta objects with equal name " - + regattaName); - } - } - } else { - cacheAndReplicateDefaultRegatta(tracker.getRegatta()); - } - } else { - logger.warning("Race tracker with ID "+trackerID+" already found; not tracking twice to avoid race duplication"); - WindStore existingTrackersWindStore = tracker.getWindStore(); - if (!existingTrackersWindStore.equals(windStore)) { - logger.warning("Wind store mismatch. Requested wind store: " + windStore - + ". Wind store in use by existing tracker: " + existingTrackersWindStore); - } - GPSFixStore existingTrackersGPSFixStore = tracker.getGPSFixStore(); - if (!existingTrackersGPSFixStore.equals(gpsFixStore)) { - logger.warning("GPSFix store mismatch. Requested GPSFix store: " + gpsFixStore - + ". GPSFix store in use by existing tracker: " + existingTrackersGPSFixStore); - } - } - if (timeoutInMilliseconds != -1) { - scheduleAbortTrackerAfterInitialTimeout(tracker, timeoutInMilliseconds); - } - return tracker.getRacesHandle(); - } finally { - unlockRaceTrackersById(trackerID, raceTrackersByIdLock); - } - } - - /** - * The regatta and all its contained {@link Regatta#getAllRaces() races} are replicated to all replicas. - * - * @param regatta - * the series of this regatta must not have any {@link Series#getRaceColumns() race columns associated - * (yet)}. - */ - private void replicateSpecificRegattaWithoutRaceColumns(Regatta regatta) { - Serializable courseAreaId = null; - if (regatta.getDefaultCourseArea() != null) { - courseAreaId = regatta.getDefaultCourseArea().getId(); - } - replicate(new AddSpecificRegatta(regatta.getName(), regatta.getBoatClass() == null ? null : regatta - .getBoatClass().getName(), regatta.getStartDate(), regatta.getEndDate(), regatta.getId(), - getSeriesWithoutRaceColumnsConstructionParametersAsMap(regatta), regatta.isPersistent(), - regatta.getScoringScheme(), courseAreaId, regatta.useStartTimeInference(), regatta.getRankingMetricType())); - RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier(); - for (RaceDefinition race : regatta.getAllRaces()) { - replicate(new AddRaceDefinition(regattaIdentifier, race)); - } - } - - private RegattaCreationParametersDTO getSeriesWithoutRaceColumnsConstructionParametersAsMap(Regatta regatta) { - LinkedHashMap result = new LinkedHashMap(); - for (Series s : regatta.getSeries()) { - assert Util.isEmpty(s.getRaceColumns()); - List fleetNamesAndOrdering = new ArrayList(); - for (Fleet f : s.getFleets()) { - fleetNamesAndOrdering.add(getBaseDomainFactory().convertToFleetDTO(f)); - } - result.put( - s.getName(), - new SeriesCreationParametersDTO(fleetNamesAndOrdering, s.isMedal(), s.isStartsWithZeroScore(), s - .isFirstColumnIsNonDiscardableCarryForward(), s.getResultDiscardingRule() == null ? null - : s.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(), s - .hasSplitFleetContiguousScoring())); - } - return new RegattaCreationParametersDTO(result); - } - - /** - * If regatta is not yet in {@link #regattasByName}, it is added, this service is - * {@link Regatta#addRegattaListener(RegattaListener) added} as regatta listener, and the regatta and all its - * contained {@link Regatta#getAllRaces() races} are replicated to all replica. - */ - private void cacheAndReplicateDefaultRegatta(Regatta regatta) { - // try a quick read first, protected by regattasByName being a concurrent hash set - if (!regattasByName.containsKey(regatta.getName())) { - // now we need to obtain exclusive write access; in between, some other thread may have added a regatta by - // that - // name, so we need to check again: - LockUtil.lockForWrite(regattasByNameLock); - try { - if (!regattasByName.containsKey(regatta.getName())) { - logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() - + ") into regattasByName of " + this); - regattasByName.put(regatta.getName(), regatta); - regatta.addRegattaListener(this); - regatta.addRaceColumnListener(raceLogReplicator); - regatta.addRaceColumnListener(raceLogScoringReplicator); - - replicate(new AddDefaultRegatta(regatta.getName(), regatta.getBoatClass() == null ? null : regatta - .getBoatClass().getName(), regatta.getStartDate(), regatta.getEndDate(), regatta.getId())); - RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier(); - for (RaceDefinition race : regatta.getAllRaces()) { - replicate(new AddRaceDefinition(regattaIdentifier, race)); - } - } - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - } - } - - @Override - public DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, - GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, - long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator) { - DynamicTrackedRegatta trackedRegatta = getOrCreateTrackedRegatta(getRegatta(raceIdentifier)); - RaceDefinition race = getRace(raceIdentifier); - return trackedRegatta.createTrackedRace(race, Collections. emptyList(), windStore, gpsFixStore, - delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, - /* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this); - } - - private void ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking( - DynamicTrackedRegatta trackedRegatta) { - if (regattasObservedForDefaultLeaderboard.add(trackedRegatta)) { - trackedRegatta.addRaceListener(new RaceAdditionListener()); - } - } - - private void stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(DynamicTrackedRegatta trackedRegatta) { - regattasObservedForDefaultLeaderboard.remove(trackedRegatta); - } - - /** - * A listener class used to ensure that when a tracked race is added to any {@link TrackedRegatta} managed by this - * service, the service adds the tracked race to the default leaderboard and links it to the leaderboard columns - * that were previously connected to it. Additionally, a {@link RaceChangeListener} is added to the - * {@link TrackedRace} which is responsible for triggering the replication of all relevant changes to the tracked - * race. When a tracked race is removed, the {@link TrackedRaceReplicator} that was added as listener to that - * tracked race is removed again. - * - * A {@link PolarFixCacheUpdater} is added to every race so that polar fixes are aggregated when new GPS fixes - * arrive. - * - * @author Axel Uhl (d043530) - * - */ - private class RaceAdditionListener implements RaceListener, Serializable { - private static final long serialVersionUID = 1036955460477000265L; - - private final Map trackedRaceReplicators; - - private final Map polarFixCacheUpdaters; - - public RaceAdditionListener() { - this.trackedRaceReplicators = new HashMap(); - this.polarFixCacheUpdaters = new HashMap(); - } - - @Override - public void raceRemoved(TrackedRace trackedRace) { - TrackedRaceReplicator trackedRaceReplicator = trackedRaceReplicators.remove(trackedRace); - if (trackedRaceReplicator != null) { - trackedRace.removeListener(trackedRaceReplicator); - } - PolarFixCacheUpdater polarFixCacheUpdater = polarFixCacheUpdaters.remove(trackedRace); - if (polarFixCacheUpdater != null) { - trackedRace.removeListener(polarFixCacheUpdater); - } - } - - @Override - public void raceAdded(TrackedRace trackedRace) { - // replicate the addition of the tracked race: - CreateTrackedRace op = new CreateTrackedRace(trackedRace.getRaceIdentifier(), trackedRace.getWindStore(), - trackedRace.getGPSFixStore(), trackedRace.getDelayToLiveInMillis(), - trackedRace.getMillisecondsOverWhichToAverageWind(), - trackedRace.getMillisecondsOverWhichToAverageSpeed()); - replicate(op); - linkRaceToConfiguredLeaderboardColumns(trackedRace); - TrackedRaceReplicator trackedRaceReplicator = new TrackedRaceReplicator(trackedRace); - trackedRaceReplicators.put(trackedRace, trackedRaceReplicator); - trackedRace.addListener(trackedRaceReplicator, /* fire wind already loaded */true, true); - - PolarFixCacheUpdater polarFixCacheUpdater = new PolarFixCacheUpdater(trackedRace); - polarFixCacheUpdaters.put(trackedRace, polarFixCacheUpdater); - trackedRace.addListener(polarFixCacheUpdater); - - if (polarDataService != null) { - trackedRace.setPolarDataService(polarDataService); - } - } - } - - private class PolarFixCacheUpdater extends AbstractRaceChangeListener { - - private final TrackedRace race; - - public PolarFixCacheUpdater(TrackedRace race) { - this.race = race; - } - - @Override - public void competitorPositionChanged(GPSFixMoving fix, Competitor item) { - if (polarDataService != null) { - polarDataService.competitorPositionChanged(fix, item, race); - } - } - - @Override - public void statusChanged(TrackedRaceStatus newStatus, TrackedRaceStatus oldStatus) { - if (oldStatus.getStatus() == TrackedRaceStatusEnum.LOADING - && newStatus.getStatus() != TrackedRaceStatusEnum.LOADING) { - if (polarDataService != null) { - polarDataService.raceFinishedLoading(race); - } - } - } - - } - - private class TrackedRaceReplicator implements RaceChangeListener { - private final TrackedRace trackedRace; - - public TrackedRaceReplicator(TrackedRace trackedRace) { - this.trackedRace = trackedRace; - } - - @Override - public void windSourcesToExcludeChanged(Iterable windSourcesToExclude) { - replicate(new UpdateWindSourcesToExclude(getRaceIdentifier(), windSourcesToExclude)); - } - - @Override - public void startOfTrackingChanged(TimePoint startOfTracking) { - replicate(new UpdateStartOfTracking(getRaceIdentifier(), startOfTracking)); - } - - @Override - public void endOfTrackingChanged(TimePoint endOfTracking) { - replicate(new UpdateEndOfTracking(getRaceIdentifier(), endOfTracking)); - } - - @Override - public void startTimeReceivedChanged(TimePoint startTimeReceived) { - replicate(new UpdateStartTimeReceived(getRaceIdentifier(), startTimeReceived)); - } - - @Override - public void startOfRaceChanged(TimePoint oldStartOfRace, TimePoint newStartOfRace) { - // no action required; the update signaled by this call is implicit; for explicit updates - // see raceTimesChanged(TimePoint, TimePoint, TimePoint). - } - - @Override - public void waypointAdded(int zeroBasedIndex, Waypoint waypointThatGotAdded) { - // no-op; the course change is replicated by the separate CourseChangeReplicator - } - - @Override - public void waypointRemoved(int zeroBasedIndex, Waypoint waypointThatGotRemoved) { - // no-op; the course change is replicated by the separate CourseChangeReplicator - } - - @Override - public void delayToLiveChanged(long delayToLiveInMillis) { - replicate(new UpdateRaceDelayToLive(getRaceIdentifier(), delayToLiveInMillis)); - } - - @Override - public void windDataReceived(Wind wind, WindSource windSource) { - replicate(new RecordWindFix(getRaceIdentifier(), windSource, wind)); - } - - @Override - public void windDataRemoved(Wind wind, WindSource windSource) { - replicate(new RemoveWindFix(getRaceIdentifier(), windSource, wind)); - } - - @Override - public void windAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) { - replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage)); - } - - @Override - public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) { - replicate(new RecordCompetitorGPSFix(getRaceIdentifier(), competitor, fix)); - } - - @Override - public void statusChanged(TrackedRaceStatus newStatus, TrackedRaceStatus oldStatus) { - replicate(new UpdateTrackedRaceStatus(getRaceIdentifier(), newStatus)); - } - - @Override - public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { - final RecordMarkGPSFix operation; - if (firstInTrack) { - operation = new RecordMarkGPSFixForNewMarkTrack(getRaceIdentifier(), mark, fix); - } else { - operation = new RecordMarkGPSFixForExistingTrack(getRaceIdentifier(), mark, fix); - } - replicate(operation); - } - - @Override - public void markPassingReceived(Competitor competitor, Map oldMarkPassings, - Iterable markPassings) { - replicate(new UpdateMarkPassings(getRaceIdentifier(), competitor, markPassings)); - } - - @Override - public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) { - replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage)); - } - - private RegattaAndRaceIdentifier getRaceIdentifier() { - return trackedRace.getRaceIdentifier(); - } - } - - /** - * Based on the trackedRace's {@link TrackedRace#getRaceIdentifier() race identifier}, the tracked race - * is (re-)associated to all {@link RaceColumn race columns} that currently have no - * {@link RaceColumn#getTrackedRace(Fleet) tracked race assigned} and whose - * {@link RaceColumn#getRaceIdentifier(Fleet) race identifier} equals that of trackedRace. - */ - private void linkRaceToConfiguredLeaderboardColumns(TrackedRace trackedRace) { - boolean leaderboardHasChanged = false; - RegattaAndRaceIdentifier trackedRaceIdentifier = trackedRace.getRaceIdentifier(); - for (Leaderboard leaderboard : getLeaderboards().values()) { - for (RaceColumn column : leaderboard.getRaceColumns()) { - for (Fleet fleet : column.getFleets()) { - if (trackedRaceIdentifier.equals(column.getRaceIdentifier(fleet)) - && column.getTrackedRace(fleet) == null) { - column.setTrackedRace(fleet, trackedRace); - leaderboardHasChanged = true; - replicate(new ConnectTrackedRaceToLeaderboardColumn(leaderboard.getName(), column.getName(), - fleet.getName(), trackedRaceIdentifier)); - } - } - } - if (leaderboardHasChanged) { - // Update the corresponding groups, to keep them in sync - syncGroupsAfterLeaderboardChange(leaderboard, /* doDatabaseUpdate */false); - } - } - } - - @Override - public void stopTracking(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { - final Set trackersForRegatta = raceTrackersByRegatta.get(regatta); - if (trackersForRegatta != null) { - for (RaceTracker raceTracker : trackersForRegatta) { - final Set races = raceTracker.getRaces(); - if (races != null) { - for (RaceDefinition race : races) { - stopTrackingWind(regatta, race); - } - } - raceTracker.stop(/* preemptive */false); - final Object trackerId = raceTracker.getID(); - final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); - try { - raceTrackersByID.remove(trackerId); - } finally { - unlockRaceTrackersById(trackerId, lock); - } - raceTrackersByID.remove(trackerId); - } - LockUtil.lockForWrite(raceTrackersByRegattaLock); - try { - raceTrackersByRegatta.remove(regatta); - } finally { - LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); - } - } - } - - @Override - public void stopTrackingAndRemove(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { - stopTracking(regatta); - if (regatta != null) { - if (regatta.getName() != null) { - logger.info("Removing regatta " + regatta.getName() + " (" + regatta.hashCode() + ") from " + this); - LockUtil.lockForWrite(regattasByNameLock); - try { - regattasByName.remove(regatta.getName()); - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - LockUtil.lockForWrite(regattaTrackingCacheLock); - try { - regattaTrackingCache.remove(regatta); - } finally { - LockUtil.unlockAfterWrite(regattaTrackingCacheLock); - } - regatta.removeRegattaListener(this); - regatta.removeRaceColumnListener(raceLogReplicator); - regatta.removeRaceColumnListener(raceLogScoringReplicator); - } - for (RaceDefinition race : regatta.getAllRaces()) { - stopTrackingWind(regatta, race); - } - } - } - - /** - * The tracker will initially try to connect to the tracking infrastructure to obtain basic race master data. If - * this fails after some timeout, to avoid garbage and lingering threads, the task scheduled by this method will - * check after the timeout expires if race master data was successfully received. If so, the tracker continues - * normally. Otherwise, the tracker is shut down orderly by calling {@link RaceTracker#stop(boolean) stopping}. - * - * @return the scheduled task, in case the caller wants to {@link ScheduledFuture#cancel(boolean) cancel} it, e.g., - * when the tracker is stopped or has successfully received the race - */ - private ScheduledFuture scheduleAbortTrackerAfterInitialTimeout(final RaceTracker tracker, - final long timeoutInMilliseconds) { - ScheduledFuture task = getScheduler().schedule(new Runnable() { - @Override - public void run() { - if (tracker.getRaces() == null || tracker.getRaces().isEmpty()) { - try { - Regatta regatta = tracker.getRegatta(); - logger.log(Level.SEVERE, "RaceDefinition for a race in regatta " + regatta.getName() - + " not obtained within " + timeoutInMilliseconds - + "ms. Aborting tracker for this race."); - Set trackersForRegatta = raceTrackersByRegatta.get(regatta); - if (trackersForRegatta != null) { - trackersForRegatta.remove(tracker); - } - tracker.stop(/* preemptive */true); - final Object trackerId = tracker.getID(); - final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); - try { - raceTrackersByID.remove(trackerId); - } finally { - unlockRaceTrackersById(trackerId, lock); - } - if (trackersForRegatta == null || trackersForRegatta.isEmpty()) { - stopTracking(regatta); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "scheduleAbortTrackerAfterInitialTimeout", e); - e.printStackTrace(); - } - } - } - }, /* delay */timeoutInMilliseconds, /* unit */TimeUnit.MILLISECONDS); - return task; - } - - @Override - public void stopTracking(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException, - InterruptedException { - logger.info("Stopping tracking for " + race + "..."); - final Set trackerSet = raceTrackersByRegatta.get(regatta); - if (trackerSet != null) { - Iterator trackerIter = trackerSet.iterator(); - while (trackerIter.hasNext()) { - RaceTracker raceTracker = trackerIter.next(); - if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) { - logger.info("Found tracker to stop for races " + raceTracker.getRaces()); - raceTracker.stop(/* preemptive */false); - trackerIter.remove(); - final Object trackerId = raceTracker.getID(); - final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); - try { - raceTrackersByID.remove(trackerId); - } finally { - unlockRaceTrackersById(trackerId, lock); - } - } - } - } else { - logger.warning("Didn't find any trackers for regatta " + regatta); - } - stopTrackingWind(regatta, race); - // if the last tracked race was removed, confirm that tracking for the entire regatta has stopped - if (trackerSet == null || trackerSet.isEmpty()) { - stopTracking(regatta); - } - } - - @Override - public void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { - Set leaderboardsToRemove = new HashSet<>(); - for (Leaderboard leaderboard : getLeaderboards().values()) { - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - if (regattaLeaderboard.getRegatta() == regatta) { - leaderboardsToRemove.add(regattaLeaderboard); - } - } - } - for (RegattaLeaderboard regattaLeaderboardToRemove : leaderboardsToRemove) { - removeLeaderboard(regattaLeaderboardToRemove.getName()); - } - // avoid ConcurrentModificationException by copying the races to remove: - Set racesToRemove = new HashSet<>(); - Util.addAll(regatta.getAllRaces(), racesToRemove); - for (RaceDefinition race : racesToRemove) { - removeRace(regatta, race); - mongoObjectFactory.removeRegattaForRaceID(race.getName(), regatta); - persistentRegattasForRaceIDs.remove(race.getId().toString()); - } - if (regatta.isPersistent()) { - mongoObjectFactory.removeRegatta(regatta); - } - LockUtil.lockForWrite(regattasByNameLock); - try { - regattasByName.remove(regatta.getName()); - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - regatta.removeRegattaListener(this); - regatta.removeRaceColumnListener(raceLogReplicator); - regatta.removeRaceColumnListener(raceLogScoringReplicator); - onRegattaLikeRemoved(regatta); - } - - @Override - public void removeSeries(Series series) throws MalformedURLException, IOException, InterruptedException { - Regatta regatta = series.getRegatta(); - regatta.removeSeries(series); - if (regatta.isPersistent()) { - mongoObjectFactory.storeRegatta(regatta); - } - } - - @Override - public Regatta updateRegatta(RegattaIdentifier regattaIdentifier, TimePoint startDate, TimePoint endDate, - Serializable newDefaultCourseAreaId, RegattaConfiguration newRegattaConfiguration, - Iterable series, boolean useStartTimeInference) { - // We're not doing any renaming of the regatta itself, therefore we don't have to sync on the maps. - Regatta regatta = getRegatta(regattaIdentifier); - CourseArea newCourseArea = getCourseArea(newDefaultCourseAreaId); - if (newCourseArea != regatta.getDefaultCourseArea()) { - regatta.setDefaultCourseArea(newCourseArea); - } - regatta.setStartDate(startDate); - regatta.setEndDate(endDate); - if (regatta.useStartTimeInference() != useStartTimeInference) { - regatta.setUseStartTimeInference(useStartTimeInference); - final DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(regatta); - if (trackedRegatta != null) { - trackedRegatta.lockTrackedRacesForRead(); - try { - for (DynamicTrackedRace trackedRace : trackedRegatta.getTrackedRaces()) { - // the start times of the regatta's tracked races now have to be re-evaluated the next time they - // are queried - trackedRace.invalidateStartTime(); - } - } finally { - trackedRegatta.unlockTrackedRacesAfterRead(); - } - } - } - regatta.setRegattaConfiguration(newRegattaConfiguration); - if (series != null) { - for (Series seriesObj : series) { - regatta.addSeries(seriesObj); - } - } - regatta.adjustEventToRegattaAssociation(this); - if (regatta.isPersistent()) { - mongoObjectFactory.storeRegatta(regatta); - } - return regatta; - } - - @Override - public void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException, - InterruptedException { - logger.info("Removing the race " + race + "..."); - stopAllTrackersForWhichRaceIsLastReachable(regatta, race); - stopTrackingWind(regatta, race); - TrackedRace trackedRace = getExistingTrackedRace(regatta, race); - if (trackedRace != null) { - TrackedRegatta trackedRegatta = getTrackedRegatta(regatta); - final boolean isTrackedRacesEmpty; - if (trackedRegatta != null) { - trackedRegatta.lockTrackedRacesForWrite(); - try { - trackedRegatta.removeTrackedRace(trackedRace); - isTrackedRacesEmpty = Util.isEmpty(trackedRegatta.getTrackedRaces()); - } finally { - trackedRegatta.unlockTrackedRacesAfterWrite(); - } - } else { - isTrackedRacesEmpty = false; - } - if (isTrackedRacesEmpty) { - removeTrackedRegatta(regatta); - } - // remove tracked race from RaceColumns of regatta - for (Series series : regatta.getSeries()) { - for (RaceColumnInSeries raceColumn : series.getRaceColumns()) { - for (Fleet fleet : series.getFleets()) { - if (raceColumn.getTrackedRace(fleet) == trackedRace) { - raceColumn.releaseTrackedRace(fleet); - } - } - } - } - for (Leaderboard leaderboard : getLeaderboards().values()) { - if (leaderboard instanceof FlexibleLeaderboard) { // RegattaLeaderboards have implicitly been updated by - // the code above - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - for (Fleet fleet : raceColumn.getFleets()) { - if (raceColumn.getTrackedRace(fleet) == trackedRace) { - raceColumn.releaseTrackedRace(fleet); // but leave the RaceIdentifier on the race column - // untouched, e.g., for later re-load - } - } - } - } - } - } - // remove the race from the (default) regatta if the regatta is not persistently stored - regatta.removeRace(race); - if (!regatta.isPersistent() && Util.isEmpty(regatta.getAllRaces())) { - logger.info("Removing regatta " + regatta.getName() + " (" + regatta.hashCode() + ") from service " + this); - LockUtil.lockForWrite(regattasByNameLock); - try { - regattasByName.remove(regatta.getName()); - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - regatta.removeRegattaListener(this); - regatta.removeRaceColumnListener(raceLogReplicator); - regatta.removeRaceColumnListener(raceLogScoringReplicator); - } - } - - /** - * Doesn't stop any wind trackers - */ - private void stopAllTrackersForWhichRaceIsLastReachable(Regatta regatta, RaceDefinition race) - throws MalformedURLException, IOException, InterruptedException { - if (raceTrackersByRegatta.containsKey(regatta)) { - Iterator trackerIter = raceTrackersByRegatta.get(regatta).iterator(); - while (trackerIter.hasNext()) { - RaceTracker raceTracker = trackerIter.next(); - if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) { - boolean foundReachableRace = false; - for (RaceDefinition raceTrackedByTracker : raceTracker.getRaces()) { - if (raceTrackedByTracker != race && isReachable(regatta, raceTrackedByTracker)) { - foundReachableRace = true; - break; - } - } - if (!foundReachableRace) { - // firstly stop the tracker - raceTracker.stop(/* preemptive */true); - // remove it from the raceTrackers by Regatta - trackerIter.remove(); - final Object trackerId = raceTracker.getID(); - final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); - try { - raceTrackersByID.remove(trackerId); - } finally { - unlockRaceTrackersById(trackerId, lock); - } - // if the last tracked race was removed, remove the entire regatta - if (raceTrackersByRegatta.get(regatta).isEmpty()) { - stopTracking(regatta); - } - } - } - } - } - } - - private boolean isReachable(Regatta regatta, RaceDefinition race) { - return Util.contains(regatta.getAllRaces(), race); - } - - @Override - public void startTrackingWind(Regatta regatta, RaceDefinition race, boolean correctByDeclination) throws Exception { - for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { - windTrackerFactory.createWindTracker(getOrCreateTrackedRegatta(regatta), race, correctByDeclination); - } - } - - @Override - public void stopTrackingWind(Regatta regatta, RaceDefinition race) throws SocketException, IOException { - for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { - WindTracker windTracker = windTrackerFactory.getExistingWindTracker(race); - if (windTracker != null) { - windTracker.stop(); - } - } - } - - @Override - public Iterable> getWindTrackedRaces() { - List> result = new ArrayList>(); - for (Regatta regatta : getAllRegattas()) { - for (RaceDefinition race : regatta.getAllRaces()) { - for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { - WindTracker windTracker = windTrackerFactory.getExistingWindTracker(race); - if (windTracker != null) { - result.add(new com.sap.sse.common.Util.Triple(regatta, race, - windTracker.toString())); - } - } - } - } - return result; - } - - @Override - public DynamicTrackedRace getTrackedRace(Regatta regatta, RaceDefinition race) { - return getOrCreateTrackedRegatta(regatta).getTrackedRace(race); - } - - private DynamicTrackedRace getExistingTrackedRace(Regatta regatta, RaceDefinition race) { - return getOrCreateTrackedRegatta(regatta).getExistingTrackedRace(race); - } - - @Override - public DynamicTrackedRegatta getOrCreateTrackedRegatta(Regatta regatta) { - cacheAndReplicateDefaultRegatta(regatta); - LockUtil.lockForWrite(regattaTrackingCacheLock); - try { - DynamicTrackedRegatta result = regattaTrackingCache.get(regatta); - if (result == null) { - logger.info("Creating DynamicTrackedRegattaImpl for regatta " + regatta.getName() + " with hashCode " - + regatta.hashCode()); - result = new DynamicTrackedRegattaImpl(regatta); - replicate(new TrackRegatta(regatta.getRegattaIdentifier())); - regattaTrackingCache.put(regatta, result); - ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result); - } - return result; - } finally { - LockUtil.unlockAfterWrite(regattaTrackingCacheLock); - } - } - - @Override - public DynamicTrackedRegatta getTrackedRegatta(com.sap.sailing.domain.base.Regatta regatta) { - return regattaTrackingCache.get(regatta); - } - - @Override - public void removeTrackedRegatta(Regatta regatta) { - logger.info("Removing regatta " + regatta.getName() + " from regattaTrackingCache"); - final DynamicTrackedRegatta trackedRegatta; - LockUtil.lockForWrite(regattaTrackingCacheLock); - try { - trackedRegatta = regattaTrackingCache.remove(regatta); - } finally { - LockUtil.unlockAfterWrite(regattaTrackingCacheLock); - } - stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(trackedRegatta); - } - - @Override - public Regatta getRegatta(RegattaName regattaName) { - return (Regatta) regattasByName.get(regattaName.getRegattaName()); - } - - @Override - public Regatta getRegatta(RegattaIdentifier regattaIdentifier) { - return (Regatta) regattaIdentifier.getRegatta(this); - } - - @Override - public DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { - DynamicTrackedRace result = null; - Regatta regatta = regattasByName.get(raceIdentifier.getRegattaName()); - if (regatta != null) { - DynamicTrackedRegatta trackedRegatta = regattaTrackingCache.get(regatta); - if (trackedRegatta != null) { - RaceDefinition race = getRace(raceIdentifier); - if (race != null) { - result = trackedRegatta.getTrackedRace(race); - } - } - } - return result; - } - - @Override - public DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { - Regatta regatta = getRegattaByName(raceIdentifier.getRegattaName()); - DynamicTrackedRace trackedRace = null; - if (regatta != null) { - RaceDefinition race = regatta.getRaceByName(raceIdentifier.getRaceName()); - trackedRace = getOrCreateTrackedRegatta(regatta).getExistingTrackedRace(race); - } - return trackedRace; - } - - @Override - public RaceDefinition getRace(RegattaAndRaceIdentifier regattaNameAndRaceName) { - RaceDefinition result = null; - Regatta regatta = getRegatta(regattaNameAndRaceName); - if (regatta != null) { - result = regatta.getRaceByName(regattaNameAndRaceName.getRaceName()); - } - return result; - } - - @Override - public Map getLeaderboardGroups() { - return Collections.unmodifiableMap(new HashMap(leaderboardGroupsByName)); - } - - @Override - public LeaderboardGroup getLeaderboardGroupByName(String groupName) { - return leaderboardGroupsByName.get(groupName); - } - - @Override - public LeaderboardGroup getLeaderboardGroupByID(UUID leaderboardGroupID) { - return leaderboardGroupsByID.get(leaderboardGroupID); - } - - @Override - public LeaderboardGroup addLeaderboardGroup(UUID id, String groupName, String description, String displayName, - boolean displayGroupsInReverseOrder, List leaderboardNames, - int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { - ArrayList leaderboards = new ArrayList<>(); - for (String leaderboardName : leaderboardNames) { - Leaderboard leaderboard = leaderboardsByName.get(leaderboardName); - if (leaderboard == null) { - throw new IllegalArgumentException("No leaderboard with name " + leaderboardName + " found"); - } else { - leaderboards.add(leaderboard); - } - } - LeaderboardGroup result = new LeaderboardGroupImpl(id, groupName, description, displayName, - displayGroupsInReverseOrder, leaderboards); - if (overallLeaderboardScoringSchemeType != null) { - // create overall leaderboard and its discards settings - addOverallLeaderboardToLeaderboardGroup(result, - getBaseDomainFactory().createScoringScheme(overallLeaderboardScoringSchemeType), - overallLeaderboardDiscardThresholds); - } - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - if (leaderboardGroupsByName.containsKey(groupName)) { - throw new IllegalArgumentException("Leaderboard group with name " + groupName + " already exists"); - } - leaderboardGroupsByName.put(groupName, result); - leaderboardGroupsByID.put(result.getId(), result); - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - mongoObjectFactory.storeLeaderboardGroup(result); - return result; - } - - @Override - public void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup) { - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - String groupName = leaderboardGroup.getName(); - if (leaderboardGroupsByName.containsKey(groupName)) { - throw new IllegalArgumentException("Leaderboard group with name " + groupName + " already exists"); - } - leaderboardGroupsByName.put(groupName, leaderboardGroup); - leaderboardGroupsByID.put(leaderboardGroup.getId(), leaderboardGroup); - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - if (leaderboardGroup.hasOverallLeaderboard()) { - addLeaderboard(leaderboardGroup.getOverallLeaderboard()); - } - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - } - - @Override - public void removeLeaderboardGroup(String groupName) { - final LeaderboardGroup leaderboardGroup; - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - leaderboardGroup = leaderboardGroupsByName.remove(groupName); - if (leaderboardGroup != null) { - leaderboardGroupsByID.remove(leaderboardGroup.getId()); - } - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - mongoObjectFactory.removeLeaderboardGroup(groupName); - if (leaderboardGroup != null && leaderboardGroup.getOverallLeaderboard() != null) { - removeLeaderboard(leaderboardGroup.getOverallLeaderboard().getName()); - } - } - - @Override - public void renameLeaderboardGroup(String oldName, String newName) { - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - final LeaderboardGroup toRename = leaderboardGroupsByName.get(oldName); - if (toRename == null) { - throw new IllegalArgumentException("No leaderboard group with name " + oldName + " found"); - } - if (leaderboardGroupsByName.containsKey(newName)) { - throw new IllegalArgumentException("Leaderboard group with name " + newName + " already exists"); - } - leaderboardGroupsByName.remove(oldName); - toRename.setName(newName); - leaderboardGroupsByName.put(newName, toRename); - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - mongoObjectFactory.renameLeaderboardGroup(oldName, newName); - } - - @Override - public void updateLeaderboardGroup(String oldName, String newName, String description, String displayName, - List leaderboardNames, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType) { - if (!oldName.equals(newName)) { - renameLeaderboardGroup(oldName, newName); - } - LeaderboardGroup group = getLeaderboardGroupByName(newName); - if (!description.equals(group.getDescription())) { - group.setDescriptiom(description); - } - if (!Util.equalsWithNull(displayName, group.getDisplayName())) { - group.setDisplayName(displayName); - } - group.clearLeaderboards(); - for (String leaderboardName : leaderboardNames) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - group.addLeaderboard(leaderboard); - } - } - Leaderboard overallLeaderboard = group.getOverallLeaderboard(); - if (overallLeaderboard != null) { - if (overallLeaderboardScoringSchemeType == null) { - group.setOverallLeaderboard(null); - removeLeaderboard(overallLeaderboard.getName()); - } else { - // update existing overall leaderboard's discards settings; scoring scheme cannot be updated in-place - overallLeaderboard.setCrossLeaderboardResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl( - overallLeaderboardDiscardThresholds)); - updateStoredLeaderboard(overallLeaderboard); - } - } else if (overallLeaderboard == null && overallLeaderboardScoringSchemeType != null) { - addOverallLeaderboardToLeaderboardGroup(group, - getBaseDomainFactory().createScoringScheme(overallLeaderboardScoringSchemeType), - overallLeaderboardDiscardThresholds); - } - updateStoredLeaderboardGroup(group); - } - - private void addOverallLeaderboardToLeaderboardGroup(LeaderboardGroup leaderboardGroup, - ScoringScheme scoringScheme, int[] discardThresholds) { - Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, scoringScheme, - new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); - leaderboardGroup.setOverallLeaderboard(overallLeaderboard); - addLeaderboard(overallLeaderboard); - updateStoredLeaderboard(overallLeaderboard); - } - - @Override - public void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup) { - mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - } - - private ScheduledExecutorService getScheduler() { - return scheduler; - } - - @Override - public ObjectInputStream createObjectInputStreamResolvingAgainstCache(InputStream is) throws IOException { - return getBaseDomainFactory().createObjectInputStreamResolvingAgainstThisFactory(is); - } - - @Override - public ClassLoader getDeserializationClassLoader() { - return joinedClassLoader; - } - - @Override - public Serializable getId() { - return getClass().getName(); - } - - @Override - public Iterable> getOperationExecutionListeners() { - return operationExecutionListeners.keySet(); - } - - @Override - public void addOperationExecutionListener(OperationExecutionListener listener) { - operationExecutionListeners.put(listener, listener); - } - - @Override - public void removeOperationExecutionListener(OperationExecutionListener listener) { - operationExecutionListeners.remove(listener); - } - - @Override - public void serializeForInitialReplicationInternal(ObjectOutputStream oos) throws IOException { - StringBuffer logoutput = new StringBuffer(); - - logger.info("Serializing regattas..."); - oos.writeObject(regattasByName); - logoutput.append("Serialized " + regattasByName.size() + " regattas\n"); - for (Regatta regatta : regattasByName.values()) { - logoutput.append(String.format("%3s\n", regatta.toString())); - } - - logger.info("Serializing events..."); - oos.writeObject(eventsById); - logoutput.append("\nSerialized " + eventsById.size() + " events\n"); - for (Event event : eventsById.values()) { - logoutput.append(String.format("%3s\n", event.toString())); - } - - logger.info("Serializing regattas observed..."); - oos.writeObject(regattasObservedForDefaultLeaderboard); - logger.info("Serializing regatta tracking cache..."); - oos.writeObject(regattaTrackingCache); - logger.info("Serializing leaderboard groups..."); - oos.writeObject(leaderboardGroupsByName); - logoutput.append("Serialized " + leaderboardGroupsByName.size() + " leaderboard groups\n"); - for (LeaderboardGroup lg : leaderboardGroupsByName.values()) { - logoutput.append(String.format("%3s\n", lg.toString())); - } - logger.info("Serializing leaderboards..."); - oos.writeObject(leaderboardsByName); - logoutput.append("Serialized " + leaderboardsByName.size() + " leaderboards\n"); - for (Leaderboard lg : leaderboardsByName.values()) { - logoutput.append(String.format("%3s\n", lg.toString())); - } - logger.info("Serializing media library..."); - mediaLibrary.serialize(oos); - logoutput.append("Serialized " + mediaLibrary.allTracks().size() + " media tracks\n"); - for (MediaTrack lg : mediaLibrary.allTracks()) { - logoutput.append(String.format("%3s\n", lg.toString())); - } - logger.info("Serializing persisted competitors..."); - oos.writeObject(competitorStore); - logoutput.append("Serialized " + competitorStore.size() + " persisted competitors\n"); - - logger.info("Serializing configuration map..."); - oos.writeObject(configurationMap); - logoutput.append("Serialized " + configurationMap.size() + " configuration entries\n"); - for (DeviceConfigurationMatcher matcher : configurationMap.keySet()) { - logoutput.append(String.format("%3s\n", matcher.toString())); - } - - logger.info("Serializing remote sailing server references..."); - final ArrayList remoteServerReferences = new ArrayList<>(remoteSailingServerSet - .getCachedEventsForRemoteSailingServers().keySet()); - oos.writeObject(remoteServerReferences); - logoutput.append("Serialized " + remoteServerReferences.size() + " remote sailing server references\n"); - - logger.info(logoutput.toString()); - } - - @SuppressWarnings("unchecked") - // all the casts of ois.readObject()'s return value to Map<..., ...> - // the type-parameters in the casts of the de-serialized collection objects can't be checked - @Override - public void initiallyFillFromInternal(ObjectInputStream ois) throws IOException, ClassNotFoundException, - InterruptedException { - logger.info("Performing initial replication load on " + this); - // Use this object's class's class loader as the context class loader which will then be used for - // de-serialization; this will cause all classes to be visible that this bundle - // (com.sap.sailing.server) can see - StringBuffer logoutput = new StringBuffer(); - logger.info("Reading all regattas..."); - regattasByName.putAll((Map) ois.readObject()); - logoutput.append("Received " + regattasByName.size() + " NEW regattas\n"); - for (Regatta regatta : regattasByName.values()) { - logoutput.append(String.format("%3s\n", regatta.toString())); - } - - logger.info("Reading all events..."); - eventsById.putAll((Map) ois.readObject()); - logoutput.append("\nReceived " + eventsById.size() + " NEW events\n"); - for (Event event : eventsById.values()) { - logoutput.append(String.format("%3s\n", event.toString())); - } - - // it is important that the leaderboards and tracked regattas are cleared before auto-linking to - // old leaderboards takes place which then don't match the new ones - logger.info("Reading all dynamic tracked regattas..."); - for (DynamicTrackedRegatta trackedRegattaToObserve : (Set) ois.readObject()) { - ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(trackedRegattaToObserve); - } - - logger.info("Reading all of the regatta tracking cache..."); - regattaTrackingCache.putAll((Map) ois.readObject()); - logoutput.append("Received " + regattaTrackingCache.size() + " NEW regatta tracking cache entries\n"); - - logger.info("Reading leaderboard groups..."); - leaderboardGroupsByName.putAll((Map) ois.readObject()); - logoutput.append("Received " + leaderboardGroupsByName.size() + " NEW leaderboard groups\n"); - for (LeaderboardGroup lg : leaderboardGroupsByName.values()) { - leaderboardGroupsByID.put(lg.getId(), lg); - logoutput.append(String.format("%3s\n", lg.toString())); - } - - logger.info("Reading leaderboards by name..."); - leaderboardsByName.putAll((Map) ois.readObject()); - logoutput.append("Received " + leaderboardsByName.size() + " NEW leaderboards\n"); - for (Leaderboard leaderboard : leaderboardsByName.values()) { - logoutput.append(String.format("%3s\n", leaderboard.toString())); - } - - // now fix ScoreCorrectionListener setup for LeaderboardGroupMetaLeaderboard instances: - for (Leaderboard leaderboard : leaderboardsByName.values()) { - if (leaderboard instanceof LeaderboardGroupMetaLeaderboard) { - ((LeaderboardGroupMetaLeaderboard) leaderboard) - .registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards(); - } else if (leaderboard instanceof FlexibleLeaderboard) { - // and re-establish the RaceLogReplicator as listener on FlexibleLeaderboard objects - leaderboard.addRaceColumnListener(raceLogReplicator); - } - } - - logger.info("Reading media library..."); - mediaLibrary.deserialize(ois); - logoutput.append("Received " + mediaLibrary.allTracks().size() + " NEW media tracks\n"); - for (MediaTrack mediatrack : mediaLibrary.allTracks()) { - logoutput.append(String.format("%3s\n", mediatrack.toString())); - } - - // only copy the competitors from the deserialized competitor store; don't use it because it will have set - // a default Mongo object factory - logger.info("Reading competitors..."); - for (Competitor competitor : ((CompetitorStore) ois.readObject()).getCompetitors()) { - DynamicCompetitor dynamicCompetitor = (DynamicCompetitor) competitor; - // the following should actually be redundant because during de-serialization the Competitor objects, - // whose classes implement IsManagedByCache, should already have been got/created from/in the - // competitor store - competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), - dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(), - dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), - dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile()); - } - logoutput.append("Received " + competitorStore.size() + " NEW competitors\n"); - - logger.info("Reading device configurations..."); - configurationMap.putAll((DeviceConfigurationMapImpl) ois.readObject()); - logoutput.append("Received " + configurationMap.size() + " NEW configuration entries\n"); - for (DeviceConfigurationMatcher matcher : configurationMap.keySet()) { - logoutput.append(String.format("%3s\n", matcher.toString())); - } - - logger.info("Reading remote sailing server references..."); - for (RemoteSailingServerReference remoteSailingServerReference : (Iterable) ois - .readObject()) { - remoteSailingServerSet.add(remoteSailingServerReference); - logoutput.append("Received remote sailing server reference " + remoteSailingServerReference); - } - - // make sure to initialize listeners correctly - for (Regatta regatta : regattasByName.values()) { - RegattaImpl regattaImpl = (RegattaImpl) regatta; - regattaImpl.initializeSeriesAfterDeserialize(); - regattaImpl.addRaceColumnListener(raceLogReplicator); - } - // re-establish RaceLogResolver references to this RacingEventService in all TrackedRace instances - for (DynamicTrackedRegatta trackedRegatta : regattaTrackingCache.values()) { - trackedRegatta.lockTrackedRacesForRead(); - try { - for (TrackedRace trackedRace : trackedRegatta.getTrackedRaces()) { - ((TrackedRaceImpl) trackedRace).setRaceLogResolver(this); - } - } finally { - trackedRegatta.unlockTrackedRacesAfterRead(); - } - } - logger.info(logoutput.toString()); - } - - @Override - public void clearReplicaState() throws MalformedURLException, IOException, InterruptedException { - logger.info("Clearing all data structures..."); - LockUtil.lockForWrite(regattasByNameLock); - try { - regattasByName.clear(); - } finally { - LockUtil.unlockAfterWrite(regattasByNameLock); - } - regattasObservedForDefaultLeaderboard.clear(); - - if (raceTrackersByRegatta != null && !raceTrackersByRegatta.isEmpty()) { - for (DynamicTrackedRegatta regatta : regattaTrackingCache.values()) { - final Set trackers = raceTrackersByRegatta.get(regatta.getRegatta()); - if (trackers != null) { - for (RaceTracker tracker : trackers) { - tracker.stop(/* preemptive */true); - } - } - } - } - LockUtil.lockForWrite(regattaTrackingCacheLock); - try { - regattaTrackingCache.clear(); - } finally { - LockUtil.unlockAfterWrite(regattaTrackingCacheLock); - } - LockUtil.lockForWrite(raceTrackersByRegattaLock); - try { - raceTrackersByRegatta.clear(); - } finally { - LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); - } - LockUtil.lockForWrite(leaderboardGroupsByNameLock); - try { - leaderboardGroupsByName.clear(); - leaderboardGroupsByID.clear(); - } finally { - LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); - } - LockUtil.lockForWrite(leaderboardsByNameLock); - try { - leaderboardsByName.clear(); - } finally { - LockUtil.unlockAfterWrite(leaderboardsByNameLock); - } - eventsById.clear(); - mediaLibrary.clear(); - competitorStore.clear(); - remoteSailingServerSet.clear(); - } - - // Used for TESTING only - @Override - public Event addEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, - String venue, boolean isPublic, UUID id) { - Event result = createEventWithoutReplication(eventName, eventDescription, startDate, endDate, venue, isPublic, - id, /* officialWebsiteURL */null, /* sailorsInfoWebsiteURLAsString */null, - /* images */Collections. emptyList(), /* videos */Collections. emptyList()); - replicate(new CreateEvent(eventName, eventDescription, startDate, endDate, venue, isPublic, id, - /* officialWebsiteURLAsString */null, /* sailorsInfoWebsiteURLAsString */null, - /* images */Collections. emptyList(), /* videos */Collections. emptyList())); - return result; - } - - @Override - public void addEventWithoutReplication(Event event) { - addEvent(event); - } - - @Override - public Event createEventWithoutReplication(String eventName, String eventDescription, TimePoint startDate, - TimePoint endDate, String venue, boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, - Iterable images, Iterable videos) { - Event result = new EventImpl(eventName, startDate, endDate, venue, isPublic, id); - addEvent(result); - result.setDescription(eventDescription); - result.setOfficialWebsiteURL(officialWebsiteURL); - result.setImages(images); - result.setVideos(videos); - return result; - } - - private void addEvent(Event result) { - if (eventsById.containsKey(result.getId())) { - throw new IllegalArgumentException("Event with ID " + result.getId() - + " already exists which is pretty surprising..."); - } - eventsById.put(result.getId(), result); - mongoObjectFactory.storeEvent(result); - } - - @Override - public void updateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, - String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, - Iterable images, Iterable videos) { - final Event event = eventsById.get(id); - if (event == null) { - throw new IllegalArgumentException("Sailing event with ID " + id + " does not exist."); - } - event.setName(eventName); - event.setDescription(eventDescription); - event.setStartDate(startDate); - event.setEndDate(endDate); - event.setPublic(isPublic); - event.getVenue().setName(venueName); - List leaderboardGroups = new ArrayList<>(); - for (UUID lgid : leaderboardGroupIds) { - LeaderboardGroup lg = getLeaderboardGroupByID(lgid); - if (lg != null) { - leaderboardGroups.add(lg); - } else { - logger.info("Couldn't find leaderboard group with ID " + lgid + " while updating event " - + event.getName()); - } - } - event.setLeaderboardGroups(leaderboardGroups); - event.setOfficialWebsiteURL(officialWebsiteURL); - event.setSailorsInfoWebsiteURL(sailorsInfoWebsiteURL); - event.setImages(images); - event.setVideos(videos); - // TODO consider use diffutils to compute diff between old and new leaderboard groups list and apply the patch - // to keep changes minimial - mongoObjectFactory.storeEvent(event); - } - - @Override - public void renameEvent(UUID id, String newName) { - final Event toRename = eventsById.get(id); - if (toRename == null) { - throw new IllegalArgumentException("No sailing event with ID " + id + " found."); - } - toRename.setName(newName); - mongoObjectFactory.renameEvent(id, newName); - replicate(new RenameEvent(id, newName)); - } - - @Override - public void removeEvent(UUID id) { - removeEventFromEventsById(id); - mongoObjectFactory.removeEvent(id); - replicate(new RemoveEvent(id)); - } - - protected void removeEventFromEventsById(Serializable id) { - eventsById.remove(id); - } - - @Override - public Regatta getRememberedRegattaForRace(Serializable raceID) { - return persistentRegattasForRaceIDs.get(raceID.toString()); - } - - /** - * Persistently remembers the association of the race with its {@link RaceDefinition#getId()} to the - * regatta with its {@link Regatta#getRegattaIdentifier() identifier} so that the next time - * {@link #getRememberedRegattaForRace(RaceDefinition)} is called with race as argument, - * regatta will be returned. - */ - private void setRegattaForRace(Regatta regatta, RaceDefinition race) { - setRegattaForRace(regatta, race.getId().toString()); - } - - @Override - public void setRegattaForRace(Regatta regatta, String raceIdAsString) { - persistentRegattasForRaceIDs.put(raceIdAsString, regatta); - mongoObjectFactory.storeRegattaForRaceID(raceIdAsString, regatta); - } - - @Override - public CourseArea[] addCourseAreas(UUID eventId, String[] courseAreaNames, UUID[] courseAreaIds) { - final CourseArea[] courseAreas = addCourseAreasWithoutReplication(eventId, courseAreaIds, courseAreaNames); - replicate(new AddCourseAreas(eventId, courseAreaNames, courseAreaIds)); - return courseAreas; - } - - @Override - public CourseArea[] addCourseAreasWithoutReplication(UUID eventId, UUID[] courseAreaIds, String[] courseAreaNames) { - final CourseArea[] result = new CourseArea[courseAreaNames.length]; - for (int i=0; i mediaTracks) { - mediaLibrary.addMediaTracks(mediaTracks); - } - - @Override - public void mediaTrackTitleChanged(MediaTrack mediaTrack) { - mediaDB.updateTitle(mediaTrack.dbId, mediaTrack.title); - mediaLibrary.titleChanged(mediaTrack); - replicate(new UpdateMediaTrackTitleOperation(mediaTrack)); - } - - @Override - public void mediaTrackUrlChanged(MediaTrack mediaTrack) { - mediaDB.updateUrl(mediaTrack.dbId, mediaTrack.url); - mediaLibrary.urlChanged(mediaTrack); - replicate(new UpdateMediaTrackUrlOperation(mediaTrack)); - } - - @Override - public void mediaTrackStartTimeChanged(MediaTrack mediaTrack) { - mediaDB.updateStartTime(mediaTrack.dbId, mediaTrack.startTime); - mediaLibrary.startTimeChanged(mediaTrack); - replicate(new UpdateMediaTrackStartTimeOperation(mediaTrack)); - } - - @Override - public void mediaTrackDurationChanged(MediaTrack mediaTrack) { - mediaDB.updateDuration(mediaTrack.dbId, mediaTrack.duration); - mediaLibrary.durationChanged(mediaTrack); - replicate(new UpdateMediaTrackDurationOperation(mediaTrack)); - } - - @Override - public void mediaTrackAssignedRacesChanged(MediaTrack mediaTrack) { - mediaDB.updateRace(mediaTrack.dbId, mediaTrack.assignedRaces); - mediaLibrary.assignedRacesChanged(mediaTrack); - replicate(new UpdateMediaTrackRacesOperation(mediaTrack)); - - } - - @Override - public void mediaTrackDeleted(MediaTrack mediaTrack) { - mediaDB.deleteMediaTrack(mediaTrack.dbId); - mediaLibrary.deleteMediaTrack(mediaTrack); - replicate(new RemoveMediaTrackOperation(mediaTrack)); - } - - @Override - public void mediaTracksImported(Collection mediaTracksToImport, boolean override) { - for (MediaTrack trackToImport : mediaTracksToImport) { - MediaTrack existingTrack = mediaLibrary.lookupMediaTrack(trackToImport); - if (existingTrack == null) { - mediaDB.insertMediaTrackWithId(trackToImport.dbId, trackToImport.title, trackToImport.url, - trackToImport.startTime, trackToImport.duration, trackToImport.mimeType, - trackToImport.assignedRaces); - mediaTrackAdded(trackToImport); - } else if (override) { - - // Using fine-grained update methods. - // Rationale: Changes on more than one track property are rare - // and don't justify the introduction of a new set - // of methods (including replication). - if (!Util.equalsWithNull(existingTrack.title, trackToImport.title)) { - mediaTrackTitleChanged(trackToImport); - } - if (!Util.equalsWithNull(existingTrack.url, trackToImport.url)) { - mediaTrackUrlChanged(trackToImport); - } - if (!Util.equalsWithNull(existingTrack.startTime, trackToImport.startTime)) { - mediaTrackStartTimeChanged(trackToImport); - } - if (!Util.equalsWithNull(existingTrack.duration, trackToImport.duration)) { - mediaTrackDurationChanged(trackToImport); - } - if (!Util.equalsWithNull(existingTrack.assignedRaces, trackToImport.assignedRaces)) { - mediaTrackAssignedRacesChanged(trackToImport); - } - } - } - } - - @Override - public Collection getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier) { - return mediaLibrary.findMediaTracksForRace(regattaAndRaceIdentifier); - } - - @Override - public Collection getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier) { - TrackedRace trackedRace = getExistingTrackedRace(regattaAndRaceIdentifier); - if (trackedRace != null) { - if (trackedRace.isLive(MillisecondsTimePoint.now())) { - return mediaLibrary.findLiveMediaTracks(); - } else { - TimePoint raceStart = trackedRace.getStartOfRace() == null ? trackedRace.getStartOfTracking() - : trackedRace.getStartOfRace(); - TimePoint raceEnd = trackedRace.getEndOfRace() == null ? trackedRace.getEndOfTracking() : trackedRace - .getEndOfRace(); - return mediaLibrary.findMediaTracksInTimeRange(raceStart, raceEnd); - } - } else { - return Collections.emptyList(); - } - } - - @Override - public Collection getAllMediaTracks() { - return mediaLibrary.allTracks(); - } - - public String toString() { - return "RacingEventService: " + this.hashCode() + " Build: " + ServerInfo.getBuildVersion(); - } - - @Override - public void reloadRaceLog(String leaderboardName, String raceColumnName, String fleetName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn != null) { - Fleet fleetImpl = raceColumn.getFleetByName(fleetName); - RaceLog racelog = raceColumn.getRaceLog(fleetImpl); - if (racelog != null) { - raceColumn.reloadRaceLog(fleetImpl); - logger.info("Reloaded race log for fleet " + fleetImpl + " for race column " + raceColumn.getName() - + " for leaderboard " + leaderboard.getName()); - } - } - } - } - - @Override - public ConcurrentHashMap getPersistentRegattasForRaceIDs() { - return persistentRegattasForRaceIDs; - } - - @Override - public WindStore getWindStore() { - return windStore; - } - - @Override - public DeviceConfiguration getDeviceConfiguration(DeviceConfigurationIdentifier identifier) { - return configurationMap.getByMatch(identifier); - } - - @Override - public void createOrUpdateDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) { - configurationMap.put(matcher, configuration); - mongoObjectFactory.storeDeviceConfiguration(matcher, configuration); - replicate(new CreateOrUpdateDeviceConfiguration(matcher, configuration)); - } - - @Override - public void removeDeviceConfiguration(DeviceConfigurationMatcher matcher) { - configurationMap.remove(matcher); - mongoObjectFactory.removeDeviceConfiguration(matcher); - replicate(new RemoveDeviceConfiguration(matcher)); - } - - @Override - public Map getAllDeviceConfigurations() { - return new HashMap(configurationMap); - } - - @Override - public TimePoint setStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName, - String authorName, int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime, - RacingProcedureType racingProcedure) { - RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - final TimePoint result; - if (leaderboard instanceof HasRegattaLike && raceLog != null) { - RaceState state = RaceStateImpl.create(/* race log resolver */ this, raceLog, new LogEventAuthorImpl(authorName, authorPriority)); - if (passId > raceLog.getCurrentPassId()) { - state.setAdvancePass(logicalTimePoint); - } - state.setRacingProcedure(logicalTimePoint, racingProcedure); - state.forceNewStartTime(logicalTimePoint, startTime); - result = state.getStartTime(); - } else { - result = null; - } - return result; - } - - public RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn != null) { - Fleet fleetImpl = raceColumn.getFleetByName(fleetName); - return raceColumn.getRaceLog(fleetImpl); - } - } - return null; - } - - @Override - public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( - String leaderboardName, String raceColumnName, String fleetName) { - RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - final Triple result; - if (leaderboard instanceof HasRegattaLike && raceLog != null) { - ReadonlyRaceState state = ReadonlyRaceStateImpl.create(/* race log resolver */ this, raceLog); - result = new com.sap.sse.common.Util.Triple(state.getStartTime(), - raceLog.getCurrentPassId(), state.getRacingProcedure().getType()); - } else { - result = null; - } - return result; - } - - private Iterable getWindTrackerFactories() { - final Set result; - if (bundleContext == null) { - result = Collections.singleton((WindTrackerFactory) ExpeditionWindTrackerFactory.getInstance()); - } else { - ServiceTracker tracker = new ServiceTracker( - bundleContext, WindTrackerFactory.class.getName(), null); - tracker.open(); - result = new HashSet<>(); - for (WindTrackerFactory factory : tracker.getServices(new WindTrackerFactory[0])) { - result.add(factory); - } - } - return result; - } - - @Override - public GPSFixStore getGPSFixStore() { - return gpsFixStore; - } - - @Override - public RaceTracker getRaceTrackerById(Object id) { - return raceTrackersByID.get(id); - } - - @Override - public AbstractLogEventAuthor getServerAuthor() { - return raceLogEventAuthorForServer; - } - - @Override - public CompetitorStore getCompetitorStore() { - return competitorStore; - } - - @Override - public TypeBasedServiceFinderFactory getTypeBasedServiceFinderFactory() { - return serviceFinderFactory; - } - - @Override - public DataImportLockWithProgress getDataImportLock() { - return dataImportLock; - } - - @Override - public DataImportProgress createOrUpdateDataImportProgressWithReplication(UUID importOperationId, - double overallProgressPct, String subProgressName, double subProgressPct) { - // Create/Update locally - DataImportProgress progress = createOrUpdateDataImportProgressWithoutReplication(importOperationId, - overallProgressPct, subProgressName, subProgressPct); - // Create/Update on replicas - replicate(new CreateOrUpdateDataImportProgress(importOperationId, overallProgressPct, subProgressName, - subProgressPct)); - return progress; - } - - @Override - public DataImportProgress createOrUpdateDataImportProgressWithoutReplication(UUID importOperationId, - double overallProgressPct, String subProgressName, double subProgressPct) { - DataImportProgress progress = dataImportLock.getProgress(importOperationId); - boolean newObject = false; - if (progress == null) { - progress = new DataImportProgressImpl(importOperationId); - newObject = true; - } - progress.setOverAllProgressPct(overallProgressPct); - progress.setNameOfCurrentSubProgress(subProgressName); - progress.setCurrentSubProgressPct(subProgressPct); - if (newObject) { - dataImportLock.addProgress(importOperationId, progress); - } - return progress; - } - - @Override - public void setDataImportFailedWithoutReplication(UUID importOperationId, String errorMessage) { - DataImportProgress progress = dataImportLock.getProgress(importOperationId); - if (progress != null) { - progress.setFailed(); - progress.setErrorMessage(errorMessage); - } - } - - @Override - public void setDataImportFailedWithReplication(UUID importOperationId, String errorMessage) { - setDataImportFailedWithoutReplication(importOperationId, errorMessage); - replicate(new DataImportFailed(importOperationId, errorMessage)); - } - - @Override - public void setDataImportDeleteProgressFromMapTimerWithReplication(UUID importOperationId) { - setDataImportDeleteProgressFromMapTimerWithoutReplication(importOperationId); - replicate(new SetDataImportDeleteProgressFromMapTimer(importOperationId)); - } - - @Override - public void setDataImportDeleteProgressFromMapTimerWithoutReplication(UUID importOperationId) { - dataImportLock.setDeleteFromMapTimer(importOperationId); - } - - @Override - public Result search(KeywordQuery query) { - long start = System.currentTimeMillis(); - logger.info("Searching local server for " + query); - Result result = new RegattaByKeywordSearchService().search(this, query); - logger.fine("Search for " + query + " took " + (System.currentTimeMillis() - start) + "ms"); - return result; - } - - @Override - public Result searchRemotely(String remoteServerReferenceName, KeywordQuery query) { - long start = System.currentTimeMillis(); - ResultImpl result = null; - RemoteSailingServerReference remoteRef = remoteSailingServerSet - .getServerReferenceByName(remoteServerReferenceName); - if (remoteRef == null) { - result = null; - } else { - BufferedReader bufferedReader = null; - try { - try { - final URL eventsURL = new URL(remoteRef.getURL(), "sailingserver/api/v1/search?q=" - + URLEncoder.encode(query.toString(), "UTF-8")); - logger.info("Searching remote server " + remoteRef + " for " + query); - URLConnection urlConnection = eventsURL.openConnection(); - urlConnection.connect(); - bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); - JSONParser parser = new JSONParser(); - Object eventsAsObject = parser.parse(bufferedReader); - final LeaderboardGroupBaseJsonDeserializer leaderboardGroupBaseJsonDeserializer = new LeaderboardGroupBaseJsonDeserializer(); - LeaderboardSearchResultBaseJsonDeserializer deserializer = new LeaderboardSearchResultBaseJsonDeserializer( - new EventBaseJsonDeserializer(new VenueJsonDeserializer(new CourseAreaJsonDeserializer( - DomainFactory.INSTANCE)), leaderboardGroupBaseJsonDeserializer), - leaderboardGroupBaseJsonDeserializer); - result = new ResultImpl(query, - new LeaderboardSearchResultBaseRanker()); - JSONArray hitsAsJsonArray = (JSONArray) eventsAsObject; - for (Object hitAsObject : hitsAsJsonArray) { - JSONObject hitAsJson = (JSONObject) hitAsObject; - LeaderboardSearchResultBase hit = deserializer.deserialize(hitAsJson); - result.addHit(hit); - } - } finally { - if (bufferedReader != null) { - bufferedReader.close(); - } - } - } catch (IOException | ParseException e) { - logger.log(Level.INFO, - "Exception trying to fetch events from remote server " + remoteRef + ": " + e.getMessage(), e); - } - } - logger.fine("Remote search on " + remoteRef + " for " + query + " took " + (System.currentTimeMillis() - start) - + "ms"); - return result; - } - - @Override - public ReplicationMasterDescriptor getMasterDescriptor() { - return replicatingFromMaster; - } - - @Override - public void startedReplicatingFrom(ReplicationMasterDescriptor master) { - this.replicatingFromMaster = master; - } - - @Override - public void stoppedReplicatingFrom(ReplicationMasterDescriptor master) { - this.replicatingFromMaster = null; - } - - @Override - public void addOperationSentToMasterForReplication( - OperationWithResultWithIdWrapper operationWithResultWithIdWrapper) { - this.operationsSentToMasterForReplication.add(operationWithResultWithIdWrapper); - } - - @Override - public boolean hasSentOperationToMaster(OperationWithResult operation) { - return this.operationsSentToMasterForReplication.remove(operation); - } - - @Override - public FileStorageManagementService getFileStorageManagementService() { - ServiceReference ref = bundleContext - .getServiceReference(FileStorageManagementService.class); - if (ref == null) { - logger.warning("No file storage management service registered"); - return null; - } - return bundleContext.getService(ref); - } - - public void addMasterDataClassLoader(ClassLoader classLoader) { - masterDataClassLoaders.add(classLoader); - } - - public void removeMasterDataClassLoader(ClassLoader classLoader) { - masterDataClassLoaders.remove(classLoader); - } - - @Override - public ClassLoader getCombinedMasterDataClassLoader() { - JoinedClassLoader joinedClassLoader = new JoinedClassLoader(masterDataClassLoaders); - return joinedClassLoader; - } - - public void setPolarDataService(PolarDataService service) { - if (this.polarDataService == null && service != null) { - polarDataService = service; - polarDataService.registerDomainFactory(baseDomainFactory); - setPolarDataServiceOnAllTrackedRaces(service); - } - } - - private void setPolarDataServiceOnAllTrackedRaces(PolarDataService service) { - Iterable allRegattas = getAllRegattas(); - for (Regatta regatta : allRegattas) { - DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(regatta); - if (trackedRegatta != null) { - trackedRegatta.lockTrackedRacesForRead(); - try { - Iterable trackedRaces = trackedRegatta.getTrackedRaces(); - for (TrackedRace trackedRace : trackedRaces) { - trackedRace.setPolarDataService(service); - service.insertExistingFixes(trackedRace); - } - } finally { - trackedRegatta.unlockTrackedRacesAfterRead(); - } - } - } - } - - public void unsetPolarDataService(PolarDataService service) { - if (polarDataService == service) { - polarDataService.unregisterDomainFactory(baseDomainFactory); - polarDataService = null; - setPolarDataService(null); - } - } - - @Override - public Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint) { - final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); - final List result = new ArrayList<>(); - final Map windwardDistanceSailedPerCompetitor = new HashMap<>(); - for (final Competitor competitor : trackedRace.getRace().getCompetitors()) { - result.add(competitor); - final CompetitorRankingInfo competitorRankingInfo = rankingInfo.getCompetitorRankingInfo().apply(competitor); - windwardDistanceSailedPerCompetitor.put(competitor, competitorRankingInfo == null ? null : competitorRankingInfo.getWindwardDistanceSailed()); - } - final Comparator durationComparatorNullsLast = Comparator.nullsLast(Comparator.naturalOrder()); - result.sort((c1, c2) -> durationComparatorNullsLast.compare(windwardDistanceSailedPerCompetitor.get(c2), - windwardDistanceSailedPerCompetitor.get(c1))); - return result; - } - - /** - * A {@link SimpleRaceLogIdentifier} in particular has a {@link SimpleRaceLogIdentifier#getRegattaLikeParentName()} - * which identifies either a regatta by name or a flexible leaderboard by name. Here is why this can luckily be - * resolved unanimously: A regatta leaderboard always uses as its name the regatta name (see - * {@link RegattaImpl#getName()}). Trying to {@link RegattaLeaderboardImpl#setName(String) set} the regatta leaderboard's - * name can only update its {@link Leaderboard#getDisplayName() display name}. Therefore, regatta leaderboards are always - * keyed in {@link #leaderboardsByName} by their regatta's name. Thus, no flexible leaderboard can have a regatta's name - * as its name, and therefore leaderboard names and regatta names are unitedly unique. - */ - @Override - public RaceLog resolve(SimpleRaceLogIdentifier identifier) { - final RaceLog result; - final IsRegattaLike regattaLike; - final Regatta regatta = regattasByName.get(identifier.getRegattaLikeParentName()); - if (regatta != null) { - regattaLike = regatta; - } else { - final Leaderboard leaderboard = leaderboardsByName.get(identifier.getRegattaLikeParentName()); - if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { - regattaLike = (FlexibleLeaderboard) leaderboard; - } else { - regattaLike = null; - } - } - if (regattaLike != null) { - final RaceColumn raceColumn = regattaLike.getRaceColumnByName(identifier.getRaceColumnName()); - if (raceColumn != null) { - final Fleet fleet = raceColumn.getFleetByName(identifier.getFleetName()); - if (fleet != null) { - result = raceColumn.getRaceLog(fleet); - } else { - result = null; - } - } else { - result = null; - } - } else { - result = null; - } - return result; - } -} +package com.sap.sailing.server.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.SocketException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; +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.abstractlog.race.SimpleRaceLogIdentifier; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.RaceLogResolver; +import com.sap.sailing.domain.abstractlog.race.state.RaceState; +import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; +import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; +import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.CompetitorStore.CompetitorUpdateListener; +import com.sap.sailing.domain.base.ControlPoint; +import com.sap.sailing.domain.base.CourseArea; +import com.sap.sailing.domain.base.DomainFactory; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.EventBase; +import com.sap.sailing.domain.base.EventFetcher; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.LeaderboardSearchResult; +import com.sap.sailing.domain.base.LeaderboardSearchResultBase; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnInSeries; +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.base.RemoteSailingServerReference; +import com.sap.sailing.domain.base.SailingServerConfiguration; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.Sideline; +import com.sap.sailing.domain.base.Waypoint; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationIdentifier; +import com.sap.sailing.domain.base.configuration.DeviceConfigurationMatcher; +import com.sap.sailing.domain.base.configuration.RegattaConfiguration; +import com.sap.sailing.domain.base.configuration.impl.DeviceConfigurationMapImpl; +import com.sap.sailing.domain.base.impl.DynamicCompetitor; +import com.sap.sailing.domain.base.impl.EventImpl; +import com.sap.sailing.domain.base.impl.RegattaImpl; +import com.sap.sailing.domain.base.impl.RemoteSailingServerReferenceImpl; +import com.sap.sailing.domain.common.DataImportProgress; +import com.sap.sailing.domain.common.Distance; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.Renamable; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.TrackedRaceStatusEnum; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; +import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; +import com.sap.sailing.domain.common.impl.DataImportProgressImpl; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.racelog.RacingProcedureType; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.GPSFixMoving; +import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; +import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.LeaderboardRegistry; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; +import com.sap.sailing.domain.persistence.DomainObjectFactory; +import com.sap.sailing.domain.persistence.MongoObjectFactory; +import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory; +import com.sap.sailing.domain.persistence.MongoRegattaLogStoreFactory; +import com.sap.sailing.domain.persistence.MongoWindStore; +import com.sap.sailing.domain.persistence.MongoWindStoreFactory; +import com.sap.sailing.domain.persistence.PersistenceFactory; +import com.sap.sailing.domain.persistence.media.MediaDB; +import com.sap.sailing.domain.persistence.media.MediaDBFactory; +import com.sap.sailing.domain.persistence.racelog.tracking.MongoGPSFixStoreFactory; +import com.sap.sailing.domain.polars.PolarDataService; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; +import com.sap.sailing.domain.racelog.RaceLogStore; +import com.sap.sailing.domain.racelog.tracking.GPSFixStore; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo; +import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; +import com.sap.sailing.domain.ranking.RankingMetricConstructor; +import com.sap.sailing.domain.regattalike.HasRegattaLike; +import com.sap.sailing.domain.regattalike.IsRegattaLike; +import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; +import com.sap.sailing.domain.regattalog.RegattaLogStore; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; +import com.sap.sailing.domain.tracking.GPSFixTrack; +import com.sap.sailing.domain.tracking.MarkPassing; +import com.sap.sailing.domain.tracking.RaceChangeListener; +import com.sap.sailing.domain.tracking.RaceHandle; +import com.sap.sailing.domain.tracking.RaceListener; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.domain.tracking.RaceTrackingConnectivityParameters; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.TrackedRaceStatus; +import com.sap.sailing.domain.tracking.TrackedRegatta; +import com.sap.sailing.domain.tracking.WindStore; +import com.sap.sailing.domain.tracking.WindTracker; +import com.sap.sailing.domain.tracking.WindTrackerFactory; +import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; +import com.sap.sailing.domain.tracking.impl.DynamicGPSFixTrackImpl; +import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; +import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; +import com.sap.sailing.expeditionconnector.ExpeditionWindTrackerFactory; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.Replicator; +import com.sap.sailing.server.gateway.deserialization.impl.CourseAreaJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardSearchResultBaseJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer; +import com.sap.sailing.server.masterdata.DataImportLockWithProgress; +import com.sap.sailing.server.operationaltransformation.AddCourseAreas; +import com.sap.sailing.server.operationaltransformation.AddDefaultRegatta; +import com.sap.sailing.server.operationaltransformation.AddMediaTrackOperation; +import com.sap.sailing.server.operationaltransformation.AddRaceDefinition; +import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; +import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.CreateEvent; +import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDataImportProgress; +import com.sap.sailing.server.operationaltransformation.CreateOrUpdateDeviceConfiguration; +import com.sap.sailing.server.operationaltransformation.CreateTrackedRace; +import com.sap.sailing.server.operationaltransformation.DataImportFailed; +import com.sap.sailing.server.operationaltransformation.RecordCompetitorGPSFix; +import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFix; +import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForExistingTrack; +import com.sap.sailing.server.operationaltransformation.RecordMarkGPSFixForNewMarkTrack; +import com.sap.sailing.server.operationaltransformation.RecordWindFix; +import com.sap.sailing.server.operationaltransformation.RemoveDeviceConfiguration; +import com.sap.sailing.server.operationaltransformation.RemoveEvent; +import com.sap.sailing.server.operationaltransformation.RemoveMediaTrackOperation; +import com.sap.sailing.server.operationaltransformation.RemoveWindFix; +import com.sap.sailing.server.operationaltransformation.RenameEvent; +import com.sap.sailing.server.operationaltransformation.SetDataImportDeleteProgressFromMapTimer; +import com.sap.sailing.server.operationaltransformation.TrackRegatta; +import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; +import com.sap.sailing.server.operationaltransformation.UpdateEndOfTracking; +import com.sap.sailing.server.operationaltransformation.UpdateMarkPassings; +import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackDurationOperation; +import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackRacesOperation; +import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackStartTimeOperation; +import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackTitleOperation; +import com.sap.sailing.server.operationaltransformation.UpdateMediaTrackUrlOperation; +import com.sap.sailing.server.operationaltransformation.UpdateRaceDelayToLive; +import com.sap.sailing.server.operationaltransformation.UpdateStartOfTracking; +import com.sap.sailing.server.operationaltransformation.UpdateStartTimeReceived; +import com.sap.sailing.server.operationaltransformation.UpdateTrackedRaceStatus; +import com.sap.sailing.server.operationaltransformation.UpdateWindAveragingTime; +import com.sap.sailing.server.operationaltransformation.UpdateWindSourcesToExclude; +import com.sap.sailing.server.simulation.SimulationService; +import com.sap.sailing.server.simulation.SimulationServiceFactory; +import com.sap.sse.ServerInfo; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.TypeBasedServiceFinderFactory; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.search.KeywordQuery; +import com.sap.sse.common.search.Result; +import com.sap.sse.common.search.ResultImpl; +import com.sap.sse.concurrent.LockUtil; +import com.sap.sse.concurrent.NamedReentrantReadWriteLock; +import com.sap.sse.filestorage.FileStorageManagementService; +import com.sap.sse.replication.OperationExecutionListener; +import com.sap.sse.replication.OperationWithResult; +import com.sap.sse.replication.ReplicationMasterDescriptor; +import com.sap.sse.replication.impl.OperationWithResultWithIdWrapper; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.util.ClearStateTestSupport; +import com.sap.sse.util.JoinedClassLoader; +import com.sap.sse.util.impl.ThreadFactoryWithPriority; + +public class RacingEventServiceImpl implements RacingEventService, ClearStateTestSupport, RegattaListener, + LeaderboardRegistry, Replicator, EventFetcher { + private static final Logger logger = Logger.getLogger(RacingEventServiceImpl.class.getName()); + + /** + * A scheduler for the periodic checks of the paramURL documents for the advent of {@link ControlPoint}s with static + * position information otherwise not available through MarkPassingReceiver's events. + */ + private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactoryWithPriority(Thread.NORM_PRIORITY, /* daemon */ true)); + + private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory; + + /** + * Holds the {@link Event} objects for those event registered with this service. Note that there may be + * {@link Event} objects that exist outside this service for events not (yet) registered here. + */ + private final ConcurrentHashMap eventsById; + + private final RemoteSailingServerSet remoteSailingServerSet; + + /** + * Holds the {@link Regatta} objects for those races registered with this service. Note that there may be + * {@link Regatta} objects that exist outside this service for regattas not (yet) registered here. + */ + protected final ConcurrentHashMap regattasByName; + + private final NamedReentrantReadWriteLock regattasByNameLock; + + private final ConcurrentHashMap courseListeners; + + protected final ConcurrentHashMap> raceTrackersByRegatta; + + /** + * Although {@link #raceTrackersByRegatta} is a concurrent hash map, entering sets as values needs to be + * synchronized using this lock's write lock to avoid two value sets overwriting each other. + */ + private final NamedReentrantReadWriteLock raceTrackersByRegattaLock; + + /** + * Remembers the trackers by paramURL/liveURI/storedURI to avoid duplication + */ + protected final ConcurrentHashMap raceTrackersByID; + + /** + * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} will check + * {@link #raceTrackersByID} for the presence of a tracker and won't create a new tracker if one for the + * connectivity parameters' ID already exists. This check and creation and addition to {@link #raceTrackersByID} + * requires locking in the face of concurrent calls to + * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)}. Using synchronized is + * not ideal due to its coarse-grained locking style which allows for little concurrency. Instead, this map is used + * to keep locks for any ID that any invocation of the + * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} method is currently working on. + * Fetching or creating and putting a lock to this map happens in ({@link #getOrCreateRaceTrackersByIdLock}) which + * takes care of managing concurrent access to this concurrent map. When done, the + * {@link #addRace(RegattaIdentifier, RaceTrackingConnectivityParameters, long)} method cleans up by removing the + * lock again from this map, again using a synchronized method ( + * {@link #unlockRaceTrackersById(Object, NamedReentrantReadWriteLock)}). + */ + private final ConcurrentHashMap raceTrackersByIDLocks; + + /** + * Leaderboards managed by this racing event service + */ + private final ConcurrentHashMap leaderboardsByName; + + /** + * {@link #leaderboardsByName} is already a concurrent hash map; however, when renaming a leaderboard, this shall + * happen as an atomic transaction, not interruptible by other write accesses on the same map because otherwise + * assumptions made during the rename process wouldn't hold. See, in particular, + * {@link #renameLeaderboard(String, String)}. + */ + private final NamedReentrantReadWriteLock leaderboardsByNameLock; + + private final ConcurrentHashMap leaderboardGroupsByName; + + private final ConcurrentHashMap leaderboardGroupsByID; + + /** + * See {@link #leaderboardsByNameLock} + */ + private final NamedReentrantReadWriteLock leaderboardGroupsByNameLock; + + private final CompetitorStore competitorStore; + + /** + * A set based on a concurrent hash map, therefore being thread safe + */ + private Set regattasObservedForDefaultLeaderboard = Collections + .newSetFromMap(new ConcurrentHashMap()); + + private final MongoObjectFactory mongoObjectFactory; + + private final DomainObjectFactory domainObjectFactory; + + private final ConcurrentHashMap regattaTrackingCache; + + /** + * Protects write access transactions that do a previous read to {@link #regattaTrackingCache}; read-only access is + * already synchronized by using a concurrent hash map for {@link #regattaTrackingCache}. + */ + private final NamedReentrantReadWriteLock regattaTrackingCacheLock; + + private final ConcurrentHashMap, OperationExecutionListener> operationExecutionListeners; + + /** + * Keys are the toString() representation of the {@link RaceDefinition#getId() IDs} of races passed to + * {@link #setRegattaForRace(Regatta, RaceDefinition)}. + */ + private final ConcurrentHashMap persistentRegattasForRaceIDs; + + private final RaceLogReplicator raceLogReplicator; + private final RegattaLogReplicator regattaLogReplicator; + + private final RaceLogScoringReplicator raceLogScoringReplicator; + + private final MediaDB mediaDB; + + private final MediaLibrary mediaLibrary; + + /** + * Currently valid pairs of {@link DeviceConfigurationMatcher}s and {@link DeviceConfiguration}s. The contents of + * this map is persisted and replicated. See {@link DeviceConfigurationMapImpl}. + */ + protected final DeviceConfigurationMapImpl configurationMap; + + private final WindStore windStore; + private final GPSFixStore gpsFixStore; + + /** + * This author should be used for server generated race log events + */ + private final AbstractLogEventAuthor raceLogEventAuthorForServer = new LogEventAuthorImpl( + RacingEventService.class.getName(), 0); + + private PolarDataService polarDataService; + + private final SimulationService simulationService; + + /** + * Allow only one master data import at a time to avoid situation where multiple Imports override each other in + * unpredictable fashion + */ + private final DataImportLockWithProgress dataImportLock; + + /** + * If this service runs in the context of an OSGi environment, the activator should {@link #setBundleContext set the + * bundle context} on this object so that service lookups become possible. + */ + private BundleContext bundleContext; + + private TypeBasedServiceFinderFactory serviceFinderFactory; + + /** + * The master from which this replicable is currently replicating, or null if this replicable is not + * currently replicated from any master. + */ + private ReplicationMasterDescriptor replicatingFromMaster; + + private Set> operationsSentToMasterForReplication; + + private ThreadLocal currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster = ThreadLocal + .withInitial(() -> false); + + private final Set masterDataClassLoaders = new HashSet(); + + private final JoinedClassLoader joinedClassLoader; + + private SailingServerConfiguration sailingServerConfiguration; + + /** + * Providing the constructor parameters for a new {@link RacingEventServiceImpl} instance is a bit tricky + * in some cases because containment and initialization order of some types is fairly tightly coupled. + * There is a dependency of many such objects on an instance of {@link RaceLogResolver} which is implemented + * by {@link RacingEventServiceImpl}. However, therefore, this instance only becomes available in the + * innermost constructor. + * + * @author Axel Uhl (d043530) + * + */ + public static interface ConstructorParameters { + DomainObjectFactory getDomainObjectFactory(); + MongoObjectFactory getMongoObjectFactory(); + com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory(); + CompetitorStore getCompetitorStore(); + } + + /** + * Constructs a {@link DomainFactory base domain factory} that uses this object's {@link #competitorStore competitor + * store} for competitor management. This base domain factory is then also used for the construction of the + * {@link DomainObjectFactory}. This constructor variant initially clears the persistent competitor collection, + * hence removes all previously persistent competitors. This is the default for testing and for backward + * compatibility with prior releases that did not support a persistent competitor collection. + */ + public RacingEventServiceImpl() { + this(true, null); + } + + public RacingEventServiceImpl(WindStore windStore, GPSFixStore gpsFixStore, + TypeBasedServiceFinderFactory serviceFinderFactory) { + this(true, windStore, gpsFixStore, serviceFinderFactory); + } + + void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + /** + * Like {@link #RacingEventServiceImpl()}, but allows callers to specify that the persistent competitor collection + * be cleared before the service starts. + * + * @param clearPersistentCompetitorStore + * if true, the {@link PersistentCompetitorStore} is created empty, with the corresponding + * database collection cleared as well. Use with caution! When used with false, competitors + * created and stored during previous service executions will initially be loaded. + */ + public RacingEventServiceImpl(boolean clearPersistentCompetitorStore, final TypeBasedServiceFinderFactory serviceFinderFactory) { + this((final RaceLogResolver raceLogResolver)-> { + return new ConstructorParameters() { + private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); + private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( + PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory), + clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); + + @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } + @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } + @Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); } + @Override public CompetitorStore getCompetitorStore() { return competitorStore; } + }; + }, MediaDBFactory.INSTANCE.getDefaultMediaDB(), null, null, serviceFinderFactory); + } + + private RacingEventServiceImpl(final boolean clearPersistentCompetitorStore, WindStore windStore, + GPSFixStore gpsFixStore, final TypeBasedServiceFinderFactory serviceFinderFactory) { + this((final RaceLogResolver raceLogResolver)-> { + return new ConstructorParameters() { + private final MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory(serviceFinderFactory); + private final PersistentCompetitorStore competitorStore = new PersistentCompetitorStore( + mongoObjectFactory, + clearPersistentCompetitorStore, serviceFinderFactory, raceLogResolver); + + @Override public DomainObjectFactory getDomainObjectFactory() { return competitorStore.getDomainObjectFactory(); } + @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } + @Override public DomainFactory getBaseDomainFactory() { return competitorStore.getBaseDomainFactory(); } + @Override public CompetitorStore getCompetitorStore() { return competitorStore; } + }; + }, MediaDBFactory.INSTANCE.getDefaultMediaDB(), windStore, gpsFixStore, serviceFinderFactory); + } + + /** + * Uses the default factories for the tracking adapters and the {@link DomainFactory base domain factory} of the + * {@link PersistenceFactory#getDefaultDomainObjectFactory() default domain object factory}. This constructor should + * be used for testing because it provides a transient {@link CompetitorStore} as required for competitor + * persistence. + */ + public RacingEventServiceImpl(Function domainObjectFactoryProvider, + final MongoObjectFactory mongoObjectFactory, MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) { + this((final RaceLogResolver raceLogResolver)-> { + return new ConstructorParameters() { + private final DomainObjectFactory domainObjectFactory = domainObjectFactoryProvider.apply(raceLogResolver); + + @Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; } + @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } + @Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); } + @Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); } + }; + }, mediaDB, windStore, gpsFixStore, null); + } + + public RacingEventServiceImpl(final DomainObjectFactory domainObjectFactory, MongoObjectFactory mongoObjectFactory, + MediaDB mediaDB, WindStore windStore, GPSFixStore gpsFixStore) { + this((final RaceLogResolver raceLogResolver)-> { + return new ConstructorParameters() { + @Override public DomainObjectFactory getDomainObjectFactory() { return domainObjectFactory; } + @Override public MongoObjectFactory getMongoObjectFactory() { return mongoObjectFactory; } + @Override public DomainFactory getBaseDomainFactory() { return domainObjectFactory.getBaseDomainFactory(); } + @Override public CompetitorStore getCompetitorStore() { return getBaseDomainFactory().getCompetitorStore(); } + }; + }, mediaDB, windStore, gpsFixStore, null); + } + + /** + * @param windStore + * if null, a default {@link MongoWindStore} will be used, based on the persistence set-up + * of this service + * @param serviceFinderFactory + * used to find the services handling specific types of tracking devices, such as the persistent storage + * of {@link DeviceIdentifier}s of specific device types or the managing of the device-to-competitor + * associations per race tracked. + */ + public RacingEventServiceImpl(Function constructorParametersProvider, MediaDB mediaDb, + WindStore windStore, GPSFixStore gpsFixStore, TypeBasedServiceFinderFactory serviceFinderFactory) { + logger.info("Created " + this); + final ConstructorParameters constructorParameters = constructorParametersProvider.apply(this); + this.domainObjectFactory = constructorParameters.getDomainObjectFactory(); + this.masterDataClassLoaders.add(this.getClass().getClassLoader()); + joinedClassLoader = new JoinedClassLoader(masterDataClassLoaders); + this.operationsSentToMasterForReplication = new HashSet<>(); + this.baseDomainFactory = constructorParameters.getBaseDomainFactory(); + this.mongoObjectFactory = constructorParameters.getMongoObjectFactory(); + this.mediaDB = mediaDb; + this.competitorStore = constructorParameters.getCompetitorStore(); + if (windStore == null) { + try { + windStore = MongoWindStoreFactory.INSTANCE.getMongoWindStore(mongoObjectFactory, domainObjectFactory); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + this.competitorStore.addCompetitorUpdateListener(new CompetitorUpdateListener() { + @Override + public void competitorUpdated(Competitor competitor) { + replicate(new UpdateCompetitor(competitor.getId().toString(), competitor.getName(), competitor + .getColor(), competitor.getEmail(), competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), + competitor.getTeam().getImage(), competitor.getFlagImage(), + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile())); + } + }); + this.windStore = windStore; + this.dataImportLock = new DataImportLockWithProgress(); + + remoteSailingServerSet = new RemoteSailingServerSet(scheduler); + regattasByName = new ConcurrentHashMap(); + regattasByNameLock = new NamedReentrantReadWriteLock("regattasByName for " + this, /* fair */false); + eventsById = new ConcurrentHashMap(); + regattaTrackingCache = new ConcurrentHashMap<>(); + regattaTrackingCacheLock = new NamedReentrantReadWriteLock("regattaTrackingCache for " + this, /* fair */false); + raceTrackersByRegatta = new ConcurrentHashMap<>(); + raceTrackersByRegattaLock = new NamedReentrantReadWriteLock("raceTrackersByRegatta for " + this, /* fair */ + false); + raceTrackersByID = new ConcurrentHashMap<>(); + raceTrackersByIDLocks = new ConcurrentHashMap<>(); + leaderboardGroupsByName = new ConcurrentHashMap<>(); + leaderboardGroupsByID = new ConcurrentHashMap<>(); + leaderboardGroupsByNameLock = new NamedReentrantReadWriteLock("leaderboardGroupsByName for " + this, /* fair */ + false); + leaderboardsByName = new ConcurrentHashMap(); + leaderboardsByNameLock = new NamedReentrantReadWriteLock("leaderboardsByName for " + this, /* fair */false); + operationExecutionListeners = new ConcurrentHashMap<>(); + courseListeners = new ConcurrentHashMap<>(); + persistentRegattasForRaceIDs = new ConcurrentHashMap<>(); + final int SIMULATION_THREAD_POOL_SIZE = Math.max(Runtime.getRuntime().availableProcessors()/3, 1); + Executor simulatorExecutor = new ThreadPoolExecutor(/* corePoolSize */SIMULATION_THREAD_POOL_SIZE, + /* maximumPoolSize */SIMULATION_THREAD_POOL_SIZE, + /* keepAliveTime */60, TimeUnit.SECONDS, + /* workQueue */new LinkedBlockingQueue()); + // TODO: initialize smart-future-cache for simulation-results and add to simulation-service + simulationService = SimulationServiceFactory.INSTANCE.getService(simulatorExecutor, this); + this.raceLogReplicator = new RaceLogReplicator(this); + this.regattaLogReplicator = new RegattaLogReplicator(this); + this.raceLogScoringReplicator = new RaceLogScoringReplicator(this); + this.mediaLibrary = new MediaLibrary(); + if (gpsFixStore == null) { + try { + gpsFixStore = MongoGPSFixStoreFactory.INSTANCE.getMongoGPSFixStore(mongoObjectFactory, + domainObjectFactory, serviceFinderFactory); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + this.gpsFixStore = gpsFixStore; + this.configurationMap = new DeviceConfigurationMapImpl(); + this.serviceFinderFactory = serviceFinderFactory; + + sailingServerConfiguration = domainObjectFactory.loadServerConfiguration(); + final Iterable> loadedEventsWithRequireStoreFlag = loadStoredEvents(); + loadStoredRegattas(); + loadRaceIDToRegattaAssociations(); + loadStoredLeaderboardsAndGroups(); + loadLinksFromEventsToLeaderboardGroups(); + loadMediaLibary(); + loadStoredDeviceConfigurations(); + loadAllRemoteSailingServersAndSchedulePeriodicEventCacheRefresh(); + + // Stores all events which run through a data migration + // Remark: must be called after loadLinksFromEventsToLeaderboardGroups(), otherwise would loose the Event -> LeaderboardGroup relation + for (Pair eventAndRequireStoreFlag : loadedEventsWithRequireStoreFlag) { + if (eventAndRequireStoreFlag.getB()) { + mongoObjectFactory.storeEvent(eventAndRequireStoreFlag.getA()); + } + } + } + + @Override + public boolean isCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster() { + return currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster.get(); + } + + @Override + public void setCurrentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster( + boolean currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster) { + this.currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster + .set(currentlyFillingFromInitialLoadOrApplyingOperationReceivedFromMaster); + } + + @Override + public PolarDataService getPolarDataService() { + return polarDataService; + } + + @Override + public SimulationService getSimulationService() { + return simulationService; + } + + @Override + public void clearState() throws Exception { + for (String leaderboardGroupName : new ArrayList<>(this.leaderboardGroupsByName.keySet())) { + removeLeaderboardGroup(leaderboardGroupName); + } + for (String leaderboardName : new ArrayList<>(this.leaderboardsByName.keySet())) { + removeLeaderboard(leaderboardName); + } + for (Regatta regatta : new ArrayList<>(this.regattasByName.values())) { + stopTracking(regatta); + removeRegatta(regatta); + } + for (Event event : new ArrayList<>(this.eventsById.values())) { + removeEvent(event.getId()); + } + for (MediaTrack mediaTrack : this.mediaLibrary.allTracks()) { + mediaTrackDeleted(mediaTrack); + } + // TODO clear user store? See bug 2430. + this.competitorStore.clear(); + } + + @Override + public com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() { + return baseDomainFactory; + } + + @Override + public MongoObjectFactory getMongoObjectFactory() { + return mongoObjectFactory; + } + + @Override + public DomainObjectFactory getDomainObjectFactory() { + return domainObjectFactory; + } + + private void loadRaceIDToRegattaAssociations() { + persistentRegattasForRaceIDs.putAll(domainObjectFactory.loadRaceIDToRegattaAssociations(this)); + } + + private void loadStoredRegattas() { + LockUtil.lockForWrite(regattasByNameLock); + try { + for (Regatta regatta : domainObjectFactory.loadAllRegattas(this)) { + logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() + + ") into regattasByName"); + regattasByName.put(regatta.getName(), regatta); + regatta.addRegattaListener(this); + onRegattaLikeAdded(regatta); + regatta.addRaceColumnListener(raceLogReplicator); + regatta.addRaceColumnListener(raceLogScoringReplicator); + } + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + } + + private Iterable> loadStoredEvents() { + Iterable> loadedEventsWithRequireStoreFlag = domainObjectFactory.loadAllEvents(); + for (Pair eventAndFlag : loadedEventsWithRequireStoreFlag) { + Event event = eventAndFlag.getA(); + if (event.getId() != null) + eventsById.put(event.getId(), event); + } + return loadedEventsWithRequireStoreFlag; + } + + private void loadLinksFromEventsToLeaderboardGroups() { + domainObjectFactory.loadLeaderboardGroupLinksForEvents(/* eventResolver */this, /* leaderboardGroupResolver */ + this); + } + + private void loadAllRemoteSailingServersAndSchedulePeriodicEventCacheRefresh() { + for (RemoteSailingServerReference sailingServer : domainObjectFactory.loadAllRemoteSailingServerReferences()) { + remoteSailingServerSet.add(sailingServer); + } + } + + /** + * Collects media track references from the configured sources (mongo DB by default, ftp folder yet to be + * implemented). The method is expected to be called initially blocking the API until finished. + * + * Subsequent calls (assumed to be triggered from the admin console or in scheduled intervals) don't need to block. + * In that case, the API will simply serve the current state. + * + */ + private void loadMediaLibary() { + Collection allDbMediaTracks = mediaDB.loadAllMediaTracks(); + mediaTracksAdded(allDbMediaTracks); + } + + private void loadStoredDeviceConfigurations() { + for (Entry entry : domainObjectFactory + .loadAllDeviceConfigurations()) { + configurationMap.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void addLeaderboard(Leaderboard leaderboard) { + LockUtil.lockForWrite(leaderboardsByNameLock); + try { + leaderboardsByName.put(leaderboard.getName(), leaderboard); + } finally { + LockUtil.unlockAfterWrite(leaderboardsByNameLock); + } + // RaceColumns of RegattaLeaderboards are tracked via its Regatta! + if (leaderboard instanceof FlexibleLeaderboard) { + onRegattaLikeAdded(((FlexibleLeaderboard) leaderboard).getRegattaLike()); + leaderboard.addRaceColumnListener(raceLogReplicator); + leaderboard.addRaceColumnListener(raceLogScoringReplicator); + } + } + + private void loadStoredLeaderboardsAndGroups() { + logger.info("loading stored leaderboards and groups"); + // Loading all leaderboard groups and the contained leaderboards + for (LeaderboardGroup leaderboardGroup : domainObjectFactory.getAllLeaderboardGroups(this, this)) { + logger.info("loaded leaderboard group " + leaderboardGroup.getName() + " into " + this); + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + leaderboardGroupsByName.put(leaderboardGroup.getName(), leaderboardGroup); + leaderboardGroupsByID.put(leaderboardGroup.getId(), leaderboardGroup); + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + } + // Loading the remaining leaderboards + domainObjectFactory.getLeaderboardsNotInGroup(this, this); + logger.info("done with loading stored leaderboards and groups"); + } + + @Override + public FlexibleLeaderboard addFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, + int[] discardThresholds, ScoringScheme scoringScheme, Serializable courseAreaId) { + logger.info("adding flexible leaderboard " + leaderboardName); + CourseArea courseArea = getCourseArea(courseAreaId); + FlexibleLeaderboard result = new FlexibleLeaderboardImpl(getRaceLogStore(), getRegattaLogStore(), + leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardThresholds), scoringScheme, + courseArea); + result.setDisplayName(leaderboardDisplayName); + if (getLeaderboardByName(leaderboardName) != null) { + throw new IllegalArgumentException("Leaderboard with name " + leaderboardName + " already exists"); + } + addLeaderboard(result); + mongoObjectFactory.storeLeaderboard(result); + return result; + } + + @Override + public CourseArea getCourseArea(Serializable courseAreaId) { + for (Event event : getAllEvents()) { + for (CourseArea courseArea : event.getVenue().getCourseAreas()) { + if (courseArea.getId().equals(courseAreaId)) { + return courseArea; + } + } + } + return null; + } + + @Override + public RegattaLeaderboard addRegattaLeaderboard(RegattaIdentifier regattaIdentifier, String leaderboardDisplayName, + int[] discardThresholds) { + Regatta regatta = getRegatta(regattaIdentifier); + logger.info("adding regatta leaderboard for regatta " + + (regatta == null ? "null" : (regatta.getName() + " (" + regatta.hashCode() + ")")) + " to " + this); + RegattaLeaderboard result = null; + if (regatta != null) { + result = new RegattaLeaderboardImpl(regatta, new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); + result.setDisplayName(leaderboardDisplayName); + if (getLeaderboardByName(result.getName()) != null) { + throw new IllegalArgumentException("Leaderboard with name " + result.getName() + " already exists in " + + this); + } + addLeaderboard(result); + mongoObjectFactory.storeLeaderboard(result); + } else { + logger.warning("Cannot find regatta " + regattaIdentifier + + ". Hence, cannot create regatta leaderboard for it."); + } + return result; + } + + @Override + public RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + if (leaderboard instanceof FlexibleLeaderboard) { + // uses the default fleet as the single fleet for the new column + RaceColumn result = ((FlexibleLeaderboard) leaderboard).addRaceColumn(columnName, medalRace); + updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); + return result; + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + + " is not a FlexibleLeaderboard"); + } + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } + } + + @Override + public void moveLeaderboardColumnUp(String leaderboardName, String columnName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { + ((FlexibleLeaderboard) leaderboard).moveRaceColumnUp(columnName); + updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } + } + + @Override + public void moveLeaderboardColumnDown(String leaderboardName, String columnName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { + ((FlexibleLeaderboard) leaderboard).moveRaceColumnDown(columnName); + updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } + } + + @Override + public void removeLeaderboardColumn(String leaderboardName, String columnName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard == null) { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } else if (!(leaderboard instanceof FlexibleLeaderboard)) { + throw new IllegalArgumentException("Columns cannot be removed from Leaderboard named " + leaderboardName); + } else { + ((FlexibleLeaderboard) leaderboard).removeRaceColumn(columnName); + updateStoredLeaderboard((FlexibleLeaderboard) leaderboard); + } + } + + @Override + public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(oldColumnName); + if (raceColumn instanceof FlexibleRaceColumn) { + // remove race log under old identifier; the race log identifier changes + for (Fleet fleet : raceColumn.getFleets()) { + getMongoObjectFactory().removeRaceLog(raceColumn.getRaceLogIdentifier(fleet)); + } + ((FlexibleRaceColumn) raceColumn).setName(newColumnName); + // store the race logs again under the new identifiers + storeRaceLogs(raceColumn); + updateStoredLeaderboard(leaderboard); + } else { + throw new IllegalArgumentException("Race column " + oldColumnName + " cannot be renamed"); + } + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } + } + + /** + * When a race column is renamed, its race log identifiers change. Therefore, the race logs need to be stored under + * the new identifier again to be consistent with the in-memory image again. + */ + private void storeRaceLogs(RaceColumn raceColumn) { + for (Fleet fleet : raceColumn.getFleets()) { + RaceLogIdentifier identifier = raceColumn.getRaceLogIdentifier(fleet); + RaceLogEventVisitor storeVisitor = MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStoreVisitor( + identifier, getMongoObjectFactory()); + RaceLog raceLog = raceColumn.getRaceLog(fleet); + raceLog.lockForRead(); + try { + for (RaceLogEvent e : raceLog.getRawFixes()) { + e.accept(storeVisitor); + } + } finally { + raceLog.unlockAfterRead(); + } + } + } + + @Override + public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double factor) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(columnName); + if (raceColumn != null) { + raceColumn.setFactor(factor); + updateStoredLeaderboard(leaderboard); + } else { + throw new IllegalArgumentException("Race column " + columnName + " not found in leaderboard " + + leaderboardName); + } + } else { + throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found"); + } + } + + @Override + public void renameLeaderboard(String oldName, String newName) { + final Leaderboard toRename = leaderboardsByName.get(oldName); + LockUtil.lockForWrite(leaderboardsByNameLock); + try { + if (toRename == null) { + throw new IllegalArgumentException("No leaderboard with name " + oldName + " found"); + } + if (leaderboardsByName.containsKey(newName)) { + throw new IllegalArgumentException("Leaderboard with name " + newName + " already exists"); + } + if (toRename instanceof Renamable) { + ((Renamable) toRename).setName(newName); + leaderboardsByName.remove(oldName); + leaderboardsByName.put(newName, toRename); + } else { + throw new IllegalArgumentException("Leaderboard with name " + newName + " is of type " + + toRename.getClass().getSimpleName() + " and therefore cannot be renamed"); + } + } finally { + LockUtil.unlockAfterWrite(leaderboardsByNameLock); + } + // don't need the lock anymore to update DB + if (toRename instanceof Renamable) { + mongoObjectFactory.renameLeaderboard(oldName, newName); + syncGroupsAfterLeaderboardChange(toRename, true); + } + } + + @Override + public void updateStoredLeaderboard(Leaderboard leaderboard) { + getMongoObjectFactory().storeLeaderboard(leaderboard); + syncGroupsAfterLeaderboardChange(leaderboard, true); + } + + @Override + public void updateStoredRegatta(Regatta regatta) { + if (regatta.isPersistent()) { + mongoObjectFactory.storeRegatta(regatta); + } + } + + /** + * Checks all groups, if they contain a leaderboard with the name of the updatedLeaderboard and + * replaces the one in the group with the updated one.
    + * This synchronizes things like the RaceIdentifier in the leaderboard columns. + */ + private void syncGroupsAfterLeaderboardChange(Leaderboard updatedLeaderboard, boolean doDatabaseUpdate) { + boolean groupNeedsUpdate = false; + for (LeaderboardGroup leaderboardGroup : leaderboardGroupsByName.values()) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + if (leaderboard == updatedLeaderboard) { + int index = leaderboardGroup.getIndexOf(leaderboard); + leaderboardGroup.removeLeaderboard(leaderboard); + leaderboardGroup.addLeaderboardAt(updatedLeaderboard, index); + groupNeedsUpdate = true; + // TODO we assume that the leaderboard names are unique, so we can break the inner loop here + break; + } + } + + if (doDatabaseUpdate && groupNeedsUpdate) { + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + } + groupNeedsUpdate = false; + } + } + + @Override + public void removeLeaderboard(String leaderboardName) { + Leaderboard leaderboard = removeLeaderboardFromLeaderboardsByName(leaderboardName); + if (leaderboard != null) { + leaderboard.removeRaceColumnListener(raceLogReplicator); + leaderboard.removeRaceColumnListener(raceLogScoringReplicator); + mongoObjectFactory.removeLeaderboard(leaderboardName); + syncGroupsAfterLeaderboardRemove(leaderboardName, true); + if (leaderboard instanceof FlexibleLeaderboard) { + onRegattaLikeRemoved(((FlexibleLeaderboard) leaderboard).getRegattaLike()); + } + leaderboard.destroy(); + } + } + + private Leaderboard removeLeaderboardFromLeaderboardsByName(String leaderboardName) { + LockUtil.lockForWrite(leaderboardsByNameLock); + try { + return leaderboardsByName.remove(leaderboardName); + } finally { + LockUtil.unlockAfterWrite(leaderboardsByNameLock); + } + } + + /** + * Checks all groups, if they contain a leaderboard with the removedLeaderboardName and removes it from + * the group. + * + * @param removedLeaderboardName + */ + private void syncGroupsAfterLeaderboardRemove(String removedLeaderboardName, boolean doDatabaseUpdate) { + boolean groupNeedsUpdate = false; + for (LeaderboardGroup leaderboardGroup : leaderboardGroupsByName.values()) { + for (Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + if (leaderboard.getName().equals(removedLeaderboardName)) { + leaderboardGroup.removeLeaderboard(leaderboard); + groupNeedsUpdate = true; + // TODO we assume that the leaderboard names are unique, so we can break the inner loop here + break; + } + } + + if (doDatabaseUpdate && groupNeedsUpdate) { + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + } + groupNeedsUpdate = false; + } + } + + @Override + public Leaderboard getLeaderboardByName(String name) { + return leaderboardsByName.get(name); + } + + @Override + public Position getMarkPosition(Mark mark, LeaderboardThatHasRegattaLike leaderboard, TimePoint timePoint, RaceLog raceLog) { + GPSFixTrack track = null; + // If no spanning track is found, the fix closest to the time point requested is used instead + GPSFix nonSpanningFallback = null; + for (TrackedRace trackedRace : leaderboard.getTrackedRaces()) { + GPSFixTrack trackCandidate = trackedRace.getTrack(mark); + if (trackCandidate != null) { + if (spansTimePoint(trackCandidate, timePoint)) { + track = trackCandidate; + break; + } else { + nonSpanningFallback = improveTimewiseClosestFix(nonSpanningFallback, trackCandidate, timePoint); + } + } + } + if (track == null) { // no spanning track found in any tracked race, or no tracked races found + // try to load from store + DynamicGPSFixTrackImpl loadedTrack = new DynamicGPSFixTrackImpl(mark, 0); + track = loadedTrack; + Set> logs = new HashSet<>(); + logs.add(leaderboard.getRegattaLike().getRegattaLog()); + if (raceLog == null) { // no race log explicitly provided --> use all race logs + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + logs.add(raceColumn.getRaceLog(fleet)); + } + } + } else { + logs.add(raceLog); + } + for (AbstractLog log : logs) { + try { + getGPSFixStore().loadMarkTrack(loadedTrack, log, mark); + } catch (Exception e) { + logger.log(Level.WARNING, "Couldn't load mark track for mark " + mark + " from log " + log, e); + } + } + } + Position result = track.getEstimatedPosition(timePoint, /* extrapolate */ false); + if (result == null) { + result = nonSpanningFallback == null ? null : nonSpanningFallback.getPosition(); + } + return result; + } + + private GPSFix improveTimewiseClosestFix(GPSFix nonSpanningFallback, GPSFixTrack track, final TimePoint timePoint) { + GPSFix lastAtOrBefore = track.getLastFixAtOrBefore(timePoint); + GPSFix firstAtOrAfter = track.getFirstFixAtOrAfter(timePoint); + // find the fix closes to timePoint, sorting null values to the end and fixes near timePoint to the beginning + final List list = Arrays.asList(nonSpanningFallback, lastAtOrBefore, firstAtOrAfter); + list.sort(new Comparator() { + @Override + public int compare(GPSFix o1, GPSFix o2) { + final int result; + if (o1 == null) { + if (o2 == null) { + result = 0; + } else { + result = 1; + } + } else if (o2 == null) { + result = -1; + } else { + result = new Long(Math.abs(o1.getTimePoint().until(timePoint).asMillis())).compareTo( + Math.abs(o2.getTimePoint().until(timePoint).asMillis())); + } + return result; + } + }); + return list.get(0); + } + + private boolean spansTimePoint(GPSFixTrack track, TimePoint timePoint) { + return track.getLastFixAtOrBefore(timePoint) != null && track.getFirstFixAtOrAfter(timePoint) != null; + } + + @Override + public Map getLeaderboards() { + return Collections.unmodifiableMap(new HashMap(leaderboardsByName)); + } + + @Override + public SailingServerConfiguration getSailingServerConfiguration() { + return sailingServerConfiguration; + } + + @Override + public void updateServerConfiguration(SailingServerConfiguration serverConfiguration) { + this.sailingServerConfiguration = serverConfiguration; + mongoObjectFactory.storeServerConfiguration(serverConfiguration); + } + + @Override + public Map, Exception>> getPublicEventsOfAllSailingServers() { + return remoteSailingServerSet.getCachedEventsForRemoteSailingServers(); // FIXME should probably add our own + // stuff here... Is it enough to pass on + // the remote reference URL to the + // client for leaderboard group URL + // construction? + } + + @Override + public RemoteSailingServerReference addRemoteSailingServerReference(String name, URL url) { + RemoteSailingServerReference result = new RemoteSailingServerReferenceImpl(name, url); + remoteSailingServerSet.add(result); + mongoObjectFactory.storeSailingServer(result); + return result; + } + + @Override + public Iterable getLiveRemoteServerReferences() { + return remoteSailingServerSet.getLiveRemoteServerReferences(); + } + + @Override + public RemoteSailingServerReference getRemoteServerReferenceByName(String remoteServerReferenceName) { + return remoteSailingServerSet.getServerReferenceByName(remoteServerReferenceName); + } + + @Override + public com.sap.sse.common.Util.Pair, Exception> updateRemoteServerEventCacheSynchronously( + RemoteSailingServerReference ref) { + return remoteSailingServerSet.getEventsOrException(ref); + } + + @Override + public void removeRemoteSailingServerReference(String name) { + remoteSailingServerSet.remove(name); + mongoObjectFactory.removeSailingServer(name); + } + + @Override + public Iterable getAllEvents() { + return Collections.unmodifiableCollection(new ArrayList(eventsById.values())); + } + + @Override + public Event getEvent(Serializable id) { + return id == null ? null : eventsById.get(id); + } + + @Override + public Iterable getAllRegattas() { + return Collections.unmodifiableCollection(new ArrayList(regattasByName.values())); + } + + @Override + public boolean isRaceBeingTracked(Regatta regattaContext, RaceDefinition r) { + Set trackers = raceTrackersByRegatta.get(regattaContext); + if (trackers != null) { + for (RaceTracker tracker : trackers) { + final Set races = tracker.getRaces(); + if (races != null && races.contains(r)) { + return true; + } + } + } + return false; + } + + @Override + public Regatta getRegattaByName(String name) { + return name == null ? null : regattasByName.get(name); + } + + @Override + public Regatta getOrCreateDefaultRegatta(String name, String boatClassName, Serializable id) { + Regatta result = regattasByName.get(name); + if (result == null) { + result = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), name, getBaseDomainFactory() + .getOrCreateBoatClass(boatClassName), /* startDate */null, /* endDate */null, this, + getBaseDomainFactory().createScoringScheme(ScoringSchemeType.LOW_POINT), id, null); + logger.info("Created default regatta " + result.getName() + " (" + hashCode() + ") on " + this); + onRegattaLikeAdded(result); + cacheAndReplicateDefaultRegatta(result); + } + return result; + } + + private void onRegattaLikeAdded(IsRegattaLike isRegattaLike) { + isRegattaLike.addListener(regattaLogReplicator); + } + + private void onRegattaLikeRemoved(IsRegattaLike isRegattaLike) { + isRegattaLike.removeListener(regattaLogReplicator); + getRegattaLogStore().removeRegattaLog(isRegattaLike.getRegattaLikeIdentifier()); + } + + @Override + public Regatta createRegatta(String fullRegattaName, String boatClassName, TimePoint startDate, TimePoint endDate, + Serializable id, Iterable series, boolean persistent, ScoringScheme scoringScheme, + Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor) { + com.sap.sse.common.Util.Pair regattaWithCreatedFlag = getOrCreateRegattaWithoutReplication( + fullRegattaName, boatClassName, startDate, endDate, id, series, persistent, scoringScheme, + defaultCourseAreaId, useStartTimeInference, rankingMetricConstructor); + Regatta regatta = regattaWithCreatedFlag.getA(); + if (regattaWithCreatedFlag.getB()) { + onRegattaLikeAdded(regatta); + replicateSpecificRegattaWithoutRaceColumns(regatta); + } + return regatta; + } + + @Override + public void addRegattaWithoutReplication(Regatta regatta) { + UUID defaultCourseAreaId = null; + if (regatta.getDefaultCourseArea() != null) { + defaultCourseAreaId = regatta.getDefaultCourseArea().getId(); + } + boolean wasAdded = addAndConnectRegatta(regatta.isPersistent(), defaultCourseAreaId, regatta); + if (!wasAdded) { + logger.info("Regatta with name " + regatta.getName() + " already existed, so it hasn't been added."); + } + } + + private RaceLogStore getRaceLogStore() { + return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory); + } + + private RegattaLogStore getRegattaLogStore() { + return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore(mongoObjectFactory, domainObjectFactory); + } + + @Override + public com.sap.sse.common.Util.Pair getOrCreateRegattaWithoutReplication(String fullRegattaName, + String boatClassName, TimePoint startDate, TimePoint endDate, Serializable id, + Iterable series, boolean persistent, ScoringScheme scoringScheme, + Serializable defaultCourseAreaId, boolean useStartTimeInference, RankingMetricConstructor rankingMetricConstructor) { + CourseArea courseArea = getCourseArea(defaultCourseAreaId); + Regatta regatta = new RegattaImpl(getRaceLogStore(), getRegattaLogStore(), fullRegattaName, + getBaseDomainFactory().getOrCreateBoatClass(boatClassName), startDate, endDate, series, persistent, + scoringScheme, id, courseArea, useStartTimeInference, rankingMetricConstructor); + boolean wasCreated = addAndConnectRegatta(persistent, defaultCourseAreaId, regatta); + if (wasCreated) { + logger.info("Created regatta " + regatta.getName() + " (" + hashCode() + ") on " + this); + } + return new com.sap.sse.common.Util.Pair(regatta, wasCreated); + } + + private boolean addAndConnectRegatta(boolean persistent, Serializable defaultCourseAreaId, Regatta regatta) { + boolean wasCreated = false; + // try a quick read protected by the concurrent hash map implementation + if (!regattasByName.containsKey(regatta.getName())) { + LockUtil.lockForWrite(regattasByNameLock); + try { + // check again, now that we hold the exclusive write lock + if (!regattasByName.containsKey(regatta.getName())) { + wasCreated = true; + logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() + + ") into regattasByName of " + this); + regattasByName.put(regatta.getName(), regatta); + regatta.addRegattaListener(this); + regatta.addRaceColumnListener(raceLogReplicator); + regatta.addRaceColumnListener(raceLogScoringReplicator); + } + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + } + if (persistent) { + updateStoredRegatta(regatta); + } + for (Event event : getAllEvents()) { + for (CourseArea eventCourseArea : event.getVenue().getCourseAreas()) { + if (defaultCourseAreaId != null && eventCourseArea.getId().equals(defaultCourseAreaId)) { + event.addRegatta(regatta); + } + } + } + return wasCreated; + } + + @Override + public void addRace(RegattaIdentifier addToRegatta, RaceDefinition raceDefinition) { + Regatta regatta = getRegatta(addToRegatta); + regatta.addRace(raceDefinition); // will trigger the raceAdded operation because this service is listening on + // all its regattas + } + + /** + * If the regatta {@link Regatta#isPersistent() is a persistent one}, the association of the race with + * the regatta is remembered persistently so that {@link #getRememberedRegattaForRace(Serializable)} will provide + * it. + */ + @Override + public void raceAdded(Regatta regatta, RaceDefinition raceDefinition) { + if (regatta.isPersistent()) { + setRegattaForRace(regatta, raceDefinition); + } + final CourseChangeReplicator listener = new CourseChangeReplicator(this, regatta, raceDefinition); + courseListeners.put(raceDefinition, listener); + raceDefinition.getCourse().addCourseListener(listener); + replicate(new AddRaceDefinition(regatta.getRegattaIdentifier(), raceDefinition)); + } + + @Override + public void raceRemoved(Regatta regatta, RaceDefinition raceDefinition) { + raceDefinition.getCourse().removeCourseListener(courseListeners.remove(raceDefinition)); + } + + private NamedReentrantReadWriteLock lockRaceTrackersById(Object trackerId) { + NamedReentrantReadWriteLock lock; + synchronized (raceTrackersByIDLocks) { + lock = raceTrackersByIDLocks.get(trackerId); + if (lock == null) { + lock = new NamedReentrantReadWriteLock("raceTrackersByIDLock for " + trackerId, /* fair */false); + raceTrackersByIDLocks.put(trackerId, lock); + } + } + LockUtil.lockForWrite(lock); + return lock; + } + + /** + * @param lock + * need to pass the lock obtained from {@link #lockRaceTrackersById(Object)} because a competing thread + * may already have removed the lock from the {@link #raceTrackersByIDLocks} map + */ + private void unlockRaceTrackersById(Object trackerId, NamedReentrantReadWriteLock lock) { + LockUtil.unlockAfterWrite(lock); + synchronized (raceTrackersByIDLocks) { + raceTrackersByIDLocks.remove(trackerId); + } + } + + @Override + public RaceHandle addRace(RegattaIdentifier regattaToAddTo, RaceTrackingConnectivityParameters params, + long timeoutInMilliseconds) throws Exception { + final Object trackerID = params.getTrackerID(); + NamedReentrantReadWriteLock raceTrackersByIdLock = lockRaceTrackersById(trackerID); + try { + RaceTracker tracker = raceTrackersByID.get(trackerID); + if (tracker == null) { + Regatta regatta = regattaToAddTo == null ? null : getRegatta(regattaToAddTo); + if (regatta == null) { + // create tracker and use an existing or create a default regatta + tracker = params.createRaceTracker(this, windStore, gpsFixStore, /* raceLogResolver */ this); + } else { + // use the regatta selected by the RaceIdentifier regattaToAddTo + tracker = params.createRaceTracker(regatta, this, windStore, gpsFixStore, /* raceLogResolver */ this); + assert tracker.getRegatta() == regatta; + } + LockUtil.lockForWrite(raceTrackersByRegattaLock); + try { + raceTrackersByID.put(trackerID, tracker); + Set trackers = raceTrackersByRegatta.get(tracker.getRegatta()); + if (trackers == null) { + trackers = Collections.newSetFromMap(new ConcurrentHashMap()); + raceTrackersByRegatta.put(tracker.getRegatta(), trackers); + } + trackers.add(tracker); + } finally { + LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); + } + // TODO we assume here that the regatta name is unique which necessitates adding the boat class name to + // it in RegattaImpl constructor + String regattaName = tracker.getRegatta().getName(); + Regatta regattaWithName = regattasByName.get(regattaName); + // TODO we assume here that the regatta name is unique which necessitates adding the boat class name to + // it in RegattaImpl constructor + if (regattaWithName != null) { + if (regattaWithName != tracker.getRegatta()) { + if (Util.isEmpty(regattaWithName.getAllRaces())) { + // probably, tracker removed the last races from the old regatta and created a new one + LockUtil.lockForWrite(regattasByNameLock); + try { + regattasByName.remove(regattaName); + cacheAndReplicateDefaultRegatta(tracker.getRegatta()); + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + } else { + throw new RuntimeException("Internal error. Two regatta objects with equal name " + + regattaName); + } + } + } else { + cacheAndReplicateDefaultRegatta(tracker.getRegatta()); + } + } else { + logger.warning("Race tracker with ID "+trackerID+" already found; not tracking twice to avoid race duplication"); + WindStore existingTrackersWindStore = tracker.getWindStore(); + if (!existingTrackersWindStore.equals(windStore)) { + logger.warning("Wind store mismatch. Requested wind store: " + windStore + + ". Wind store in use by existing tracker: " + existingTrackersWindStore); + } + GPSFixStore existingTrackersGPSFixStore = tracker.getGPSFixStore(); + if (!existingTrackersGPSFixStore.equals(gpsFixStore)) { + logger.warning("GPSFix store mismatch. Requested GPSFix store: " + gpsFixStore + + ". GPSFix store in use by existing tracker: " + existingTrackersGPSFixStore); + } + } + if (timeoutInMilliseconds != -1) { + scheduleAbortTrackerAfterInitialTimeout(tracker, timeoutInMilliseconds); + } + return tracker.getRacesHandle(); + } finally { + unlockRaceTrackersById(trackerID, raceTrackersByIdLock); + } + } + + /** + * The regatta and all its contained {@link Regatta#getAllRaces() races} are replicated to all replicas. + * + * @param regatta + * the series of this regatta must not have any {@link Series#getRaceColumns() race columns associated + * (yet)}. + */ + private void replicateSpecificRegattaWithoutRaceColumns(Regatta regatta) { + Serializable courseAreaId = null; + if (regatta.getDefaultCourseArea() != null) { + courseAreaId = regatta.getDefaultCourseArea().getId(); + } + replicate(new AddSpecificRegatta(regatta.getName(), regatta.getBoatClass() == null ? null : regatta + .getBoatClass().getName(), regatta.getStartDate(), regatta.getEndDate(), regatta.getId(), + getSeriesWithoutRaceColumnsConstructionParametersAsMap(regatta), regatta.isPersistent(), + regatta.getScoringScheme(), courseAreaId, regatta.useStartTimeInference(), regatta.getRankingMetricType())); + RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier(); + for (RaceDefinition race : regatta.getAllRaces()) { + replicate(new AddRaceDefinition(regattaIdentifier, race)); + } + } + + private RegattaCreationParametersDTO getSeriesWithoutRaceColumnsConstructionParametersAsMap(Regatta regatta) { + LinkedHashMap result = new LinkedHashMap(); + for (Series s : regatta.getSeries()) { + assert Util.isEmpty(s.getRaceColumns()); + List fleetNamesAndOrdering = new ArrayList(); + for (Fleet f : s.getFleets()) { + fleetNamesAndOrdering.add(getBaseDomainFactory().convertToFleetDTO(f)); + } + result.put( + s.getName(), + new SeriesCreationParametersDTO(fleetNamesAndOrdering, s.isMedal(), s.isStartsWithZeroScore(), s + .isFirstColumnIsNonDiscardableCarryForward(), s.getResultDiscardingRule() == null ? null + : s.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(), s + .hasSplitFleetContiguousScoring())); + } + return new RegattaCreationParametersDTO(result); + } + + /** + * If regatta is not yet in {@link #regattasByName}, it is added, this service is + * {@link Regatta#addRegattaListener(RegattaListener) added} as regatta listener, and the regatta and all its + * contained {@link Regatta#getAllRaces() races} are replicated to all replica. + */ + private void cacheAndReplicateDefaultRegatta(Regatta regatta) { + // try a quick read first, protected by regattasByName being a concurrent hash set + if (!regattasByName.containsKey(regatta.getName())) { + // now we need to obtain exclusive write access; in between, some other thread may have added a regatta by + // that + // name, so we need to check again: + LockUtil.lockForWrite(regattasByNameLock); + try { + if (!regattasByName.containsKey(regatta.getName())) { + logger.info("putting regatta " + regatta.getName() + " (" + regatta.hashCode() + + ") into regattasByName of " + this); + regattasByName.put(regatta.getName(), regatta); + regatta.addRegattaListener(this); + regatta.addRaceColumnListener(raceLogReplicator); + regatta.addRaceColumnListener(raceLogScoringReplicator); + + replicate(new AddDefaultRegatta(regatta.getName(), regatta.getBoatClass() == null ? null : regatta + .getBoatClass().getName(), regatta.getStartDate(), regatta.getEndDate(), regatta.getId())); + RegattaIdentifier regattaIdentifier = regatta.getRegattaIdentifier(); + for (RaceDefinition race : regatta.getAllRaces()) { + replicate(new AddRaceDefinition(regattaIdentifier, race)); + } + } + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + } + } + + @Override + public DynamicTrackedRace createTrackedRace(RegattaAndRaceIdentifier raceIdentifier, WindStore windStore, + GPSFixStore gpsFixStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, + long millisecondsOverWhichToAverageSpeed, boolean useMarkPassingCalculator) { + DynamicTrackedRegatta trackedRegatta = getOrCreateTrackedRegatta(getRegatta(raceIdentifier)); + RaceDefinition race = getRace(raceIdentifier); + return trackedRegatta.createTrackedRace(race, Collections. emptyList(), windStore, gpsFixStore, + delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, + /* raceDefinitionSetToUpdate */null, useMarkPassingCalculator, /* raceLogResolver */ this); + } + + private void ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking( + DynamicTrackedRegatta trackedRegatta) { + if (regattasObservedForDefaultLeaderboard.add(trackedRegatta)) { + trackedRegatta.addRaceListener(new RaceAdditionListener()); + } + } + + private void stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(DynamicTrackedRegatta trackedRegatta) { + regattasObservedForDefaultLeaderboard.remove(trackedRegatta); + } + + /** + * A listener class used to ensure that when a tracked race is added to any {@link TrackedRegatta} managed by this + * service, the service adds the tracked race to the default leaderboard and links it to the leaderboard columns + * that were previously connected to it. Additionally, a {@link RaceChangeListener} is added to the + * {@link TrackedRace} which is responsible for triggering the replication of all relevant changes to the tracked + * race. When a tracked race is removed, the {@link TrackedRaceReplicator} that was added as listener to that + * tracked race is removed again. + * + * A {@link PolarFixCacheUpdater} is added to every race so that polar fixes are aggregated when new GPS fixes + * arrive. + * + * @author Axel Uhl (d043530) + * + */ + private class RaceAdditionListener implements RaceListener, Serializable { + private static final long serialVersionUID = 1036955460477000265L; + + private final Map trackedRaceReplicators; + + private final Map polarFixCacheUpdaters; + + public RaceAdditionListener() { + this.trackedRaceReplicators = new HashMap(); + this.polarFixCacheUpdaters = new HashMap(); + } + + @Override + public void raceRemoved(TrackedRace trackedRace) { + TrackedRaceReplicator trackedRaceReplicator = trackedRaceReplicators.remove(trackedRace); + if (trackedRaceReplicator != null) { + trackedRace.removeListener(trackedRaceReplicator); + } + PolarFixCacheUpdater polarFixCacheUpdater = polarFixCacheUpdaters.remove(trackedRace); + if (polarFixCacheUpdater != null) { + trackedRace.removeListener(polarFixCacheUpdater); + } + } + + @Override + public void raceAdded(TrackedRace trackedRace) { + // replicate the addition of the tracked race: + CreateTrackedRace op = new CreateTrackedRace(trackedRace.getRaceIdentifier(), trackedRace.getWindStore(), + trackedRace.getGPSFixStore(), trackedRace.getDelayToLiveInMillis(), + trackedRace.getMillisecondsOverWhichToAverageWind(), + trackedRace.getMillisecondsOverWhichToAverageSpeed()); + replicate(op); + linkRaceToConfiguredLeaderboardColumns(trackedRace); + TrackedRaceReplicator trackedRaceReplicator = new TrackedRaceReplicator(trackedRace); + trackedRaceReplicators.put(trackedRace, trackedRaceReplicator); + trackedRace.addListener(trackedRaceReplicator, /* fire wind already loaded */true, true); + + PolarFixCacheUpdater polarFixCacheUpdater = new PolarFixCacheUpdater(trackedRace); + polarFixCacheUpdaters.put(trackedRace, polarFixCacheUpdater); + trackedRace.addListener(polarFixCacheUpdater); + + if (polarDataService != null) { + trackedRace.setPolarDataService(polarDataService); + } + } + } + + private class PolarFixCacheUpdater extends AbstractRaceChangeListener { + + private final TrackedRace race; + + public PolarFixCacheUpdater(TrackedRace race) { + this.race = race; + } + + @Override + public void competitorPositionChanged(GPSFixMoving fix, Competitor item) { + if (polarDataService != null) { + polarDataService.competitorPositionChanged(fix, item, race); + } + } + + @Override + public void statusChanged(TrackedRaceStatus newStatus, TrackedRaceStatus oldStatus) { + if (oldStatus.getStatus() == TrackedRaceStatusEnum.LOADING + && newStatus.getStatus() != TrackedRaceStatusEnum.LOADING) { + if (polarDataService != null) { + polarDataService.raceFinishedLoading(race); + } + } + } + + } + + private class TrackedRaceReplicator implements RaceChangeListener { + private final TrackedRace trackedRace; + + public TrackedRaceReplicator(TrackedRace trackedRace) { + this.trackedRace = trackedRace; + } + + @Override + public void windSourcesToExcludeChanged(Iterable windSourcesToExclude) { + replicate(new UpdateWindSourcesToExclude(getRaceIdentifier(), windSourcesToExclude)); + } + + @Override + public void startOfTrackingChanged(TimePoint startOfTracking) { + replicate(new UpdateStartOfTracking(getRaceIdentifier(), startOfTracking)); + } + + @Override + public void endOfTrackingChanged(TimePoint endOfTracking) { + replicate(new UpdateEndOfTracking(getRaceIdentifier(), endOfTracking)); + } + + @Override + public void startTimeReceivedChanged(TimePoint startTimeReceived) { + replicate(new UpdateStartTimeReceived(getRaceIdentifier(), startTimeReceived)); + } + + @Override + public void startOfRaceChanged(TimePoint oldStartOfRace, TimePoint newStartOfRace) { + // no action required; the update signaled by this call is implicit; for explicit updates + // see raceTimesChanged(TimePoint, TimePoint, TimePoint). + } + + @Override + public void waypointAdded(int zeroBasedIndex, Waypoint waypointThatGotAdded) { + // no-op; the course change is replicated by the separate CourseChangeReplicator + } + + @Override + public void waypointRemoved(int zeroBasedIndex, Waypoint waypointThatGotRemoved) { + // no-op; the course change is replicated by the separate CourseChangeReplicator + } + + @Override + public void delayToLiveChanged(long delayToLiveInMillis) { + replicate(new UpdateRaceDelayToLive(getRaceIdentifier(), delayToLiveInMillis)); + } + + @Override + public void windDataReceived(Wind wind, WindSource windSource) { + replicate(new RecordWindFix(getRaceIdentifier(), windSource, wind)); + } + + @Override + public void windDataRemoved(Wind wind, WindSource windSource) { + replicate(new RemoveWindFix(getRaceIdentifier(), windSource, wind)); + } + + @Override + public void windAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) { + replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage)); + } + + @Override + public void competitorPositionChanged(GPSFixMoving fix, Competitor competitor) { + replicate(new RecordCompetitorGPSFix(getRaceIdentifier(), competitor, fix)); + } + + @Override + public void statusChanged(TrackedRaceStatus newStatus, TrackedRaceStatus oldStatus) { + replicate(new UpdateTrackedRaceStatus(getRaceIdentifier(), newStatus)); + } + + @Override + public void markPositionChanged(GPSFix fix, Mark mark, boolean firstInTrack) { + final RecordMarkGPSFix operation; + if (firstInTrack) { + operation = new RecordMarkGPSFixForNewMarkTrack(getRaceIdentifier(), mark, fix); + } else { + operation = new RecordMarkGPSFixForExistingTrack(getRaceIdentifier(), mark, fix); + } + replicate(operation); + } + + @Override + public void markPassingReceived(Competitor competitor, Map oldMarkPassings, + Iterable markPassings) { + replicate(new UpdateMarkPassings(getRaceIdentifier(), competitor, markPassings)); + } + + @Override + public void speedAveragingChanged(long oldMillisecondsOverWhichToAverage, long newMillisecondsOverWhichToAverage) { + replicate(new UpdateWindAveragingTime(getRaceIdentifier(), newMillisecondsOverWhichToAverage)); + } + + private RegattaAndRaceIdentifier getRaceIdentifier() { + return trackedRace.getRaceIdentifier(); + } + + } + + /** + * Based on the trackedRace's {@link TrackedRace#getRaceIdentifier() race identifier}, the tracked race + * is (re-)associated to all {@link RaceColumn race columns} that currently have no + * {@link RaceColumn#getTrackedRace(Fleet) tracked race assigned} and whose + * {@link RaceColumn#getRaceIdentifier(Fleet) race identifier} equals that of trackedRace. + */ + private void linkRaceToConfiguredLeaderboardColumns(TrackedRace trackedRace) { + boolean leaderboardHasChanged = false; + RegattaAndRaceIdentifier trackedRaceIdentifier = trackedRace.getRaceIdentifier(); + for (Leaderboard leaderboard : getLeaderboards().values()) { + for (RaceColumn column : leaderboard.getRaceColumns()) { + for (Fleet fleet : column.getFleets()) { + if (trackedRaceIdentifier.equals(column.getRaceIdentifier(fleet)) + && column.getTrackedRace(fleet) == null) { + column.setTrackedRace(fleet, trackedRace); + leaderboardHasChanged = true; + replicate(new ConnectTrackedRaceToLeaderboardColumn(leaderboard.getName(), column.getName(), + fleet.getName(), trackedRaceIdentifier)); + } + } + } + if (leaderboardHasChanged) { + // Update the corresponding groups, to keep them in sync + syncGroupsAfterLeaderboardChange(leaderboard, /* doDatabaseUpdate */false); + } + } + } + + @Override + public void stopTracking(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { + final Set trackersForRegatta = raceTrackersByRegatta.get(regatta); + if (trackersForRegatta != null) { + for (RaceTracker raceTracker : trackersForRegatta) { + final Set races = raceTracker.getRaces(); + if (races != null) { + for (RaceDefinition race : races) { + stopTrackingWind(regatta, race); + } + } + raceTracker.stop(/* preemptive */false); + final Object trackerId = raceTracker.getID(); + final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); + try { + raceTrackersByID.remove(trackerId); + } finally { + unlockRaceTrackersById(trackerId, lock); + } + raceTrackersByID.remove(trackerId); + } + LockUtil.lockForWrite(raceTrackersByRegattaLock); + try { + raceTrackersByRegatta.remove(regatta); + } finally { + LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); + } + } + } + + @Override + public void stopTrackingAndRemove(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { + stopTracking(regatta); + if (regatta != null) { + if (regatta.getName() != null) { + logger.info("Removing regatta " + regatta.getName() + " (" + regatta.hashCode() + ") from " + this); + LockUtil.lockForWrite(regattasByNameLock); + try { + regattasByName.remove(regatta.getName()); + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + LockUtil.lockForWrite(regattaTrackingCacheLock); + try { + regattaTrackingCache.remove(regatta); + } finally { + LockUtil.unlockAfterWrite(regattaTrackingCacheLock); + } + regatta.removeRegattaListener(this); + regatta.removeRaceColumnListener(raceLogReplicator); + regatta.removeRaceColumnListener(raceLogScoringReplicator); + } + for (RaceDefinition race : regatta.getAllRaces()) { + stopTrackingWind(regatta, race); + } + } + } + + /** + * The tracker will initially try to connect to the tracking infrastructure to obtain basic race master data. If + * this fails after some timeout, to avoid garbage and lingering threads, the task scheduled by this method will + * check after the timeout expires if race master data was successfully received. If so, the tracker continues + * normally. Otherwise, the tracker is shut down orderly by calling {@link RaceTracker#stop(boolean) stopping}. + * + * @return the scheduled task, in case the caller wants to {@link ScheduledFuture#cancel(boolean) cancel} it, e.g., + * when the tracker is stopped or has successfully received the race + */ + private ScheduledFuture scheduleAbortTrackerAfterInitialTimeout(final RaceTracker tracker, + final long timeoutInMilliseconds) { + ScheduledFuture task = getScheduler().schedule(new Runnable() { + @Override + public void run() { + if (tracker.getRaces() == null || tracker.getRaces().isEmpty()) { + try { + Regatta regatta = tracker.getRegatta(); + logger.log(Level.SEVERE, "RaceDefinition for a race in regatta " + regatta.getName() + + " not obtained within " + timeoutInMilliseconds + + "ms. Aborting tracker for this race."); + Set trackersForRegatta = raceTrackersByRegatta.get(regatta); + if (trackersForRegatta != null) { + trackersForRegatta.remove(tracker); + } + tracker.stop(/* preemptive */true); + final Object trackerId = tracker.getID(); + final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); + try { + raceTrackersByID.remove(trackerId); + } finally { + unlockRaceTrackersById(trackerId, lock); + } + if (trackersForRegatta == null || trackersForRegatta.isEmpty()) { + stopTracking(regatta); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "scheduleAbortTrackerAfterInitialTimeout", e); + e.printStackTrace(); + } + } + } + }, /* delay */timeoutInMilliseconds, /* unit */TimeUnit.MILLISECONDS); + return task; + } + + @Override + public void stopTracking(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException, + InterruptedException { + logger.info("Stopping tracking for " + race + "..."); + final Set trackerSet = raceTrackersByRegatta.get(regatta); + if (trackerSet != null) { + Iterator trackerIter = trackerSet.iterator(); + while (trackerIter.hasNext()) { + RaceTracker raceTracker = trackerIter.next(); + if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) { + logger.info("Found tracker to stop for races " + raceTracker.getRaces()); + raceTracker.stop(/* preemptive */false); + trackerIter.remove(); + final Object trackerId = raceTracker.getID(); + final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); + try { + raceTrackersByID.remove(trackerId); + } finally { + unlockRaceTrackersById(trackerId, lock); + } + } + } + } else { + logger.warning("Didn't find any trackers for regatta " + regatta); + } + stopTrackingWind(regatta, race); + // if the last tracked race was removed, confirm that tracking for the entire regatta has stopped + if (trackerSet == null || trackerSet.isEmpty()) { + stopTracking(regatta); + } + } + + @Override + public void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { + Set leaderboardsToRemove = new HashSet<>(); + for (Leaderboard leaderboard : getLeaderboards().values()) { + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; + if (regattaLeaderboard.getRegatta() == regatta) { + leaderboardsToRemove.add(regattaLeaderboard); + } + } + } + for (RegattaLeaderboard regattaLeaderboardToRemove : leaderboardsToRemove) { + removeLeaderboard(regattaLeaderboardToRemove.getName()); + } + // avoid ConcurrentModificationException by copying the races to remove: + Set racesToRemove = new HashSet<>(); + Util.addAll(regatta.getAllRaces(), racesToRemove); + for (RaceDefinition race : racesToRemove) { + removeRace(regatta, race); + mongoObjectFactory.removeRegattaForRaceID(race.getName(), regatta); + persistentRegattasForRaceIDs.remove(race.getId().toString()); + } + if (regatta.isPersistent()) { + mongoObjectFactory.removeRegatta(regatta); + } + LockUtil.lockForWrite(regattasByNameLock); + try { + regattasByName.remove(regatta.getName()); + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + regatta.removeRegattaListener(this); + regatta.removeRaceColumnListener(raceLogReplicator); + regatta.removeRaceColumnListener(raceLogScoringReplicator); + onRegattaLikeRemoved(regatta); + } + + @Override + public void removeSeries(Series series) throws MalformedURLException, IOException, InterruptedException { + Regatta regatta = series.getRegatta(); + regatta.removeSeries(series); + if (regatta.isPersistent()) { + mongoObjectFactory.storeRegatta(regatta); + } + } + + @Override + public Regatta updateRegatta(RegattaIdentifier regattaIdentifier, TimePoint startDate, TimePoint endDate, + Serializable newDefaultCourseAreaId, RegattaConfiguration newRegattaConfiguration, + Iterable series, boolean useStartTimeInference) { + // We're not doing any renaming of the regatta itself, therefore we don't have to sync on the maps. + Regatta regatta = getRegatta(regattaIdentifier); + CourseArea newCourseArea = getCourseArea(newDefaultCourseAreaId); + if (newCourseArea != regatta.getDefaultCourseArea()) { + regatta.setDefaultCourseArea(newCourseArea); + } + regatta.setStartDate(startDate); + regatta.setEndDate(endDate); + if (regatta.useStartTimeInference() != useStartTimeInference) { + regatta.setUseStartTimeInference(useStartTimeInference); + final DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(regatta); + if (trackedRegatta != null) { + trackedRegatta.lockTrackedRacesForRead(); + try { + for (DynamicTrackedRace trackedRace : trackedRegatta.getTrackedRaces()) { + // the start times of the regatta's tracked races now have to be re-evaluated the next time they + // are queried + trackedRace.invalidateStartTime(); + } + } finally { + trackedRegatta.unlockTrackedRacesAfterRead(); + } + } + } + regatta.setRegattaConfiguration(newRegattaConfiguration); + if (series != null) { + for (Series seriesObj : series) { + regatta.addSeries(seriesObj); + } + } + regatta.adjustEventToRegattaAssociation(this); + if (regatta.isPersistent()) { + mongoObjectFactory.storeRegatta(regatta); + } + return regatta; + } + + @Override + public void removeRace(Regatta regatta, RaceDefinition race) throws MalformedURLException, IOException, + InterruptedException { + logger.info("Removing the race " + race + "..."); + stopAllTrackersForWhichRaceIsLastReachable(regatta, race); + stopTrackingWind(regatta, race); + TrackedRace trackedRace = getExistingTrackedRace(regatta, race); + if (trackedRace != null) { + TrackedRegatta trackedRegatta = getTrackedRegatta(regatta); + final boolean isTrackedRacesEmpty; + if (trackedRegatta != null) { + trackedRegatta.lockTrackedRacesForWrite(); + try { + trackedRegatta.removeTrackedRace(trackedRace); + isTrackedRacesEmpty = Util.isEmpty(trackedRegatta.getTrackedRaces()); + } finally { + trackedRegatta.unlockTrackedRacesAfterWrite(); + } + } else { + isTrackedRacesEmpty = false; + } + if (isTrackedRacesEmpty) { + removeTrackedRegatta(regatta); + } + // remove tracked race from RaceColumns of regatta + for (Series series : regatta.getSeries()) { + for (RaceColumnInSeries raceColumn : series.getRaceColumns()) { + for (Fleet fleet : series.getFleets()) { + if (raceColumn.getTrackedRace(fleet) == trackedRace) { + raceColumn.releaseTrackedRace(fleet); + } + } + } + } + for (Leaderboard leaderboard : getLeaderboards().values()) { + if (leaderboard instanceof FlexibleLeaderboard) { // RegattaLeaderboards have implicitly been updated by + // the code above + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + for (Fleet fleet : raceColumn.getFleets()) { + if (raceColumn.getTrackedRace(fleet) == trackedRace) { + raceColumn.releaseTrackedRace(fleet); // but leave the RaceIdentifier on the race column + // untouched, e.g., for later re-load + } + } + } + } + } + } + // remove the race from the (default) regatta if the regatta is not persistently stored + regatta.removeRace(race); + if (!regatta.isPersistent() && Util.isEmpty(regatta.getAllRaces())) { + logger.info("Removing regatta " + regatta.getName() + " (" + regatta.hashCode() + ") from service " + this); + LockUtil.lockForWrite(regattasByNameLock); + try { + regattasByName.remove(regatta.getName()); + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + regatta.removeRegattaListener(this); + regatta.removeRaceColumnListener(raceLogReplicator); + regatta.removeRaceColumnListener(raceLogScoringReplicator); + } + } + + /** + * Doesn't stop any wind trackers + */ + private void stopAllTrackersForWhichRaceIsLastReachable(Regatta regatta, RaceDefinition race) + throws MalformedURLException, IOException, InterruptedException { + if (raceTrackersByRegatta.containsKey(regatta)) { + Iterator trackerIter = raceTrackersByRegatta.get(regatta).iterator(); + while (trackerIter.hasNext()) { + RaceTracker raceTracker = trackerIter.next(); + if (raceTracker.getRaces() != null && raceTracker.getRaces().contains(race)) { + boolean foundReachableRace = false; + for (RaceDefinition raceTrackedByTracker : raceTracker.getRaces()) { + if (raceTrackedByTracker != race && isReachable(regatta, raceTrackedByTracker)) { + foundReachableRace = true; + break; + } + } + if (!foundReachableRace) { + // firstly stop the tracker + raceTracker.stop(/* preemptive */true); + // remove it from the raceTrackers by Regatta + trackerIter.remove(); + final Object trackerId = raceTracker.getID(); + final NamedReentrantReadWriteLock lock = lockRaceTrackersById(trackerId); + try { + raceTrackersByID.remove(trackerId); + } finally { + unlockRaceTrackersById(trackerId, lock); + } + // if the last tracked race was removed, remove the entire regatta + if (raceTrackersByRegatta.get(regatta).isEmpty()) { + stopTracking(regatta); + } + } + } + } + } + } + + private boolean isReachable(Regatta regatta, RaceDefinition race) { + return Util.contains(regatta.getAllRaces(), race); + } + + @Override + public void startTrackingWind(Regatta regatta, RaceDefinition race, boolean correctByDeclination) throws Exception { + for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { + windTrackerFactory.createWindTracker(getOrCreateTrackedRegatta(regatta), race, correctByDeclination); + } + } + + @Override + public void stopTrackingWind(Regatta regatta, RaceDefinition race) throws SocketException, IOException { + for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { + WindTracker windTracker = windTrackerFactory.getExistingWindTracker(race); + if (windTracker != null) { + windTracker.stop(); + } + } + } + + @Override + public Iterable> getWindTrackedRaces() { + List> result = new ArrayList>(); + for (Regatta regatta : getAllRegattas()) { + for (RaceDefinition race : regatta.getAllRaces()) { + for (WindTrackerFactory windTrackerFactory : getWindTrackerFactories()) { + WindTracker windTracker = windTrackerFactory.getExistingWindTracker(race); + if (windTracker != null) { + result.add(new com.sap.sse.common.Util.Triple(regatta, race, + windTracker.toString())); + } + } + } + } + return result; + } + + @Override + public DynamicTrackedRace getTrackedRace(Regatta regatta, RaceDefinition race) { + return getOrCreateTrackedRegatta(regatta).getTrackedRace(race); + } + + private DynamicTrackedRace getExistingTrackedRace(Regatta regatta, RaceDefinition race) { + return getOrCreateTrackedRegatta(regatta).getExistingTrackedRace(race); + } + + @Override + public DynamicTrackedRegatta getOrCreateTrackedRegatta(Regatta regatta) { + cacheAndReplicateDefaultRegatta(regatta); + LockUtil.lockForWrite(regattaTrackingCacheLock); + try { + DynamicTrackedRegatta result = regattaTrackingCache.get(regatta); + if (result == null) { + logger.info("Creating DynamicTrackedRegattaImpl for regatta " + regatta.getName() + " with hashCode " + + regatta.hashCode()); + result = new DynamicTrackedRegattaImpl(regatta); + replicate(new TrackRegatta(regatta.getRegattaIdentifier())); + regattaTrackingCache.put(regatta, result); + ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(result); + } + return result; + } finally { + LockUtil.unlockAfterWrite(regattaTrackingCacheLock); + } + } + + @Override + public DynamicTrackedRegatta getTrackedRegatta(com.sap.sailing.domain.base.Regatta regatta) { + return regattaTrackingCache.get(regatta); + } + + @Override + public void removeTrackedRegatta(Regatta regatta) { + logger.info("Removing regatta " + regatta.getName() + " from regattaTrackingCache"); + final DynamicTrackedRegatta trackedRegatta; + LockUtil.lockForWrite(regattaTrackingCacheLock); + try { + trackedRegatta = regattaTrackingCache.remove(regatta); + } finally { + LockUtil.unlockAfterWrite(regattaTrackingCacheLock); + } + stopObservingRegattaForRedaultLeaderboardAndAutoLeaderboardLinking(trackedRegatta); + } + + @Override + public Regatta getRegatta(RegattaName regattaName) { + return (Regatta) regattasByName.get(regattaName.getRegattaName()); + } + + @Override + public Regatta getRegatta(RegattaIdentifier regattaIdentifier) { + return (Regatta) regattaIdentifier.getRegatta(this); + } + + @Override + public DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { + DynamicTrackedRace result = null; + Regatta regatta = regattasByName.get(raceIdentifier.getRegattaName()); + if (regatta != null) { + DynamicTrackedRegatta trackedRegatta = regattaTrackingCache.get(regatta); + if (trackedRegatta != null) { + RaceDefinition race = getRace(raceIdentifier); + if (race != null) { + result = trackedRegatta.getTrackedRace(race); + } + } + } + return result; + } + + @Override + public DynamicTrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier raceIdentifier) { + Regatta regatta = getRegattaByName(raceIdentifier.getRegattaName()); + DynamicTrackedRace trackedRace = null; + if (regatta != null) { + RaceDefinition race = regatta.getRaceByName(raceIdentifier.getRaceName()); + trackedRace = getOrCreateTrackedRegatta(regatta).getExistingTrackedRace(race); + } + return trackedRace; + } + + @Override + public RaceDefinition getRace(RegattaAndRaceIdentifier regattaNameAndRaceName) { + RaceDefinition result = null; + Regatta regatta = getRegatta(regattaNameAndRaceName); + if (regatta != null) { + result = regatta.getRaceByName(regattaNameAndRaceName.getRaceName()); + } + return result; + } + + @Override + public Map getLeaderboardGroups() { + return Collections.unmodifiableMap(new HashMap(leaderboardGroupsByName)); + } + + @Override + public LeaderboardGroup getLeaderboardGroupByName(String groupName) { + return leaderboardGroupsByName.get(groupName); + } + + @Override + public LeaderboardGroup getLeaderboardGroupByID(UUID leaderboardGroupID) { + return leaderboardGroupsByID.get(leaderboardGroupID); + } + + @Override + public LeaderboardGroup addLeaderboardGroup(UUID id, String groupName, String description, String displayName, + boolean displayGroupsInReverseOrder, List leaderboardNames, + int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { + ArrayList leaderboards = new ArrayList<>(); + for (String leaderboardName : leaderboardNames) { + Leaderboard leaderboard = leaderboardsByName.get(leaderboardName); + if (leaderboard == null) { + throw new IllegalArgumentException("No leaderboard with name " + leaderboardName + " found"); + } else { + leaderboards.add(leaderboard); + } + } + LeaderboardGroup result = new LeaderboardGroupImpl(id, groupName, description, displayName, + displayGroupsInReverseOrder, leaderboards); + if (overallLeaderboardScoringSchemeType != null) { + // create overall leaderboard and its discards settings + addOverallLeaderboardToLeaderboardGroup(result, + getBaseDomainFactory().createScoringScheme(overallLeaderboardScoringSchemeType), + overallLeaderboardDiscardThresholds); + } + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + if (leaderboardGroupsByName.containsKey(groupName)) { + throw new IllegalArgumentException("Leaderboard group with name " + groupName + " already exists"); + } + leaderboardGroupsByName.put(groupName, result); + leaderboardGroupsByID.put(result.getId(), result); + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + mongoObjectFactory.storeLeaderboardGroup(result); + return result; + } + + @Override + public void addLeaderboardGroupWithoutReplication(LeaderboardGroup leaderboardGroup) { + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + String groupName = leaderboardGroup.getName(); + if (leaderboardGroupsByName.containsKey(groupName)) { + throw new IllegalArgumentException("Leaderboard group with name " + groupName + " already exists"); + } + leaderboardGroupsByName.put(groupName, leaderboardGroup); + leaderboardGroupsByID.put(leaderboardGroup.getId(), leaderboardGroup); + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + if (leaderboardGroup.hasOverallLeaderboard()) { + addLeaderboard(leaderboardGroup.getOverallLeaderboard()); + } + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + } + + @Override + public void removeLeaderboardGroup(String groupName) { + final LeaderboardGroup leaderboardGroup; + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + leaderboardGroup = leaderboardGroupsByName.remove(groupName); + if (leaderboardGroup != null) { + leaderboardGroupsByID.remove(leaderboardGroup.getId()); + } + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + mongoObjectFactory.removeLeaderboardGroup(groupName); + if (leaderboardGroup != null && leaderboardGroup.getOverallLeaderboard() != null) { + removeLeaderboard(leaderboardGroup.getOverallLeaderboard().getName()); + } + } + + @Override + public void renameLeaderboardGroup(String oldName, String newName) { + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + final LeaderboardGroup toRename = leaderboardGroupsByName.get(oldName); + if (toRename == null) { + throw new IllegalArgumentException("No leaderboard group with name " + oldName + " found"); + } + if (leaderboardGroupsByName.containsKey(newName)) { + throw new IllegalArgumentException("Leaderboard group with name " + newName + " already exists"); + } + leaderboardGroupsByName.remove(oldName); + toRename.setName(newName); + leaderboardGroupsByName.put(newName, toRename); + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + mongoObjectFactory.renameLeaderboardGroup(oldName, newName); + } + + @Override + public void updateLeaderboardGroup(String oldName, String newName, String description, String displayName, + List leaderboardNames, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType) { + if (!oldName.equals(newName)) { + renameLeaderboardGroup(oldName, newName); + } + LeaderboardGroup group = getLeaderboardGroupByName(newName); + if (!description.equals(group.getDescription())) { + group.setDescriptiom(description); + } + if (!Util.equalsWithNull(displayName, group.getDisplayName())) { + group.setDisplayName(displayName); + } + group.clearLeaderboards(); + for (String leaderboardName : leaderboardNames) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + group.addLeaderboard(leaderboard); + } + } + Leaderboard overallLeaderboard = group.getOverallLeaderboard(); + if (overallLeaderboard != null) { + if (overallLeaderboardScoringSchemeType == null) { + group.setOverallLeaderboard(null); + removeLeaderboard(overallLeaderboard.getName()); + } else { + // update existing overall leaderboard's discards settings; scoring scheme cannot be updated in-place + overallLeaderboard.setCrossLeaderboardResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl( + overallLeaderboardDiscardThresholds)); + updateStoredLeaderboard(overallLeaderboard); + } + } else if (overallLeaderboard == null && overallLeaderboardScoringSchemeType != null) { + addOverallLeaderboardToLeaderboardGroup(group, + getBaseDomainFactory().createScoringScheme(overallLeaderboardScoringSchemeType), + overallLeaderboardDiscardThresholds); + } + updateStoredLeaderboardGroup(group); + } + + private void addOverallLeaderboardToLeaderboardGroup(LeaderboardGroup leaderboardGroup, + ScoringScheme scoringScheme, int[] discardThresholds) { + Leaderboard overallLeaderboard = new LeaderboardGroupMetaLeaderboard(leaderboardGroup, scoringScheme, + new ThresholdBasedResultDiscardingRuleImpl(discardThresholds)); + leaderboardGroup.setOverallLeaderboard(overallLeaderboard); + addLeaderboard(overallLeaderboard); + updateStoredLeaderboard(overallLeaderboard); + } + + @Override + public void updateStoredLeaderboardGroup(LeaderboardGroup leaderboardGroup) { + mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); + } + + private ScheduledExecutorService getScheduler() { + return scheduler; + } + + @Override + public ObjectInputStream createObjectInputStreamResolvingAgainstCache(InputStream is) throws IOException { + return getBaseDomainFactory().createObjectInputStreamResolvingAgainstThisFactory(is); + } + + @Override + public ClassLoader getDeserializationClassLoader() { + return joinedClassLoader; + } + + @Override + public Serializable getId() { + return getClass().getName(); + } + + @Override + public Iterable> getOperationExecutionListeners() { + return operationExecutionListeners.keySet(); + } + + @Override + public void addOperationExecutionListener(OperationExecutionListener listener) { + operationExecutionListeners.put(listener, listener); + } + + @Override + public void removeOperationExecutionListener(OperationExecutionListener listener) { + operationExecutionListeners.remove(listener); + } + + @Override + public void serializeForInitialReplicationInternal(ObjectOutputStream oos) throws IOException { + StringBuffer logoutput = new StringBuffer(); + + logger.info("Serializing regattas..."); + oos.writeObject(regattasByName); + logoutput.append("Serialized " + regattasByName.size() + " regattas\n"); + for (Regatta regatta : regattasByName.values()) { + logoutput.append(String.format("%3s\n", regatta.toString())); + } + + logger.info("Serializing events..."); + oos.writeObject(eventsById); + logoutput.append("\nSerialized " + eventsById.size() + " events\n"); + for (Event event : eventsById.values()) { + logoutput.append(String.format("%3s\n", event.toString())); + } + + logger.info("Serializing regattas observed..."); + oos.writeObject(regattasObservedForDefaultLeaderboard); + logger.info("Serializing regatta tracking cache..."); + oos.writeObject(regattaTrackingCache); + logger.info("Serializing leaderboard groups..."); + oos.writeObject(leaderboardGroupsByName); + logoutput.append("Serialized " + leaderboardGroupsByName.size() + " leaderboard groups\n"); + for (LeaderboardGroup lg : leaderboardGroupsByName.values()) { + logoutput.append(String.format("%3s\n", lg.toString())); + } + logger.info("Serializing leaderboards..."); + oos.writeObject(leaderboardsByName); + logoutput.append("Serialized " + leaderboardsByName.size() + " leaderboards\n"); + for (Leaderboard lg : leaderboardsByName.values()) { + logoutput.append(String.format("%3s\n", lg.toString())); + } + logger.info("Serializing media library..."); + mediaLibrary.serialize(oos); + logoutput.append("Serialized " + mediaLibrary.allTracks().size() + " media tracks\n"); + for (MediaTrack lg : mediaLibrary.allTracks()) { + logoutput.append(String.format("%3s\n", lg.toString())); + } + logger.info("Serializing persisted competitors..."); + oos.writeObject(competitorStore); + logoutput.append("Serialized " + competitorStore.size() + " persisted competitors\n"); + + logger.info("Serializing configuration map..."); + oos.writeObject(configurationMap); + logoutput.append("Serialized " + configurationMap.size() + " configuration entries\n"); + for (DeviceConfigurationMatcher matcher : configurationMap.keySet()) { + logoutput.append(String.format("%3s\n", matcher.toString())); + } + + logger.info("Serializing remote sailing server references..."); + final ArrayList remoteServerReferences = new ArrayList<>(remoteSailingServerSet + .getCachedEventsForRemoteSailingServers().keySet()); + oos.writeObject(remoteServerReferences); + logoutput.append("Serialized " + remoteServerReferences.size() + " remote sailing server references\n"); + + logger.info(logoutput.toString()); + } + + @SuppressWarnings("unchecked") + // all the casts of ois.readObject()'s return value to Map<..., ...> + // the type-parameters in the casts of the de-serialized collection objects can't be checked + @Override + public void initiallyFillFromInternal(ObjectInputStream ois) throws IOException, ClassNotFoundException, + InterruptedException { + logger.info("Performing initial replication load on " + this); + // Use this object's class's class loader as the context class loader which will then be used for + // de-serialization; this will cause all classes to be visible that this bundle + // (com.sap.sailing.server) can see + StringBuffer logoutput = new StringBuffer(); + logger.info("Reading all regattas..."); + regattasByName.putAll((Map) ois.readObject()); + logoutput.append("Received " + regattasByName.size() + " NEW regattas\n"); + for (Regatta regatta : regattasByName.values()) { + logoutput.append(String.format("%3s\n", regatta.toString())); + } + + logger.info("Reading all events..."); + eventsById.putAll((Map) ois.readObject()); + logoutput.append("\nReceived " + eventsById.size() + " NEW events\n"); + for (Event event : eventsById.values()) { + logoutput.append(String.format("%3s\n", event.toString())); + } + + // it is important that the leaderboards and tracked regattas are cleared before auto-linking to + // old leaderboards takes place which then don't match the new ones + logger.info("Reading all dynamic tracked regattas..."); + for (DynamicTrackedRegatta trackedRegattaToObserve : (Set) ois.readObject()) { + ensureRegattaIsObservedForDefaultLeaderboardAndAutoLeaderboardLinking(trackedRegattaToObserve); + } + + logger.info("Reading all of the regatta tracking cache..."); + regattaTrackingCache.putAll((Map) ois.readObject()); + logoutput.append("Received " + regattaTrackingCache.size() + " NEW regatta tracking cache entries\n"); + + logger.info("Reading leaderboard groups..."); + leaderboardGroupsByName.putAll((Map) ois.readObject()); + logoutput.append("Received " + leaderboardGroupsByName.size() + " NEW leaderboard groups\n"); + for (LeaderboardGroup lg : leaderboardGroupsByName.values()) { + leaderboardGroupsByID.put(lg.getId(), lg); + logoutput.append(String.format("%3s\n", lg.toString())); + } + + logger.info("Reading leaderboards by name..."); + leaderboardsByName.putAll((Map) ois.readObject()); + logoutput.append("Received " + leaderboardsByName.size() + " NEW leaderboards\n"); + for (Leaderboard leaderboard : leaderboardsByName.values()) { + logoutput.append(String.format("%3s\n", leaderboard.toString())); + } + + // now fix ScoreCorrectionListener setup for LeaderboardGroupMetaLeaderboard instances: + for (Leaderboard leaderboard : leaderboardsByName.values()) { + if (leaderboard instanceof LeaderboardGroupMetaLeaderboard) { + ((LeaderboardGroupMetaLeaderboard) leaderboard) + .registerAsScoreCorrectionChangeForwarderAndRaceColumnListenerOnAllLeaderboards(); + } else if (leaderboard instanceof FlexibleLeaderboard) { + // and re-establish the RaceLogReplicator as listener on FlexibleLeaderboard objects + leaderboard.addRaceColumnListener(raceLogReplicator); + } + } + + logger.info("Reading media library..."); + mediaLibrary.deserialize(ois); + logoutput.append("Received " + mediaLibrary.allTracks().size() + " NEW media tracks\n"); + for (MediaTrack mediatrack : mediaLibrary.allTracks()) { + logoutput.append(String.format("%3s\n", mediatrack.toString())); + } + + // only copy the competitors from the deserialized competitor store; don't use it because it will have set + // a default Mongo object factory + logger.info("Reading competitors..."); + for (Competitor competitor : ((CompetitorStore) ois.readObject()).getCompetitors()) { + DynamicCompetitor dynamicCompetitor = (DynamicCompetitor) competitor; + // the following should actually be redundant because during de-serialization the Competitor objects, + // whose classes implement IsManagedByCache, should already have been got/created from/in the + // competitor store + competitorStore.getOrCreateCompetitor(dynamicCompetitor.getId(), dynamicCompetitor.getName(), + dynamicCompetitor.getColor(), dynamicCompetitor.getEmail(), dynamicCompetitor.getFlagImage(), + dynamicCompetitor.getTeam(), dynamicCompetitor.getBoat(), dynamicCompetitor.getTimeOnTimeFactor(), + dynamicCompetitor.getTimeOnDistanceAllowancePerNauticalMile()); + } + logoutput.append("Received " + competitorStore.size() + " NEW competitors\n"); + + logger.info("Reading device configurations..."); + configurationMap.putAll((DeviceConfigurationMapImpl) ois.readObject()); + logoutput.append("Received " + configurationMap.size() + " NEW configuration entries\n"); + for (DeviceConfigurationMatcher matcher : configurationMap.keySet()) { + logoutput.append(String.format("%3s\n", matcher.toString())); + } + + logger.info("Reading remote sailing server references..."); + for (RemoteSailingServerReference remoteSailingServerReference : (Iterable) ois + .readObject()) { + remoteSailingServerSet.add(remoteSailingServerReference); + logoutput.append("Received remote sailing server reference " + remoteSailingServerReference); + } + + // make sure to initialize listeners correctly + for (Regatta regatta : regattasByName.values()) { + RegattaImpl regattaImpl = (RegattaImpl) regatta; + regattaImpl.initializeSeriesAfterDeserialize(); + regattaImpl.addRaceColumnListener(raceLogReplicator); + } + // re-establish RaceLogResolver references to this RacingEventService in all TrackedRace instances + for (DynamicTrackedRegatta trackedRegatta : regattaTrackingCache.values()) { + trackedRegatta.lockTrackedRacesForRead(); + try { + for (TrackedRace trackedRace : trackedRegatta.getTrackedRaces()) { + ((TrackedRaceImpl) trackedRace).setRaceLogResolver(this); + } + } finally { + trackedRegatta.unlockTrackedRacesAfterRead(); + } + } + logger.info(logoutput.toString()); + } + + @Override + public void clearReplicaState() throws MalformedURLException, IOException, InterruptedException { + logger.info("Clearing all data structures..."); + LockUtil.lockForWrite(regattasByNameLock); + try { + regattasByName.clear(); + } finally { + LockUtil.unlockAfterWrite(regattasByNameLock); + } + regattasObservedForDefaultLeaderboard.clear(); + + if (raceTrackersByRegatta != null && !raceTrackersByRegatta.isEmpty()) { + for (DynamicTrackedRegatta regatta : regattaTrackingCache.values()) { + final Set trackers = raceTrackersByRegatta.get(regatta.getRegatta()); + if (trackers != null) { + for (RaceTracker tracker : trackers) { + tracker.stop(/* preemptive */true); + } + } + } + } + LockUtil.lockForWrite(regattaTrackingCacheLock); + try { + regattaTrackingCache.clear(); + } finally { + LockUtil.unlockAfterWrite(regattaTrackingCacheLock); + } + LockUtil.lockForWrite(raceTrackersByRegattaLock); + try { + raceTrackersByRegatta.clear(); + } finally { + LockUtil.unlockAfterWrite(raceTrackersByRegattaLock); + } + LockUtil.lockForWrite(leaderboardGroupsByNameLock); + try { + leaderboardGroupsByName.clear(); + leaderboardGroupsByID.clear(); + } finally { + LockUtil.unlockAfterWrite(leaderboardGroupsByNameLock); + } + LockUtil.lockForWrite(leaderboardsByNameLock); + try { + leaderboardsByName.clear(); + } finally { + LockUtil.unlockAfterWrite(leaderboardsByNameLock); + } + eventsById.clear(); + mediaLibrary.clear(); + competitorStore.clear(); + remoteSailingServerSet.clear(); + } + + // Used for TESTING only + @Override + public Event addEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, + String venue, boolean isPublic, UUID id) { + Event result = createEventWithoutReplication(eventName, eventDescription, startDate, endDate, venue, isPublic, + id, /* officialWebsiteURL */null, /* sailorsInfoWebsiteURLAsString */null, + /* images */Collections. emptyList(), /* videos */Collections. emptyList()); + replicate(new CreateEvent(eventName, eventDescription, startDate, endDate, venue, isPublic, id, + /* officialWebsiteURLAsString */null, /* sailorsInfoWebsiteURLAsString */null, + /* images */Collections. emptyList(), /* videos */Collections. emptyList())); + return result; + } + + @Override + public void addEventWithoutReplication(Event event) { + addEvent(event); + } + + @Override + public Event createEventWithoutReplication(String eventName, String eventDescription, TimePoint startDate, + TimePoint endDate, String venue, boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, + Iterable images, Iterable videos) { + Event result = new EventImpl(eventName, startDate, endDate, venue, isPublic, id); + addEvent(result); + result.setDescription(eventDescription); + result.setOfficialWebsiteURL(officialWebsiteURL); + result.setImages(images); + result.setVideos(videos); + return result; + } + + private void addEvent(Event result) { + if (eventsById.containsKey(result.getId())) { + throw new IllegalArgumentException("Event with ID " + result.getId() + + " already exists which is pretty surprising..."); + } + eventsById.put(result.getId(), result); + mongoObjectFactory.storeEvent(result); + } + + @Override + public void updateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, + String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, + Iterable images, Iterable videos) { + final Event event = eventsById.get(id); + if (event == null) { + throw new IllegalArgumentException("Sailing event with ID " + id + " does not exist."); + } + event.setName(eventName); + event.setDescription(eventDescription); + event.setStartDate(startDate); + event.setEndDate(endDate); + event.setPublic(isPublic); + event.getVenue().setName(venueName); + List leaderboardGroups = new ArrayList<>(); + for (UUID lgid : leaderboardGroupIds) { + LeaderboardGroup lg = getLeaderboardGroupByID(lgid); + if (lg != null) { + leaderboardGroups.add(lg); + } else { + logger.info("Couldn't find leaderboard group with ID " + lgid + " while updating event " + + event.getName()); + } + } + event.setLeaderboardGroups(leaderboardGroups); + event.setOfficialWebsiteURL(officialWebsiteURL); + event.setSailorsInfoWebsiteURL(sailorsInfoWebsiteURL); + event.setImages(images); + event.setVideos(videos); + // TODO consider use diffutils to compute diff between old and new leaderboard groups list and apply the patch + // to keep changes minimial + mongoObjectFactory.storeEvent(event); + } + + @Override + public void renameEvent(UUID id, String newName) { + final Event toRename = eventsById.get(id); + if (toRename == null) { + throw new IllegalArgumentException("No sailing event with ID " + id + " found."); + } + toRename.setName(newName); + mongoObjectFactory.renameEvent(id, newName); + replicate(new RenameEvent(id, newName)); + } + + @Override + public void removeEvent(UUID id) { + removeEventFromEventsById(id); + mongoObjectFactory.removeEvent(id); + replicate(new RemoveEvent(id)); + } + + protected void removeEventFromEventsById(Serializable id) { + eventsById.remove(id); + } + + @Override + public Regatta getRememberedRegattaForRace(Serializable raceID) { + return persistentRegattasForRaceIDs.get(raceID.toString()); + } + + /** + * Persistently remembers the association of the race with its {@link RaceDefinition#getId()} to the + * regatta with its {@link Regatta#getRegattaIdentifier() identifier} so that the next time + * {@link #getRememberedRegattaForRace(RaceDefinition)} is called with race as argument, + * regatta will be returned. + */ + private void setRegattaForRace(Regatta regatta, RaceDefinition race) { + setRegattaForRace(regatta, race.getId().toString()); + } + + @Override + public void setRegattaForRace(Regatta regatta, String raceIdAsString) { + persistentRegattasForRaceIDs.put(raceIdAsString, regatta); + mongoObjectFactory.storeRegattaForRaceID(raceIdAsString, regatta); + } + + @Override + public CourseArea[] addCourseAreas(UUID eventId, String[] courseAreaNames, UUID[] courseAreaIds) { + final CourseArea[] courseAreas = addCourseAreasWithoutReplication(eventId, courseAreaIds, courseAreaNames); + replicate(new AddCourseAreas(eventId, courseAreaNames, courseAreaIds)); + return courseAreas; + } + + @Override + public CourseArea[] addCourseAreasWithoutReplication(UUID eventId, UUID[] courseAreaIds, String[] courseAreaNames) { + final CourseArea[] result = new CourseArea[courseAreaNames.length]; + for (int i=0; i mediaTracks) { + mediaLibrary.addMediaTracks(mediaTracks); + } + + @Override + public void mediaTrackTitleChanged(MediaTrack mediaTrack) { + mediaDB.updateTitle(mediaTrack.dbId, mediaTrack.title); + mediaLibrary.titleChanged(mediaTrack); + replicate(new UpdateMediaTrackTitleOperation(mediaTrack)); + } + + @Override + public void mediaTrackUrlChanged(MediaTrack mediaTrack) { + mediaDB.updateUrl(mediaTrack.dbId, mediaTrack.url); + mediaLibrary.urlChanged(mediaTrack); + replicate(new UpdateMediaTrackUrlOperation(mediaTrack)); + } + + @Override + public void mediaTrackStartTimeChanged(MediaTrack mediaTrack) { + mediaDB.updateStartTime(mediaTrack.dbId, mediaTrack.startTime); + mediaLibrary.startTimeChanged(mediaTrack); + replicate(new UpdateMediaTrackStartTimeOperation(mediaTrack)); + } + + @Override + public void mediaTrackDurationChanged(MediaTrack mediaTrack) { + mediaDB.updateDuration(mediaTrack.dbId, mediaTrack.duration); + mediaLibrary.durationChanged(mediaTrack); + replicate(new UpdateMediaTrackDurationOperation(mediaTrack)); + } + + @Override + public void mediaTrackAssignedRacesChanged(MediaTrack mediaTrack) { + mediaDB.updateRace(mediaTrack.dbId, mediaTrack.assignedRaces); + mediaLibrary.assignedRacesChanged(mediaTrack); + replicate(new UpdateMediaTrackRacesOperation(mediaTrack)); + + } + + @Override + public void mediaTrackDeleted(MediaTrack mediaTrack) { + mediaDB.deleteMediaTrack(mediaTrack.dbId); + mediaLibrary.deleteMediaTrack(mediaTrack); + replicate(new RemoveMediaTrackOperation(mediaTrack)); + } + + @Override + public void mediaTracksImported(Collection mediaTracksToImport, boolean override) { + for (MediaTrack trackToImport : mediaTracksToImport) { + MediaTrack existingTrack = mediaLibrary.lookupMediaTrack(trackToImport); + if (existingTrack == null) { + mediaDB.insertMediaTrackWithId(trackToImport.dbId, trackToImport.title, trackToImport.url, + trackToImport.startTime, trackToImport.duration, trackToImport.mimeType, + trackToImport.assignedRaces); + mediaTrackAdded(trackToImport); + } else if (override) { + + // Using fine-grained update methods. + // Rationale: Changes on more than one track property are rare + // and don't justify the introduction of a new set + // of methods (including replication). + if (!Util.equalsWithNull(existingTrack.title, trackToImport.title)) { + mediaTrackTitleChanged(trackToImport); + } + if (!Util.equalsWithNull(existingTrack.url, trackToImport.url)) { + mediaTrackUrlChanged(trackToImport); + } + if (!Util.equalsWithNull(existingTrack.startTime, trackToImport.startTime)) { + mediaTrackStartTimeChanged(trackToImport); + } + if (!Util.equalsWithNull(existingTrack.duration, trackToImport.duration)) { + mediaTrackDurationChanged(trackToImport); + } + if (!Util.equalsWithNull(existingTrack.assignedRaces, trackToImport.assignedRaces)) { + mediaTrackAssignedRacesChanged(trackToImport); + } + } + } + } + + @Override + public Collection getMediaTracksForRace(RegattaAndRaceIdentifier regattaAndRaceIdentifier) { + return mediaLibrary.findMediaTracksForRace(regattaAndRaceIdentifier); + } + + @Override + public Collection getMediaTracksInTimeRange(RegattaAndRaceIdentifier regattaAndRaceIdentifier) { + TrackedRace trackedRace = getExistingTrackedRace(regattaAndRaceIdentifier); + if (trackedRace != null) { + if (trackedRace.isLive(MillisecondsTimePoint.now())) { + return mediaLibrary.findLiveMediaTracks(); + } else { + TimePoint raceStart = trackedRace.getStartOfRace() == null ? trackedRace.getStartOfTracking() + : trackedRace.getStartOfRace(); + TimePoint raceEnd = trackedRace.getEndOfRace() == null ? trackedRace.getEndOfTracking() : trackedRace + .getEndOfRace(); + return mediaLibrary.findMediaTracksInTimeRange(raceStart, raceEnd); + } + } else { + return Collections.emptyList(); + } + } + + @Override + public Collection getAllMediaTracks() { + return mediaLibrary.allTracks(); + } + + public String toString() { + return "RacingEventService: " + this.hashCode() + " Build: " + ServerInfo.getBuildVersion(); + } + + @Override + public void reloadRaceLog(String leaderboardName, String raceColumnName, String fleetName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + Fleet fleetImpl = raceColumn.getFleetByName(fleetName); + RaceLog racelog = raceColumn.getRaceLog(fleetImpl); + if (racelog != null) { + raceColumn.reloadRaceLog(fleetImpl); + logger.info("Reloaded race log for fleet " + fleetImpl + " for race column " + raceColumn.getName() + + " for leaderboard " + leaderboard.getName()); + } + } + } + } + + @Override + public ConcurrentHashMap getPersistentRegattasForRaceIDs() { + return persistentRegattasForRaceIDs; + } + + @Override + public WindStore getWindStore() { + return windStore; + } + + @Override + public DeviceConfiguration getDeviceConfiguration(DeviceConfigurationIdentifier identifier) { + return configurationMap.getByMatch(identifier); + } + + @Override + public void createOrUpdateDeviceConfiguration(DeviceConfigurationMatcher matcher, DeviceConfiguration configuration) { + configurationMap.put(matcher, configuration); + mongoObjectFactory.storeDeviceConfiguration(matcher, configuration); + replicate(new CreateOrUpdateDeviceConfiguration(matcher, configuration)); + } + + @Override + public void removeDeviceConfiguration(DeviceConfigurationMatcher matcher) { + configurationMap.remove(matcher); + mongoObjectFactory.removeDeviceConfiguration(matcher); + replicate(new RemoveDeviceConfiguration(matcher)); + } + + @Override + public Map getAllDeviceConfigurations() { + return new HashMap(configurationMap); + } + + @Override + public TimePoint setStartTimeAndProcedure(String leaderboardName, String raceColumnName, String fleetName, + String authorName, int authorPriority, int passId, TimePoint logicalTimePoint, TimePoint startTime, + RacingProcedureType racingProcedure) { + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + final TimePoint result; + if (leaderboard instanceof HasRegattaLike && raceLog != null) { + RaceState state = RaceStateImpl.create(/* race log resolver */ this, raceLog, new LogEventAuthorImpl(authorName, authorPriority)); + if (passId > raceLog.getCurrentPassId()) { + state.setAdvancePass(logicalTimePoint); + } + state.setRacingProcedure(logicalTimePoint, racingProcedure); + state.forceNewStartTime(logicalTimePoint, startTime); + result = state.getStartTime(); + } else { + result = null; + } + return result; + } + + public RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + Fleet fleetImpl = raceColumn.getFleetByName(fleetName); + return raceColumn.getRaceLog(fleetImpl); + } + } + return null; + } + + @Override + public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( + String leaderboardName, String raceColumnName, String fleetName) { + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + final Triple result; + if (leaderboard instanceof HasRegattaLike && raceLog != null) { + ReadonlyRaceState state = ReadonlyRaceStateImpl.create(/* race log resolver */ this, raceLog); + result = new com.sap.sse.common.Util.Triple(state.getStartTime(), + raceLog.getCurrentPassId(), state.getRacingProcedure().getType()); + } else { + result = null; + } + return result; + } + + private Iterable getWindTrackerFactories() { + final Set result; + if (bundleContext == null) { + result = Collections.singleton((WindTrackerFactory) ExpeditionWindTrackerFactory.getInstance()); + } else { + ServiceTracker tracker = new ServiceTracker( + bundleContext, WindTrackerFactory.class.getName(), null); + tracker.open(); + result = new HashSet<>(); + for (WindTrackerFactory factory : tracker.getServices(new WindTrackerFactory[0])) { + result.add(factory); + } + } + return result; + } + + @Override + public GPSFixStore getGPSFixStore() { + return gpsFixStore; + } + + @Override + public RaceTracker getRaceTrackerById(Object id) { + return raceTrackersByID.get(id); + } + + @Override + public AbstractLogEventAuthor getServerAuthor() { + return raceLogEventAuthorForServer; + } + + @Override + public CompetitorStore getCompetitorStore() { + return competitorStore; + } + + @Override + public TypeBasedServiceFinderFactory getTypeBasedServiceFinderFactory() { + return serviceFinderFactory; + } + + @Override + public DataImportLockWithProgress getDataImportLock() { + return dataImportLock; + } + + @Override + public DataImportProgress createOrUpdateDataImportProgressWithReplication(UUID importOperationId, + double overallProgressPct, String subProgressName, double subProgressPct) { + // Create/Update locally + DataImportProgress progress = createOrUpdateDataImportProgressWithoutReplication(importOperationId, + overallProgressPct, subProgressName, subProgressPct); + // Create/Update on replicas + replicate(new CreateOrUpdateDataImportProgress(importOperationId, overallProgressPct, subProgressName, + subProgressPct)); + return progress; + } + + @Override + public DataImportProgress createOrUpdateDataImportProgressWithoutReplication(UUID importOperationId, + double overallProgressPct, String subProgressName, double subProgressPct) { + DataImportProgress progress = dataImportLock.getProgress(importOperationId); + boolean newObject = false; + if (progress == null) { + progress = new DataImportProgressImpl(importOperationId); + newObject = true; + } + progress.setOverAllProgressPct(overallProgressPct); + progress.setNameOfCurrentSubProgress(subProgressName); + progress.setCurrentSubProgressPct(subProgressPct); + if (newObject) { + dataImportLock.addProgress(importOperationId, progress); + } + return progress; + } + + @Override + public void setDataImportFailedWithoutReplication(UUID importOperationId, String errorMessage) { + DataImportProgress progress = dataImportLock.getProgress(importOperationId); + if (progress != null) { + progress.setFailed(); + progress.setErrorMessage(errorMessage); + } + } + + @Override + public void setDataImportFailedWithReplication(UUID importOperationId, String errorMessage) { + setDataImportFailedWithoutReplication(importOperationId, errorMessage); + replicate(new DataImportFailed(importOperationId, errorMessage)); + } + + @Override + public void setDataImportDeleteProgressFromMapTimerWithReplication(UUID importOperationId) { + setDataImportDeleteProgressFromMapTimerWithoutReplication(importOperationId); + replicate(new SetDataImportDeleteProgressFromMapTimer(importOperationId)); + } + + @Override + public void setDataImportDeleteProgressFromMapTimerWithoutReplication(UUID importOperationId) { + dataImportLock.setDeleteFromMapTimer(importOperationId); + } + + @Override + public Result search(KeywordQuery query) { + long start = System.currentTimeMillis(); + logger.info("Searching local server for " + query); + Result result = new RegattaByKeywordSearchService().search(this, query); + logger.fine("Search for " + query + " took " + (System.currentTimeMillis() - start) + "ms"); + return result; + } + + @Override + public Result searchRemotely(String remoteServerReferenceName, KeywordQuery query) { + long start = System.currentTimeMillis(); + ResultImpl result = null; + RemoteSailingServerReference remoteRef = remoteSailingServerSet + .getServerReferenceByName(remoteServerReferenceName); + if (remoteRef == null) { + result = null; + } else { + BufferedReader bufferedReader = null; + try { + try { + final URL eventsURL = new URL(remoteRef.getURL(), "sailingserver/api/v1/search?q=" + + URLEncoder.encode(query.toString(), "UTF-8")); + logger.info("Searching remote server " + remoteRef + " for " + query); + URLConnection urlConnection = eventsURL.openConnection(); + urlConnection.connect(); + bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8")); + JSONParser parser = new JSONParser(); + Object eventsAsObject = parser.parse(bufferedReader); + final LeaderboardGroupBaseJsonDeserializer leaderboardGroupBaseJsonDeserializer = new LeaderboardGroupBaseJsonDeserializer(); + LeaderboardSearchResultBaseJsonDeserializer deserializer = new LeaderboardSearchResultBaseJsonDeserializer( + new EventBaseJsonDeserializer(new VenueJsonDeserializer(new CourseAreaJsonDeserializer( + DomainFactory.INSTANCE)), leaderboardGroupBaseJsonDeserializer), + leaderboardGroupBaseJsonDeserializer); + result = new ResultImpl(query, + new LeaderboardSearchResultBaseRanker()); + JSONArray hitsAsJsonArray = (JSONArray) eventsAsObject; + for (Object hitAsObject : hitsAsJsonArray) { + JSONObject hitAsJson = (JSONObject) hitAsObject; + LeaderboardSearchResultBase hit = deserializer.deserialize(hitAsJson); + result.addHit(hit); + } + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + } catch (IOException | ParseException e) { + logger.log(Level.INFO, + "Exception trying to fetch events from remote server " + remoteRef + ": " + e.getMessage(), e); + } + } + logger.fine("Remote search on " + remoteRef + " for " + query + " took " + (System.currentTimeMillis() - start) + + "ms"); + return result; + } + + @Override + public ReplicationMasterDescriptor getMasterDescriptor() { + return replicatingFromMaster; + } + + @Override + public void startedReplicatingFrom(ReplicationMasterDescriptor master) { + this.replicatingFromMaster = master; + } + + @Override + public void stoppedReplicatingFrom(ReplicationMasterDescriptor master) { + this.replicatingFromMaster = null; + } + + @Override + public void addOperationSentToMasterForReplication( + OperationWithResultWithIdWrapper operationWithResultWithIdWrapper) { + this.operationsSentToMasterForReplication.add(operationWithResultWithIdWrapper); + } + + @Override + public boolean hasSentOperationToMaster(OperationWithResult operation) { + return this.operationsSentToMasterForReplication.remove(operation); + } + + @Override + public FileStorageManagementService getFileStorageManagementService() { + ServiceReference ref = bundleContext + .getServiceReference(FileStorageManagementService.class); + if (ref == null) { + logger.warning("No file storage management service registered"); + return null; + } + return bundleContext.getService(ref); + } + + public void addMasterDataClassLoader(ClassLoader classLoader) { + masterDataClassLoaders.add(classLoader); + } + + public void removeMasterDataClassLoader(ClassLoader classLoader) { + masterDataClassLoaders.remove(classLoader); + } + + @Override + public ClassLoader getCombinedMasterDataClassLoader() { + JoinedClassLoader joinedClassLoader = new JoinedClassLoader(masterDataClassLoaders); + return joinedClassLoader; + } + + public void setPolarDataService(PolarDataService service) { + if (this.polarDataService == null && service != null) { + polarDataService = service; + polarDataService.registerDomainFactory(baseDomainFactory); + setPolarDataServiceOnAllTrackedRaces(service); + } + } + + private void setPolarDataServiceOnAllTrackedRaces(PolarDataService service) { + Iterable allRegattas = getAllRegattas(); + for (Regatta regatta : allRegattas) { + DynamicTrackedRegatta trackedRegatta = getTrackedRegatta(regatta); + if (trackedRegatta != null) { + trackedRegatta.lockTrackedRacesForRead(); + try { + Iterable trackedRaces = trackedRegatta.getTrackedRaces(); + for (TrackedRace trackedRace : trackedRaces) { + trackedRace.setPolarDataService(service); + service.insertExistingFixes(trackedRace); + } + } finally { + trackedRegatta.unlockTrackedRacesAfterRead(); + } + } + } + } + + public void unsetPolarDataService(PolarDataService service) { + if (polarDataService == service) { + polarDataService.unregisterDomainFactory(baseDomainFactory); + polarDataService = null; + setPolarDataService(null); + } + } + + @Override + public Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint) { + final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); + final List result = new ArrayList<>(); + final Map windwardDistanceSailedPerCompetitor = new HashMap<>(); + for (final Competitor competitor : trackedRace.getRace().getCompetitors()) { + result.add(competitor); + final CompetitorRankingInfo competitorRankingInfo = rankingInfo.getCompetitorRankingInfo().apply(competitor); + windwardDistanceSailedPerCompetitor.put(competitor, competitorRankingInfo == null ? null : competitorRankingInfo.getWindwardDistanceSailed()); + } + final Comparator durationComparatorNullsLast = Comparator.nullsLast(Comparator.naturalOrder()); + result.sort((c1, c2) -> durationComparatorNullsLast.compare(windwardDistanceSailedPerCompetitor.get(c2), + windwardDistanceSailedPerCompetitor.get(c1))); + return result; + } + + /** + * A {@link SimpleRaceLogIdentifier} in particular has a {@link SimpleRaceLogIdentifier#getRegattaLikeParentName()} + * which identifies either a regatta by name or a flexible leaderboard by name. Here is why this can luckily be + * resolved unanimously: A regatta leaderboard always uses as its name the regatta name (see + * {@link RegattaImpl#getName()}). Trying to {@link RegattaLeaderboardImpl#setName(String) set} the regatta leaderboard's + * name can only update its {@link Leaderboard#getDisplayName() display name}. Therefore, regatta leaderboards are always + * keyed in {@link #leaderboardsByName} by their regatta's name. Thus, no flexible leaderboard can have a regatta's name + * as its name, and therefore leaderboard names and regatta names are unitedly unique. + */ + @Override + public RaceLog resolve(SimpleRaceLogIdentifier identifier) { + final RaceLog result; + final IsRegattaLike regattaLike; + final Regatta regatta = regattasByName.get(identifier.getRegattaLikeParentName()); + if (regatta != null) { + regattaLike = regatta; + } else { + final Leaderboard leaderboard = leaderboardsByName.get(identifier.getRegattaLikeParentName()); + if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) { + regattaLike = (FlexibleLeaderboard) leaderboard; + } else { + regattaLike = null; + } + } + if (regattaLike != null) { + final RaceColumn raceColumn = regattaLike.getRaceColumnByName(identifier.getRaceColumnName()); + if (raceColumn != null) { + final Fleet fleet = raceColumn.getFleetByName(identifier.getFleetName()); + if (fleet != null) { + result = raceColumn.getRaceLog(fleet); + } else { + result = null; + } + } else { + result = null; + } + } else { + result = null; + } + return result; + } +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java index 72aa4fce917..26212aaf857 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RegattaByKeywordSearchService.java @@ -1,14 +1,15 @@ package com.sap.sailing.server.impl; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CourseArea; import com.sap.sailing.domain.base.Event; import com.sap.sailing.domain.base.LeaderboardSearchResult; import com.sap.sailing.domain.base.impl.LeaderboardSearchResultImpl; @@ -34,8 +35,32 @@ import com.sap.sse.common.search.ResultImpl; public class RegattaByKeywordSearchService { Result search(final RacingEventService racingEventService, KeywordQuery query) { ResultImpl result = new ResultImpl<>(query, new LeaderboardSearchResultRanker(racingEventService)); - final Map eventForLeaderboard = new HashMap<>(); + final Map> eventsForLeaderboardGroup = new HashMap<>(); final Map> leaderboardGroupsForLeaderboard = new HashMap<>(); + final Map eventForCourseArea = new HashMap<>(); + final Map> stringsForEvent = new HashMap<>(); + final Map> stringsForLeaderboardGroup = new HashMap<>(); + for (final Event event : racingEventService.getAllEvents()) { + final Set s4e = new HashSet<>(); + s4e.add(event.getName()); + s4e.add(event.getVenue().getName()); + stringsForEvent.put(event, s4e); + for (final LeaderboardGroup leaderboardGroup : event.getLeaderboardGroups()) { + Util.add(eventsForLeaderboardGroup, leaderboardGroup, event); + } + for (final CourseArea courseArea : event.getVenue().getCourseAreas()) { + eventForCourseArea.put(courseArea, event); + } + } + for (final LeaderboardGroup leaderboardGroup : racingEventService.getLeaderboardGroups().values()) { + final Set s4lg = new HashSet<>(); + s4lg.add(leaderboardGroup.getName()); + s4lg.add(leaderboardGroup.getDescription()); + stringsForLeaderboardGroup.put(leaderboardGroup, s4lg); + for (final Leaderboard leaderboard : leaderboardGroup.getLeaderboards()) { + Util.add(leaderboardGroupsForLeaderboard, leaderboard, leaderboardGroup); + } + } AbstractListFilter leaderboardFilter = new AbstractListFilter() { @Override public Iterable getStrings(Leaderboard leaderboard) { @@ -51,58 +76,89 @@ public class RegattaByKeywordSearchService { leaderboardStrings.add(competitorDisplayName); } } - final Iterable leaderboardGroupsHostingLeaderboard = getLeaderboardGroupsHostingLeaderboard( - leaderboard, racingEventService); - for (LeaderboardGroup leaderboardGroup : leaderboardGroupsHostingLeaderboard) { - leaderboardStrings.add(leaderboardGroup.getName()); - leaderboardStrings.add(leaderboardGroup.getDescription()); - Set leaderboardGroups = leaderboardGroupsForLeaderboard.get(leaderboard); - if (leaderboardGroups == null) { - leaderboardGroups = new HashSet<>(); - leaderboardGroupsForLeaderboard.put(leaderboard, leaderboardGroups); + final Iterable leaderboardGroupsHostingLeaderboard = leaderboardGroupsForLeaderboard.get(leaderboard); + if (leaderboardGroupsHostingLeaderboard != null) { + for (LeaderboardGroup leaderboardGroup : leaderboardGroupsHostingLeaderboard) { + leaderboardStrings.addAll(stringsForLeaderboardGroup.get(leaderboardGroup)); + final Set eventsForLG = filterEventsForLeaderboard(leaderboard, leaderboardGroup, eventsForLeaderboardGroup.get(leaderboardGroup)); + if (eventsForLG != null) { + for (final Event event : eventsForLG) { + leaderboardStrings.addAll(stringsForEvent.get(event)); + } + } } - leaderboardGroups.add(leaderboardGroup); } - for (Event event : getEventsHostingLeaderboard(leaderboard, racingEventService, leaderboardGroupsHostingLeaderboard)) { - leaderboardStrings.add(event.getName()); - leaderboardStrings.add(event.getVenue().getName()); - eventForLeaderboard.put(leaderboard, event); + final Event eventByDefaultCourseArea = eventForCourseArea.get(leaderboard.getDefaultCourseArea()); + if (eventByDefaultCourseArea != null) { + leaderboardStrings.addAll(stringsForEvent.get(eventByDefaultCourseArea)); } return leaderboardStrings; } }; for (Leaderboard matchingLeaderboard : leaderboardFilter.applyFilter(query.getKeywords(), racingEventService.getLeaderboards().values())) { - result.addHit(new LeaderboardSearchResultImpl(matchingLeaderboard, eventForLeaderboard.get(matchingLeaderboard), leaderboardGroupsForLeaderboard.get(matchingLeaderboard))); + result.addHit(new LeaderboardSearchResultImpl(matchingLeaderboard, + getEventsForLeaderboard(matchingLeaderboard, leaderboardGroupsForLeaderboard, + eventsForLeaderboardGroup, eventForCourseArea), leaderboardGroupsForLeaderboard + .get(matchingLeaderboard))); } return result; } - - private Iterable getLeaderboardGroupsHostingLeaderboard(Leaderboard leaderboard, RacingEventService racingEventService) { - Set result = new LinkedHashSet<>(); - for (LeaderboardGroup leaderboardGroup : racingEventService.getLeaderboardGroups().values()) { - for (Leaderboard lgLeaderboard : leaderboardGroup.getLeaderboards()) { - if (lgLeaderboard == leaderboard) { - result.add(leaderboardGroup); - } - } - } - return result; - } - - private Iterable getEventsHostingLeaderboard(Leaderboard leaderboard, RacingEventService racingEventService, - Iterable leaderboardGroupsHostingLeaderboard) { - Set result = new LinkedHashSet<>(); - for (Event event : racingEventService.getAllEvents()) { - if (Util.contains(event.getVenue().getCourseAreas(), leaderboard.getDefaultCourseArea())) { - result.add(event); - } else { - for (LeaderboardGroup leaderboardGroupHostingRegatta : leaderboardGroupsHostingLeaderboard) { - if (Util.contains(event.getLeaderboardGroups(), leaderboardGroupHostingRegatta)) { - result.add(event); + + /** + * For leaderboards that are part of a series, there used to be search results that linked to the leaderboard in + * combination with one random event of that series. It was the wrong event for all leaderboards except one of a + * series. In bug3348 a change was made to show all events associated to a leaderboard in the search results. This + * lead to an "explosion of results" as there were potentially n results referencing n events instead of each result + * only referencing the associated event. + * + * This filters the events to be associated to a leaderboard. If the leaderboardGroup has a OverallLeaderboard (in + * case of a series), there is a special matching to find the right event. If a leaderboard has a defaultCourseArea, + * the event hosting this CourseArea is the right one. If this reference isn't given or the CourseArea doesn't + * belong to an event of the series, the fallback behavior is causing all events to be returned. + * + * This doesn't affect any leaderboard's event set if the leaderboard isn't part of a series. + * + * @param leaderboard the leaderboard to get the matching events for + * @param leaderboardGroup the LeaderboardGroup hosting the leaderboard + * @param events all events hosting the LeaderboardGroup + * @return the best matching events for the given Leaderboard/LeaderboardGroup + */ + private Set filterEventsForLeaderboard(Leaderboard leaderboard, LeaderboardGroup leaderboardGroup, Set events) { + final Set result; + if (leaderboardGroup.hasOverallLeaderboard()) { + CourseArea defaultCourseArea = leaderboard.getDefaultCourseArea(); + Set preResult = null; + if (defaultCourseArea != null) { + for (Event event : events) { + if (Util.contains(event.getVenue().getCourseAreas(), defaultCourseArea)) { + preResult = Collections.singleton(event); break; } } } + result = preResult; + } else { + result = events; + } + return result; + } + + private Set getEventsForLeaderboard(Leaderboard matchingLeaderboard, + Map> leaderboardGroupsForLeaderboard, + Map> eventsForLeaderboardGroup, Map eventForCourseArea) { + final Set result = new HashSet<>(); + final Set lgs = leaderboardGroupsForLeaderboard.get(matchingLeaderboard); + if (lgs != null) { + for (final LeaderboardGroup lg : lgs) { + final Set eventsForLG = filterEventsForLeaderboard(matchingLeaderboard, lg, eventsForLeaderboardGroup.get(lg)); + if (eventsForLG != null) { + result.addAll(eventsForLG); + } + } + } + final Event eventByCourseArea = eventForCourseArea.get(matchingLeaderboard.getDefaultCourseArea()); + if (eventByCourseArea != null) { + result.add(eventByCourseArea); } return result; } diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/CreateEvent.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/CreateEvent.java index 0eaa2c1dd2b..1dcb15b294d 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/CreateEvent.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/CreateEvent.java @@ -1,70 +1,70 @@ -package com.sap.sailing.server.operationaltransformation; - -import java.net.URL; -import java.util.UUID; - -import com.sap.sailing.domain.base.Event; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.RacingEventServiceOperation; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; - -/** - * Creates an {@link Event} in the server, with a new venue and an empty course area list. - * See the {@link AddCourseAreas} operation for adding course areas to the event's venue. - * - * @author Axel Uhl (d043530) - * - */ -public class CreateEvent extends AbstractEventOperation { - private static final long serialVersionUID = 308389324918359960L; - private final String venue; - private final TimePoint startDate; - private final TimePoint endDate; - private final boolean isPublic; - private final String eventName; - private final String eventDescription; - private final Iterable images; - private final Iterable videos; - private final URL officialWebsiteURL; - private final URL sailorsInfoWebsiteURL; - - public CreateEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venue, - boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, Iterable images, Iterable videos) { - super(id); - this.eventName = eventName; - this.eventDescription = eventDescription; - this.startDate = startDate; - this.endDate = endDate; - this.venue = venue; - this.isPublic = isPublic; - this.officialWebsiteURL = officialWebsiteURL; - this.sailorsInfoWebsiteURL = sailorsInfoWebsiteURL; - this.images = images; - this.videos = videos; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - - protected String getEventName() { - return eventName; - } - - @Override - public Event internalApplyTo(RacingEventService toState) { - return toState.createEventWithoutReplication(getEventName(), eventDescription, startDate, endDate, venue, isPublic, - getId(), officialWebsiteURL, sailorsInfoWebsiteURL, images, videos); - } - -} +package com.sap.sailing.server.operationaltransformation; + +import java.net.URL; +import java.util.UUID; + +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.TimePoint; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +/** + * Creates an {@link Event} in the server, with a new venue and an empty course area list. + * See the {@link AddCourseAreas} operation for adding course areas to the event's venue. + * + * @author Axel Uhl (d043530) + * + */ +public class CreateEvent extends AbstractEventOperation { + private static final long serialVersionUID = 308389324918359960L; + private final String venue; + private final TimePoint startDate; + private final TimePoint endDate; + private final boolean isPublic; + private final String eventName; + private final String eventDescription; + private final Iterable images; + private final Iterable videos; + private final URL officialWebsiteURL; + private final URL sailorsInfoWebsiteURL; + + public CreateEvent(String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, String venue, + boolean isPublic, UUID id, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, Iterable images, Iterable videos) { + super(id); + this.eventName = eventName; + this.eventDescription = eventDescription; + this.startDate = startDate; + this.endDate = endDate; + this.venue = venue; + this.isPublic = isPublic; + this.officialWebsiteURL = officialWebsiteURL; + this.sailorsInfoWebsiteURL = sailorsInfoWebsiteURL; + this.images = images; + this.videos = videos; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + + protected String getEventName() { + return eventName; + } + + @Override + public Event internalApplyTo(RacingEventService toState) { + return toState.createEventWithoutReplication(getEventName(), eventDescription, startDate, endDate, venue, isPublic, + getId(), officialWebsiteURL, sailorsInfoWebsiteURL, images, videos); + } + +} diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEvent.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEvent.java index bc3d64901a6..eb9c60ca2a0 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEvent.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEvent.java @@ -1,61 +1,61 @@ -package com.sap.sailing.server.operationaltransformation; - -import java.net.URL; -import java.util.UUID; - -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.RacingEventServiceOperation; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.media.ImageDescriptor; -import com.sap.sse.common.media.VideoDescriptor; - -public class UpdateEvent extends AbstractEventOperation { - private static final long serialVersionUID = -8271559266421161532L; - private final String venueName; - private final TimePoint startDate; - private final TimePoint endDate; - private final boolean isPublic; - private final Iterable leaderboardGroupIds; - private final String eventName; - private final String eventDescription; - private final URL officialWebsiteURL; - private final URL sailorsInfoWebsiteURL; - private final Iterable images; - private final Iterable videos; - - public UpdateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, - String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, - Iterable images, Iterable videos) { - super(id); - this.eventName = eventName; - this.eventDescription = eventDescription; - this.startDate = startDate; - this.endDate = endDate; - this.venueName = venueName; - this.isPublic = isPublic; - this.leaderboardGroupIds = leaderboardGroupIds; - this.officialWebsiteURL = officialWebsiteURL; - this.sailorsInfoWebsiteURL = sailorsInfoWebsiteURL; - this.images = images; - this.videos = videos; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public Void internalApplyTo(RacingEventService toState) { - toState.updateEvent(getId(), eventName, eventDescription, startDate, endDate, venueName, isPublic, - leaderboardGroupIds, officialWebsiteURL, sailorsInfoWebsiteURL, images, videos); - return null; - } -} +package com.sap.sailing.server.operationaltransformation; + +import java.net.URL; +import java.util.UUID; + +import com.sap.sailing.server.RacingEventService; +import com.sap.sailing.server.RacingEventServiceOperation; +import com.sap.sse.common.TimePoint; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; + +public class UpdateEvent extends AbstractEventOperation { + private static final long serialVersionUID = -8271559266421161532L; + private final String venueName; + private final TimePoint startDate; + private final TimePoint endDate; + private final boolean isPublic; + private final Iterable leaderboardGroupIds; + private final String eventName; + private final String eventDescription; + private final URL officialWebsiteURL; + private final URL sailorsInfoWebsiteURL; + private final Iterable images; + private final Iterable videos; + + public UpdateEvent(UUID id, String eventName, String eventDescription, TimePoint startDate, TimePoint endDate, + String venueName, boolean isPublic, Iterable leaderboardGroupIds, URL officialWebsiteURL, URL sailorsInfoWebsiteURL, + Iterable images, Iterable videos) { + super(id); + this.eventName = eventName; + this.eventDescription = eventDescription; + this.startDate = startDate; + this.endDate = endDate; + this.venueName = venueName; + this.isPublic = isPublic; + this.leaderboardGroupIds = leaderboardGroupIds; + this.officialWebsiteURL = officialWebsiteURL; + this.sailorsInfoWebsiteURL = sailorsInfoWebsiteURL; + this.images = images; + this.videos = videos; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Void internalApplyTo(RacingEventService toState) { + toState.updateEvent(getId(), eventName, eventDescription, startDate, endDate, venueName, isPublic, + leaderboardGroupIds, officialWebsiteURL, sailorsInfoWebsiteURL, images, videos); + return null; + } +} diff --git a/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml b/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml index 16263fd6bd7..718b7ee89f3 100644 --- a/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml +++ b/java/com.sap.sailing.targetplatform.base/features/target-jackson/feature.xml @@ -62,14 +62,14 @@ unpack="false"/> - - + + @@ -82,9 +82,9 @@ - + - + @@ -95,6 +95,7 @@ + @@ -239,7 +240,6 @@ - diff --git a/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh b/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh index 0ef8633fcd8..1e0fa8e0a30 100755 --- a/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh +++ b/java/com.sap.sailing.targetplatform/scripts/uploadRepositoryToServer.sh @@ -22,8 +22,7 @@ echo "Uploading local repository to $REPO_HOME/sailing" scp -r ../../com.sap.sailing.targetplatform.base/target/repository $USER@$SERVER:$REPO_HOME/sailing echo "Making readable for everyone..." -ssh $USER@$SERVER "chmod -R a+r $REPO_HOME/sailing" -ssh $USER@$SERVER "chmod -R a+x $REPO_HOME/sailing" +ssh $USER@$SERVER "chmod -R 775 . $REPO_HOME/sailing" echo "Remote files now available:" ssh $USER@$SERVER "ls -lah $REPO_HOME/sailing" diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index cba0b1a3226..912a3371caf 100644 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -25,6 +25,26 @@

    Release Notes - Administration Console

    +

    November 2015

    +
      +
    • Adding a competitor to a leaderboard or a regatta pre-sets the competitor's boat class + according to the leaderboard's / regatta's boat class. +
    • +
    • When done with creating a regatta, the user can have the corresponding regatta leaderboard + created with a simple click instead of having to navigate to the "Leaderboards" tab. +
    • +
    • Trim leaderboard and leaderboard group names during creation, removing leading and trailing + blanks. These names can occur in URLs, and trailing blanks in particular may be trimmed, + causing the objects to not be found. +
    • +
    +

    October 2015

    +
      +
    • The "RaceLog Tracking" panel was renamed to the more intuitive "Smartphone Tracking". +
    • +
    • Competitor and course information can now be copied independently from one race to another within a Smartphone-tracked leaderboard. +
    • +

    September 2015

    • A new scoring scheme for elimination rounds has been added. It will first be used diff --git a/java/com.sap.sse.common.test/src/com/sap/sse/common/test/GetDominantObjectTest.java b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/GetDominantObjectTest.java new file mode 100644 index 00000000000..d519f6338a6 --- /dev/null +++ b/java/com.sap.sse.common.test/src/com/sap/sse/common/test/GetDominantObjectTest.java @@ -0,0 +1,54 @@ +package com.sap.sse.common.test; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +import com.sap.sse.common.Util; + +public class GetDominantObjectTest { + + @Test + public void testNullCollection() { + Assert.assertNull(Util.getDominantObject(null)); + } + + @Test + public void testEmptyCollection() { + Iterable objects = new ArrayList<>(); + Assert.assertEquals(null, Util.getDominantObject(objects)); + } + + @Test + public void testCollectionWithOneObject() { + List objectCollection = new ArrayList<>(); + String dominant = "Test"; + objectCollection.add(dominant); + Assert.assertEquals(dominant, Util.getDominantObject(objectCollection)); + } + + @Test + public void testCollectionWithTheSameCount() { + List objectCollection = new ArrayList<>(); + String dominant = "Test"; + String dominantTwo = "Test2"; + objectCollection.add(dominant); + objectCollection.add(dominantTwo); + String result = Util.getDominantObject(objectCollection); + if(!(result == dominant || result == dominantTwo)) { + Assert.assertEquals(dominant, result); + } + } + + @Test + public void testCollectionWithMoreThenOneObject() { + List objectCollection = new ArrayList<>(); + String dominant = "Test"; + objectCollection.add("not Dominant"); + objectCollection.add(dominant); + objectCollection.add(dominant); + Assert.assertEquals(dominant, Util.getDominantObject(objectCollection)); + } +} diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java old mode 100755 new mode 100644 index 3c1d8d300fc..624d09fbc0b --- a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java @@ -3,6 +3,7 @@ package com.sap.sse.common; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -21,114 +22,120 @@ public class Util { private transient int hashCode; - @SuppressWarnings("unused") // required for some serialization frameworks such as GWT RPC - private Pair() {} - - public Pair( A a, B b ) { + @SuppressWarnings("unused") + // required for some serialization frameworks such as GWT RPC + private Pair() { + } + + public Pair(A a, B b) { this.a = a; this.b = b; hashCode = 0; } - - public A getA( ) { + + public A getA() { return a; } - - public B getB( ) { + + public B getB() { return b; } - + @Override - public int hashCode( ) { - if ( hashCode == 0 ) { + public int hashCode() { + if (hashCode == 0) { hashCode = 17; - hashCode = 37 * hashCode + ( a != null ? a.hashCode( ) : 0 ); - hashCode = 37 * hashCode + ( b != null ? b.hashCode( ) : 0 ); + hashCode = 37 * hashCode + (a != null ? a.hashCode() : 0); + hashCode = 37 * hashCode + (b != null ? b.hashCode() : 0); } return hashCode; } - + @Override - public boolean equals( Object obj ) { + public boolean equals(Object obj) { boolean result; - if ( this == obj ) { + if (this == obj) { result = true; - } else if ( obj instanceof Pair ) { + } else if (obj instanceof Pair) { Pair pair = (Pair) obj; - result = ( this.a != null && this.a.equals( pair.a ) || this.a == null && pair.a == null ) && ( this.b != null && this.b.equals( pair.b ) || this.b == null && pair.b == null ); + result = (this.a != null && this.a.equals(pair.a) || this.a == null && pair.a == null) + && (this.b != null && this.b.equals(pair.b) || this.b == null && pair.b == null); } else { result = false; } return result; } - + @Override - public String toString( ) { - return "[" + (a==null?"null":a.toString( )) + ", " + - (b==null?"null":b.toString( )) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + public String toString() { + return "[" + (a == null ? "null" : a.toString()) + ", " + (b == null ? "null" : b.toString()) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } public static class Triple implements Serializable { private static final long serialVersionUID = 6806146864367514601L; - + private A a; - + private B b; - + private C c; - + private transient int hashCode; - - @SuppressWarnings("unused") // required for some serialization frameworks such as GWT RPC - private Triple() {} - - public Triple( A a, B b, C c ) { + + @SuppressWarnings("unused") + // required for some serialization frameworks such as GWT RPC + private Triple() { + } + + public Triple(A a, B b, C c) { this.a = a; this.b = b; this.c = c; hashCode = 0; } - - public A getA( ) { + + public A getA() { return a; } - - public B getB( ) { + + public B getB() { return b; } - - public C getC( ) { + + public C getC() { return c; } - + @Override - public int hashCode( ) { - if ( hashCode == 0 ) { + public int hashCode() { + if (hashCode == 0) { hashCode = 17; - hashCode = 37 * hashCode + ( a != null ? a.hashCode( ) : 0 ); - hashCode = 37 * hashCode + ( b != null ? b.hashCode( ) : 0 ); - hashCode = 37 * hashCode + ( c != null ? c.hashCode( ) : 0 ); + hashCode = 37 * hashCode + (a != null ? a.hashCode() : 0); + hashCode = 37 * hashCode + (b != null ? b.hashCode() : 0); + hashCode = 37 * hashCode + (c != null ? c.hashCode() : 0); } return hashCode; } - + @Override - public boolean equals( Object obj ) { + public boolean equals(Object obj) { boolean result; - if ( this == obj ) { + if (this == obj) { result = true; - } else if ( obj instanceof Triple ) { + } else if (obj instanceof Triple) { Triple thrice = (Triple) obj; - result = ( this.a != null && this.a.equals( thrice.a ) || this.a == null && thrice.a == null ) && ( this.b != null && this.b.equals( thrice.b ) || this.b == null && thrice.b == null ) && ( this.c != null && this.c.equals( thrice.c ) || this.c == null && thrice.c == null ); + result = (this.a != null && this.a.equals(thrice.a) || this.a == null && thrice.a == null) + && (this.b != null && this.b.equals(thrice.b) || this.b == null && thrice.b == null) + && (this.c != null && this.c.equals(thrice.c) || this.c == null && thrice.c == null); } else { result = false; } return result; } - + @Override - public String toString( ) { + public String toString() { return "[" + a + ", " + b + ", " + c + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } } @@ -147,6 +154,19 @@ public class Util { } return addTo; } + + /** + * Adds v to the value set for key k. If no entry exists yet for k, the + * entry is created using a {@link HashSet} for the value set. + */ + public static void add(Map> map, K k, V v) { + Set set = map.get(k); + if (set == null) { + set = new HashSet<>(); + map.put(k, set); + } + set.add(v); + } /** * Removes all elements in what from removeFrom and returns removeFrom for chained use. @@ -404,4 +424,37 @@ public class Util { } return result; } + + /** + * Searches the dominant object in an Iterable<T> collection. + * + * @param objects + * The Iterable<T> collection which should be analyzed. Objects are compared + * by their definition of {@link Object#equals(Object)}. + * @return T Returns the dominant object. If the collection have two objects with the highest count, + * you will get one of them returned. If the collection is null or empty, the method will + * return null. + */ + public static T getDominantObject(Iterable objects) { + T result = null; + if (objects != null) { + if (objects.iterator().hasNext()) { + HashMap countPerObject = new HashMap<>(); + int highestCount = 0; + for (T it : objects) { + Integer objectCount = countPerObject.get(it); + if (objectCount == null) { + objectCount = 0; + } + objectCount++; + countPerObject.put(it, objectCount); + if (objectCount > highestCount) { + highestCount = objectCount; + result = it; + } + } + } + } + return result; + } } \ No newline at end of file diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/filter/AbstractListFilter.java b/java/com.sap.sse.common/src/com/sap/sse/common/filter/AbstractListFilter.java index 993e83dbae2..a1308ddf82c 100755 --- a/java/com.sap.sse.common/src/com/sap/sse/common/filter/AbstractListFilter.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/filter/AbstractListFilter.java @@ -28,7 +28,6 @@ public abstract class AbstractListFilter { */ public abstract Iterable getStrings(T t); - /** * Constructs a list based on the contents of {@link #all} and the current search phrase {@link #text}. */ diff --git a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/GroupKey.java b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/GroupKey.java index 9997815e622..8f606dade0e 100644 --- a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/GroupKey.java +++ b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/GroupKey.java @@ -12,25 +12,56 @@ public interface GroupKey extends Serializable, Comparable { public String asString(); /** - * Checks if this group key has a sub key. For example if the data was grouped primary by competitor and secondary by leg type. - * @return true, if this group key has a sub key + * Checks if this group key has at least one sub key. For example if the data was grouped + * primary by competitor and secondary by leg type.
      + * This means, that {@link #getKeys()} returns a {@link List} that contains at least two elements. + * @return true, if this group key has at least one sub key */ public boolean hasSubKeys(); - - /** - * @return the main key, if there is one. Otherwise it returns this. - */ - public GroupKey getMainKey(); /** - * @return the sub keys or an empty list, if there are none. + * Returns a non-empty {@link List} of group keys that are represented by this key: + *
        + *
      • If {@link #hasSubKeys()} of this key false, a singleton List + * containing this is returned. + *
      • + *
      • If {@link #hasSubKeys()} of this key true, an unmodifiable List + * containing the represented keys is returned.
        + * The returned keys can again contain sub keys. + *
      • + *
      + * @return the group keys that are represented by this key. */ - public List getSubKeys(); + public List getKeys(); //Enforce hash code and equals in all subclasses @Override public abstract boolean equals(Object other); @Override public abstract int hashCode(); + + public static class Util { + + public static GroupKey getMainKey(GroupKey groupKey) { + return groupKey.getKeys().get(0); + } + + /** + * Returns the list of {@link GroupKey#getKeys() keys} except for the first key + * in the list. Or null, if there are no sub keys. + * + * @param groupKey + * @return the sub keys or null, if there aren't any. + */ + public static List getSubKeys(GroupKey groupKey) { + if (!groupKey.hasSubKeys()) { + return null; + } + + List keys = groupKey.getKeys(); + return keys.subList(1, keys.size()); + } + + } } diff --git a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/CompoundGroupKey.java b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/CompoundGroupKey.java index f45dee1bcdf..4517b7cada8 100644 --- a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/CompoundGroupKey.java +++ b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/CompoundGroupKey.java @@ -11,8 +11,8 @@ public class CompoundGroupKey extends AbstractGroupKey { private static final long serialVersionUID = -7902450253393172550L; - private GroupKey mainKey; - private ArrayList subKeys; + private List keys; + private boolean hasSubKeys; /** * Constructor for the GWT-Serialization. Don't use this! @@ -20,22 +20,29 @@ public class CompoundGroupKey extends AbstractGroupKey { @Deprecated CompoundGroupKey() { } - public CompoundGroupKey(GroupKey mainKey, List subKeys) { - if (mainKey == null) { - throw new IllegalArgumentException("The mainKey mustn't be null"); + public CompoundGroupKey(List keys) { + if (keys == null || keys.isEmpty()) { + throw new IllegalArgumentException("The keys mustn't be null or empty"); } - this.mainKey = mainKey; - this.subKeys = new ArrayList<>(subKeys); + this.keys = new ArrayList<>(keys); + hasSubKeys = this.keys.size() > 1; } @Override public String asString() { - StringBuilder builder = new StringBuilder(mainKey.asString()); - for (GroupKey groupKey : subKeys) { - builder.append("(" + groupKey.asString()); + StringBuilder builder = new StringBuilder(); + boolean first = true; + int bracketCount = 0; + for (GroupKey groupKey : keys) { + if (!first) { + builder.append('('); + bracketCount++; + } + builder.append(groupKey.asString()); + first = false; } - for (int i = 0; i < subKeys.size(); i++) { + for (int i = 0; i < bracketCount; i++) { builder.append(")"); } return builder.toString(); @@ -43,17 +50,16 @@ public class CompoundGroupKey extends AbstractGroupKey { @Override public boolean hasSubKeys() { - return !subKeys.isEmpty(); + return hasSubKeys; } @Override - public GroupKey getMainKey() { - return mainKey; - } - - @Override - public List getSubKeys() { - return Collections.unmodifiableList(subKeys); + public List getKeys() { + if (hasSubKeys) { + return Collections.unmodifiableList(keys); + } else { + return Collections.singletonList(keys.get(0)); + } } @Override @@ -61,15 +67,12 @@ public class CompoundGroupKey extends AbstractGroupKey { int result; if (key instanceof CompoundGroupKey) { CompoundGroupKey compoundGroupKey = (CompoundGroupKey) key; - result = mainKey.compareTo(compoundGroupKey.mainKey); + result = Integer.compare(keys.size(), compoundGroupKey.keys.size()); if (result == 0) { - result = Integer.compare(subKeys.size(), compoundGroupKey.subKeys.size()); - if (result == 0) { - for (int i = 0; i < subKeys.size(); i++) { - result = subKeys.get(i).compareTo(compoundGroupKey.subKeys.get(i)); - if (result != 0) { - break; - } + for (int i = 0; i < keys.size(); i++) { + result = keys.get(i).compareTo(compoundGroupKey.keys.get(i)); + if (result != 0) { + break; } } } @@ -83,8 +86,8 @@ public class CompoundGroupKey extends AbstractGroupKey { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((mainKey == null) ? 0 : mainKey.hashCode()); - result = prime * result + ((subKeys == null) ? 0 : subKeys.hashCode()); + result = prime * result + (hasSubKeys ? 1231 : 1237); + result = prime * result + ((keys == null) ? 0 : keys.hashCode()); return result; } @@ -97,15 +100,12 @@ public class CompoundGroupKey extends AbstractGroupKey { if (getClass() != obj.getClass()) return false; CompoundGroupKey other = (CompoundGroupKey) obj; - if (mainKey == null) { - if (other.mainKey != null) - return false; - } else if (!mainKey.equals(other.mainKey)) + if (hasSubKeys != other.hasSubKeys) return false; - if (subKeys == null) { - if (other.subKeys != null) + if (keys == null) { + if (other.keys != null) return false; - } else if (!subKeys.equals(other.subKeys)) + } else if (!keys.equals(other.keys)) return false; return true; } diff --git a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/GenericGroupKey.java b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/GenericGroupKey.java index 1c40ec40354..2d4f7de3afa 100644 --- a/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/GenericGroupKey.java +++ b/java/com.sap.sse.datamining.shared/src/com/sap/sse/datamining/shared/impl/GenericGroupKey.java @@ -31,15 +31,10 @@ public class GenericGroupKey extends AbstractGroupKey { public boolean hasSubKeys() { return false; } - - @Override - public GroupKey getMainKey() { - return this; - } @Override - public List getSubKeys() { - return Collections.emptyList(); + public List getKeys() { + return Collections.singletonList(this); } @Override diff --git a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelMultiDimensionalGroupingProcessor.java b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelMultiDimensionalGroupingProcessor.java index 504701b6f33..1480e10e7d8 100644 --- a/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelMultiDimensionalGroupingProcessor.java +++ b/java/com.sap.sse.datamining.test/src/com/sap/sse/datamining/impl/components/TestParallelMultiDimensionalGroupingProcessor.java @@ -83,10 +83,10 @@ public class TestParallelMultiDimensionalGroupingProcessor { } private void verifyGroupedElement(Number originElement) { - GroupKey mainKey = new GenericGroupKey(originElement.getLength()); - List subKeys = new ArrayList<>(); - subKeys.add(new GenericGroupKey(originElement.getCrossSum())); - GroupKey expectedKey = new CompoundGroupKey(mainKey, subKeys); + List keys = new ArrayList<>(); + keys.add(new GenericGroupKey(originElement.getLength())); + keys.add(new GenericGroupKey(originElement.getCrossSum())); + GroupKey expectedKey = new CompoundGroupKey(keys); assertThat(groupedElement.getKey(), is(expectedKey)); } diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/GroupKeyFactory.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/GroupKeyFactory.java index 98e077e87ef..a02c5cc0789 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/GroupKeyFactory.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/factories/GroupKeyFactory.java @@ -1,9 +1,9 @@ package com.sap.sse.datamining.factories; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import com.sap.sse.common.Util; import com.sap.sse.datamining.functions.Function; import com.sap.sse.datamining.shared.GroupKey; import com.sap.sse.datamining.shared.impl.CompoundGroupKey; @@ -12,18 +12,16 @@ import com.sap.sse.datamining.shared.impl.GenericGroupKey; public class GroupKeyFactory { public static GroupKey createNestingCompoundKeyFor(DataType input, Iterable> dimensions) { - Iterator> dimensionsIterator = dimensions.iterator(); - - Function mainDimension = dimensionsIterator.next(); - GroupKey mainKey = createDimensionValueGroupKeyFor(input, mainDimension); - List subKeys = new ArrayList<>(); - if (dimensionsIterator.hasNext()) { - while (dimensionsIterator.hasNext()) { - Function dimension = dimensionsIterator.next(); - subKeys.add(createDimensionValueGroupKeyFor(input, dimension)); + if (Util.size(dimensions) == 1) { + Function Dimension = Util.get(dimensions, 0); + return createDimensionValueGroupKeyFor(input, Dimension); + } else { + List keys = new ArrayList<>(); + for (Function Dimension : dimensions) { + keys.add(createDimensionValueGroupKeyFor(input, Dimension)); } + return new CompoundGroupKey(keys); } - return subKeys.isEmpty() ? mainKey : new CompoundGroupKey(mainKey, subKeys); } public static GroupKey createDimensionValueGroupKeyFor(DataType input, Function mainDimension) { diff --git a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelMultiDimensionalNestingGroupingProcessor.java b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelMultiDimensionalNestingGroupingProcessor.java index bf92a9520cd..c566783e517 100644 --- a/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelMultiDimensionalNestingGroupingProcessor.java +++ b/java/com.sap.sse.datamining/src/com/sap/sse/datamining/impl/components/AbstractParallelMultiDimensionalNestingGroupingProcessor.java @@ -2,10 +2,10 @@ package com.sap.sse.datamining.impl.components; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.concurrent.ExecutorService; +import com.sap.sse.common.Util; import com.sap.sse.datamining.components.AdditionalResultDataBuilder; import com.sap.sse.datamining.components.Processor; import com.sap.sse.datamining.components.ProcessorInstruction; @@ -57,22 +57,22 @@ public abstract class AbstractParallelMultiDimensionalNestingGroupingProcessor>(this, ProcessorInstructionPriority.Grouping) { @Override public GroupedDataEntry computeResult() { - return new GroupedDataEntry(createCompoundKeyFor(element, parameterizedDimensions.iterator()), element); + return new GroupedDataEntry(createGroupKeyFor(element), element); } }; } - private GroupKey createCompoundKeyFor(DataType input, Iterator> dimensionsIterator) { - ParameterizedFunction mainDimension = dimensionsIterator.next(); - GroupKey mainKey = createGroupKeyFor(input, mainDimension.getFunction(), mainDimension.getParameterProvider()); - List subKeys = new ArrayList<>(); - if (dimensionsIterator.hasNext()) { - while (dimensionsIterator.hasNext()) { - ParameterizedFunction dimension = dimensionsIterator.next(); - subKeys.add(createGroupKeyFor(input, dimension.getFunction(), dimension.getParameterProvider())); + private GroupKey createGroupKeyFor(DataType input) { + if (Util.size(parameterizedDimensions) == 1) { + ParameterizedFunction parameterizedDimension = Util.get(parameterizedDimensions, 0); + return createGroupKeyFor(input, parameterizedDimension.getFunction(), parameterizedDimension.getParameterProvider()); + } else { + List keys = new ArrayList<>(); + for (ParameterizedFunction parameterizedDimension : parameterizedDimensions) { + keys.add(createGroupKeyFor(input, parameterizedDimension.getFunction(), parameterizedDimension.getParameterProvider())); } + return new CompoundGroupKey(keys); } - return subKeys.isEmpty() ? mainKey : new CompoundGroupKey(mainKey, subKeys); } protected abstract GroupKey createGroupKeyFor(DataType input, Function dimension, ParameterProvider parameterProvider); diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java index 3eeb994b81a..1d9e16fbe5b 100755 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java @@ -14,4 +14,6 @@ public interface StringMessages extends Messages { String fileUploadResult(String status, String message); String removeUploadedFile(); + + String pleaseOnlyUploadContentYouHaveAllUsageRightsFor(); } diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/URLFieldWithFileUpload.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/URLFieldWithFileUpload.java index 2754f246f24..2b820bc9e63 100755 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/URLFieldWithFileUpload.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/URLFieldWithFileUpload.java @@ -46,7 +46,8 @@ public class URLFieldWithFileUpload extends Composite implements HasValue - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sse.gwt.theme/SSETheme_GWT.launch b/java/com.sap.sse.gwt.theme/SSETheme_GWT.launch index 497ba323966..099018ea63b 100644 --- a/java/com.sap.sse.gwt.theme/SSETheme_GWT.launch +++ b/java/com.sap.sse.gwt.theme/SSETheme_GWT.launch @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/ThemeResources.java b/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/ThemeResources.java index c9dd8bf04f3..9bfa24c514e 100644 --- a/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/ThemeResources.java +++ b/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/ThemeResources.java @@ -14,6 +14,8 @@ public interface ThemeResources extends ClientBundle { MediaCss mediaCss(); public interface MainCss extends CssResource{ + String mobile(); + String desktop(); String wrapper(); String navbar(); String navbar_button(); @@ -65,6 +67,7 @@ public interface ThemeResources extends ClientBundle { String slideto(); String slidetonav(); String slidetoactive(); + String fleetcorner(); } public interface MediaCss extends CssResource{ diff --git a/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/main.gss b/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/main.gss index 8bc3232eb44..ef74f7a328f 100644 --- a/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/main.gss +++ b/java/com.sap.sse.gwt.theme/src/main/java/com/sap/sse/gwt/theme/client/resources/main.gss @@ -74,6 +74,9 @@ figcaption { min-height: 100%; padding-bottom: 5em; } +.mobile .wrapper { + padding-bottom: 11.333333333333334em; +} .navbar { font-size: 1rem; } @@ -90,6 +93,8 @@ figcaption { transition: background-color 0.2s, border-color 0.2s; text-decoration: none; margin-right: 0.555555555555556em; +} +.desktop .navbar_button { border-top-left-radius: 0.277777777777778em; border-top-right-radius: 0.277777777777778em; } @@ -144,9 +149,11 @@ figcaption { font-size: 0.933333333333333rem; font-weight: 700; text-transform: uppercase; - border-radius: 0.214285714285714em; padding: 0.714285714285714em 1.071428571428571em; } +.desktop .buttonstrong { + border-radius: 0.214285714285714em; +} .buttoninactive { background-color: #ebebeb; pointer-events: none; @@ -222,6 +229,12 @@ figcaption { height: 1.666666666666667em; line-height: 1.666666666666667em; } +.mobile .label { + font-size: 0.666666666666667rem; + margin-left: 1em; + height: 1.6em; + line-height: 1.6em; +} .label:before { content: ''; position: absolute; @@ -233,17 +246,34 @@ figcaption { border-bottom: 0.833333333333333em solid transparent; border-right: 0.833333333333333em solid transparent; } +.mobile .label:before { + left: -0.8em; + border-top: 0.8em solid transparent; + border-bottom: 0.8em solid transparent; + border-right: 0.8em solid transparent; +} .labellarge { height: 2em; line-height: 1.75em; margin-left: 1em; } +.mobile .labellarge { + height: 2.4em; + line-height: 2.1em; + margin-left: 1.2em; +} .labellarge:before { left: -1em; border-top-width: 1em; border-bottom-width: 1em; border-right-width: 1em; } +.mobile .labellarge:before { + left: -1.2em; + border-top-width: 1.2em; + border-bottom-width: 1.2em; + border-right-width: 1.2em; +} .label[data-labeltype='live'] { background-color: #e94a1b; vertical-align: middle; @@ -348,6 +378,10 @@ figcaption { .mainsection { padding: 5.333333333333333em 0; } +.mobile .mainsection { + padding-top: 5.333333333333333em; + padding-bottom: 5.333333333333333em; +} .mainsection_header { text-align: center; margin-bottom: 4em; @@ -490,3 +524,13 @@ figcaption { .slidetoactive:hover { border-bottom-color: #d79900; } +.fleetcorner { + position: absolute; + top: 0.333333333333333em; + left: 0.333333333333333em; + width: 0; + height: 0; + border-style: solid; + border-width: 1em 1em 0 0; + color: transparent; +} \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java index de10e598022..54f733fc0ff 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java @@ -22,4 +22,5 @@ public interface StringMessages extends Messages { String configuration(); String settings(); String settingsForComponent(String localizedShortName); + String pleaseSelect(); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages.properties b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages.properties index 531f3e2d409..c05e6e6a61c 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages.properties +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages.properties @@ -23,4 +23,5 @@ description=Description error=Error configuration=Configuration settings=Settings -settingsForComponent=Settings for {0} \ No newline at end of file +settingsForComponent=Settings for {0} +pleaseSelect=Please select \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_de.properties b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_de.properties index 47b01033d39..65e12845d73 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_de.properties +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_de.properties @@ -23,4 +23,5 @@ description=Beschreibung error=Fehler configuration=Konfiguration settings=Einstellungen -settingsForComponent=Einstellungen für {0} \ No newline at end of file +settingsForComponent=Einstellungen für {0} +pleaseSelect=Bitte auswählen \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_ru.properties b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_ru.properties index fffedae8394..b64d3fc6eb6 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_ru.properties +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/StringMessages_ru.properties @@ -23,4 +23,5 @@ description=Описание error=Error configuration=Конфигурация settingsForComponent=Параметры {0} -settings=Параметры \ No newline at end of file +settings=Параметры +pleaseSelect=Please select \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringConstantsListEditorComposite.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringConstantsListEditorComposite.java index df1969397dd..6359e862bce 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringConstantsListEditorComposite.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/listedit/StringConstantsListEditorComposite.java @@ -96,7 +96,7 @@ public class StringConstantsListEditorComposite extends ListEditorComposite>() { @Override public void onValueChange(ValueChangeEvent> event) { - if(selectionBox != null) { + if (selectionBox != null) { // add a removed value item back to the list of available items List diffList = new ArrayList<>(); Util.addAll(availableConstantValuesToAdd, diffList); @@ -110,10 +110,10 @@ public class StringConstantsListEditorComposite extends ListEditorComposite values) { listBox.clear(); - if(placeholderTextForAddListbox != null) { + if (placeholderTextForAddListbox != null) { listBox.addItem(placeholderTextForAddListbox); } else { - listBox.addItem("Please select"); + listBox.addItem(getStringMessages().pleaseSelect()); } for (String value : values) { listBox.addItem(value); @@ -138,7 +138,7 @@ public class StringConstantsListEditorComposite extends ListEditorComposite extends AbstractEntryPoint { +public abstract class AbstractMvpEntryPoint extends AbstractEntryPoint { /** @@ -40,14 +39,14 @@ public abstract class AbstractMvpEntryPoint extends Ab * @param activityMappers * used for a composite activity mapper; the first mapper to provide an activity for a place gets its way */ - public void initMvp(ClientFactory clientFactory, PlaceHistoryMapper historyMapper, ActivityMapper... activityMappers) { + public void initMvp(CF clientFactory, PlaceHistoryMapper historyMapper, ActivityMapper... activityMappers) { // Start ActivityManager for the main widget with our ActivityMapper ActivityMapperRegistry activityMapperRegistry = new ActivityMapperRegistry(); for (ActivityMapper activityMapper : activityMappers) { activityMapperRegistry.addActivityMapper(activityMapper); } EventBus eventBus = clientFactory.getEventBus(); - ActivityManager activityManager = new CustomActivityManager(activityMapperRegistry, eventBus); + ActivityManager activityManager = createActivityManager(activityMapperRegistry, clientFactory); activityManager.setDisplay(clientFactory.getContent()); // Start PlaceHistoryHandler with our PlaceHistoryMapper @@ -58,4 +57,8 @@ public abstract class AbstractMvpEntryPoint extends Ab // Goes to place represented on URL or default place historyHandler.handleCurrentHistory(); } + + protected ActivityManager createActivityManager(ActivityMapper activityMapperRegistry, CF clientFactory) { + return new CustomActivityManager(activityMapperRegistry, clientFactory.getEventBus()); + } } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/ClientFactoryImpl.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/ClientFactoryImpl.java index 42b818f8254..489b08c45b4 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/ClientFactoryImpl.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/ClientFactoryImpl.java @@ -14,24 +14,28 @@ import com.sap.sse.gwt.client.ErrorReporter; * @author Axel Uhl (d043530) * */ -public abstract class ClientFactoryImpl implements ClientFactory { +public abstract class ClientFactoryImpl implements ClientFactory { private final EventBus eventBus; private final PlaceController placeController; - private final TopLevelView root; + private final TLV root; - public ClientFactoryImpl(TopLevelView root) { + public ClientFactoryImpl(TLV root) { this(root, new SimpleEventBus()); } - protected ClientFactoryImpl(TopLevelView root, EventBus eventBus) { + protected ClientFactoryImpl(TLV root, EventBus eventBus) { this(root, eventBus, new PlaceController(eventBus)); } - protected ClientFactoryImpl(TopLevelView root, EventBus eventBus, PlaceController placeController) { + protected ClientFactoryImpl(TLV root, EventBus eventBus, PlaceController placeController) { this.root = root; this.eventBus = eventBus; this.placeController = placeController; } + + protected TLV getTopLevelView() { + return root; + } @Override public ErrorReporter getErrorReporter() { diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/CustomActivityManager.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/CustomActivityManager.java new file mode 100644 index 00000000000..c4c04330643 --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/CustomActivityManager.java @@ -0,0 +1,21 @@ +package com.sap.sse.gwt.client.mvp; + +import com.google.gwt.activity.shared.ActivityMapper; +import com.google.gwt.place.shared.Place; +import com.google.web.bindery.event.shared.EventBus; + +public class CustomActivityManager extends DelegatingActivityManager { + + private EventBus eventBus; + + public CustomActivityManager(ActivityMapper mapper, EventBus eventBus) { + super(mapper, eventBus); + this.eventBus = eventBus; + } + + @Override + protected void afterPlaceActivation(Place place) { + super.afterPlaceActivation(place); + eventBus.fireEvent(new PlaceChangedEvent(place)); + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/DelegatingActivityManager.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/DelegatingActivityManager.java new file mode 100644 index 00000000000..10816047fa2 --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/DelegatingActivityManager.java @@ -0,0 +1,96 @@ +package com.sap.sse.gwt.client.mvp; + +import com.google.gwt.activity.shared.Activity; +import com.google.gwt.activity.shared.ActivityManager; +import com.google.gwt.activity.shared.ActivityMapper; +import com.google.gwt.place.shared.Place; +import com.google.gwt.place.shared.PlaceChangeEvent; +import com.google.gwt.place.shared.PlaceChangeRequestEvent; +import com.google.gwt.user.client.ui.AcceptsOneWidget; +import com.google.web.bindery.event.shared.EventBus; +import com.google.web.bindery.event.shared.SimpleEventBus; + +public class DelegatingActivityManager extends ActivityManager { + + private final ActivityManager realActivityManager; + + public DelegatingActivityManager(ActivityMapper mapper, EventBus eventBus) { + super(new NoOpActivityMapper(), new SimpleEventBus()); + realActivityManager = new ActivityManager(new ActivityMapperDelegate(mapper), eventBus); + } + + public EventBus getActiveEventBus() { + return realActivityManager.getActiveEventBus(); + } + + public void onPlaceChange(PlaceChangeEvent event) { + realActivityManager.onPlaceChange(event); + } + + public void onPlaceChangeRequest(PlaceChangeRequestEvent event) { + realActivityManager.onPlaceChangeRequest(event); + } + + public void setDisplay(AcceptsOneWidget display) { + realActivityManager.setDisplay(display); + } + + protected void beforeActivityStart(Activity activity) { + } + + protected void afterPlaceActivation(Place place) { + } + + private static class NoOpActivityMapper implements ActivityMapper { + @Override + public Activity getActivity(Place place) { + return null; + } + } + + private final class ActivityMapperDelegate implements ActivityMapper { + private final ActivityMapper realMapper; + public ActivityMapperDelegate(ActivityMapper realMapper) { + super(); + this.realMapper = realMapper; + } + + @Override + public Activity getActivity(Place place) { + return new ActivityDelegate(place, realMapper.getActivity(place)); + } + } + + private final class ActivityDelegate implements Activity { + + private final Activity realActivity; + private final Place place; + + public ActivityDelegate(Place place, Activity realActivity) { + this.place = place; + this.realActivity = realActivity; + } + + @Override + public String mayStop() { + return realActivity.mayStop(); + } + + @Override + public void onCancel() { + realActivity.onCancel(); + } + + @Override + public void onStop() { + realActivity.onStop(); + } + + @Override + public void start(AcceptsOneWidget panel, com.google.gwt.event.shared.EventBus eventBus) { + beforeActivityStart(realActivity); + realActivity.start(panel, eventBus); + afterPlaceActivation(place); + } + } +} diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/AppClientFactoryImpl.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/AppClientFactoryImpl.java index d54edbf0c7e..ec1d2363aa2 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/AppClientFactoryImpl.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/AppClientFactoryImpl.java @@ -14,7 +14,7 @@ import com.sap.sse.gwt.client.mvp.example.hello.HelloPlace; import com.sap.sse.gwt.client.mvp.example.hello.HelloView; import com.sap.sse.gwt.client.mvp.example.hello.HelloViewImpl; -public class AppClientFactoryImpl extends ClientFactoryImpl implements AppClientFactory { +public class AppClientFactoryImpl extends ClientFactoryImpl implements AppClientFactory { private HelloView helloView; private GoodbyeView goodbyeView; diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/ExampleEntryPoint.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/ExampleEntryPoint.java index 4bf6e3cc74b..772e27095cf 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/ExampleEntryPoint.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/example/ExampleEntryPoint.java @@ -10,7 +10,7 @@ import com.sap.sse.gwt.client.mvp.AbstractMvpEntryPoint; * * @author Axel Uhl (d043530) */ -public class ExampleEntryPoint extends AbstractMvpEntryPoint { +public class ExampleEntryPoint extends AbstractMvpEntryPoint { @Override protected void doOnModuleLoad() { diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/impl/CustomActivityManager.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/impl/CustomActivityManager.java deleted file mode 100644 index b0f2384975d..00000000000 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/mvp/impl/CustomActivityManager.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sap.sse.gwt.client.mvp.impl; - -import com.google.gwt.activity.shared.ActivityManager; -import com.google.gwt.activity.shared.ActivityMapper; -import com.google.gwt.place.shared.PlaceChangeEvent; -import com.google.web.bindery.event.shared.EventBus; -import com.sap.sse.gwt.client.mvp.PlaceChangedEvent; - -public class CustomActivityManager extends ActivityManager { - - private EventBus eventBus; - - public CustomActivityManager(ActivityMapper mapper, EventBus eventBus) { - super(mapper, eventBus); - this.eventBus = eventBus; - } - - @Override - public void onPlaceChange(PlaceChangeEvent event) { - super.onPlaceChange(event); - eventBus.fireEvent(new PlaceChangedEvent(event.getNewPlace())); - } - -} diff --git a/java/com.sap.sse.security.ui/Security UI sdm.launch b/java/com.sap.sse.security.ui/Security UI sdm.launch index 7ff5e9979c7..63fc7dc7116 100755 --- a/java/com.sap.sse.security.ui/Security UI sdm.launch +++ b/java/com.sap.sse.security.ui/Security UI sdm.launch @@ -1,48 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/SecureClientFactoryImpl.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/SecureClientFactoryImpl.java index ab63e865293..360a1b80943 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/SecureClientFactoryImpl.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/SecureClientFactoryImpl.java @@ -11,18 +11,18 @@ import com.sap.sse.gwt.client.mvp.TopLevelView; * @author Frank * */ -public abstract class SecureClientFactoryImpl extends ClientFactoryImpl implements WithSecurity { +public abstract class SecureClientFactoryImpl extends ClientFactoryImpl implements WithSecurity { private WithSecurity securityProvider; - public SecureClientFactoryImpl(TopLevelView root) { + public SecureClientFactoryImpl(TLV root) { this(root, new SimpleEventBus()); } - protected SecureClientFactoryImpl(TopLevelView root, EventBus eventBus) { + protected SecureClientFactoryImpl(TLV root, EventBus eventBus) { this(root, eventBus, new PlaceController(eventBus)); } - protected SecureClientFactoryImpl(TopLevelView root, EventBus eventBus, PlaceController placeController) { + protected SecureClientFactoryImpl(TLV root, EventBus eventBus, PlaceController placeController) { super(root, eventBus, placeController); securityProvider = new DefaultWithSecurityImpl(); diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages.properties b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages.properties index 1afc6e0a7ba..15566305597 100755 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages.properties +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages.properties @@ -77,4 +77,5 @@ errorCommunicatingWithServer=Error communicating with server editProfile=Edit user profile allPermissions=All permissions (including inferred from roles) configuration=Configuration -settingsForComponent=Settings for {0} \ No newline at end of file +settingsForComponent=Settings for {0} +pleaseSelect=Please select \ No newline at end of file diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages_de.properties b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages_de.properties index 90ec37db17c..a378439264d 100755 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages_de.properties +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/i18n/StringMessages_de.properties @@ -77,4 +77,5 @@ errorCommunicatingWithServer=Fehler bei der Kommunikation mit dem Server editProfile=Benutzerprofil bearbeiten allPermissions=Alle Berechtigungen (einschließlich der aus den Rollen abgeleiteten) configuration=Konfiguration -settingsForComponent=Einstellungen für {0} \ No newline at end of file +settingsForComponent=Einstellungen für {0} +pleaseSelect=Bitte auswählen \ No newline at end of file diff --git a/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF b/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF index e7ad05c7f81..179cf981850 100644 --- a/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.shared.android/META-INF/MANIFEST.MF @@ -7,4 +7,6 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Require-Bundle: com.sap.sse.common Export-Package: com.sap.sse.concurrent, + com.sap.sse.shared.media, + com.sap.sse.shared.media.impl, com.sap.sse.util.impl diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptor.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/ImageDescriptor.java similarity index 90% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptor.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/ImageDescriptor.java index 67ace752668..6bc37ff7450 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptor.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/ImageDescriptor.java @@ -1,4 +1,4 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; import com.sap.sse.common.Util.Pair; diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/MediaDescriptor.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaDescriptor.java similarity index 91% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/MediaDescriptor.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaDescriptor.java index 6f777b7b6be..e6298e67dd1 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/MediaDescriptor.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaDescriptor.java @@ -1,10 +1,11 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; import java.io.Serializable; import java.net.URL; import java.util.Locale; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.media.MimeType; /** * A common media interface for all kinds of media like images or videos. diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/MediaUtils.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaUtils.java similarity index 98% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/MediaUtils.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaUtils.java index 987f90a77e5..2ea747ed4ee 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/MediaUtils.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/MediaUtils.java @@ -1,4 +1,4 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; import java.io.IOException; import java.net.URL; @@ -18,6 +18,7 @@ import javax.imageio.stream.ImageInputStream; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.media.MimeType; public class MediaUtils { private static final Logger logger = Logger.getLogger(MediaUtils.class.getName()); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptor.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/VideoDescriptor.java similarity index 87% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptor.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/VideoDescriptor.java index 1f21c990afa..411138ae1af 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptor.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/VideoDescriptor.java @@ -1,4 +1,4 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; import java.net.URL; diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithImages.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithImages.java similarity index 95% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/WithImages.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithImages.java index ade9f8c6791..450f7e0fa20 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithImages.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithImages.java @@ -1,4 +1,5 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; + public interface WithImages { /** diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithMedia.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithMedia.java similarity index 91% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/WithMedia.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithMedia.java index ac433dc3bbf..e929dfc1f39 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithMedia.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithMedia.java @@ -1,4 +1,4 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; import java.util.List; diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithVideos.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithVideos.java similarity index 95% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/WithVideos.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithVideos.java index 5706f49757b..c6e411117a6 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/WithVideos.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/WithVideos.java @@ -1,4 +1,5 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media; + public interface WithVideos { diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/AbstractMediaDescriptor.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/AbstractMediaDescriptor.java similarity index 95% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/AbstractMediaDescriptor.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/AbstractMediaDescriptor.java index 5621e82192a..c1fb05a6431 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/AbstractMediaDescriptor.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/AbstractMediaDescriptor.java @@ -1,4 +1,4 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media.impl; import java.io.Serializable; import java.net.URL; @@ -8,6 +8,8 @@ import java.util.Set; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.MediaDescriptor; /** * Common media data for media items diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptorImpl.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/ImageDescriptorImpl.java similarity index 91% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptorImpl.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/ImageDescriptorImpl.java index 48f7c10896b..147a958a2d9 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/ImageDescriptorImpl.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/ImageDescriptorImpl.java @@ -1,9 +1,11 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media.impl; import java.net.URL; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.ImageDescriptor; public class ImageDescriptorImpl extends AbstractMediaDescriptor implements ImageDescriptor { diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptorImpl.java b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/VideoDescriptorImpl.java similarity index 89% rename from java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptorImpl.java rename to java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/VideoDescriptorImpl.java index ce8d112252e..0be8e8db323 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/VideoDescriptorImpl.java +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/shared/media/impl/VideoDescriptorImpl.java @@ -1,8 +1,10 @@ -package com.sap.sse.common.media; +package com.sap.sse.shared.media.impl; import java.net.URL; import com.sap.sse.common.TimePoint; +import com.sap.sse.common.media.MimeType; +import com.sap.sse.shared.media.VideoDescriptor; public class VideoDescriptorImpl extends AbstractMediaDescriptor implements VideoDescriptor { private static final long serialVersionUID = 2651747912466590862L; diff --git a/java/target/configuration/logging_debug.properties b/java/target/configuration/logging_debug.properties index 5be8f6e6335..9791b7cd1e2 100644 --- a/java/target/configuration/logging_debug.properties +++ b/java/target/configuration/logging_debug.properties @@ -21,8 +21,11 @@ com.sap.sse.level = FINE # log at level FINEST for TransientCompetitorStoreIMpl #com.sap.sailing.domain.base.impl.TransientCompetitorStoreImpl.level = FINEST #com.sap.sailing.domain.base.impl.SharedDomainFactoryImpl.level = FINEST +# Want to see start time inference in detail: +#com.sap.sailing.domain.tracking.impl.TrackedRaceImpl.level = FINEST org.eclipse.jetty.level = INFO org.apache.activemq.level = INFO # TTCM logging is disabled by default; enable by commenting out the following line com.sap.sailing.domain.tracking.impl.DynamicTrackImpl.level = OFF + diff --git a/mobile/.project b/mobile/.project new file mode 100644 index 00000000000..bed704482d7 --- /dev/null +++ b/mobile/.project @@ -0,0 +1,40 @@ + + + mobile + + + + + + + + + + 1447316205611 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-com\.sap\..* + + + + 1447316205621 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-google-.* + + + + 1447316205635 + + 10 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-github-.* + + + + diff --git a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/ui/activities/LoggableActivity.java b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/ui/activities/LoggableActivity.java index b3a6cf3c0ff..be4c1334882 100644 --- a/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/ui/activities/LoggableActivity.java +++ b/mobile/com.sap.sailing.android.shared/src/com/sap/sailing/android/shared/ui/activities/LoggableActivity.java @@ -1,5 +1,8 @@ package com.sap.sailing.android.shared.ui.activities; +import java.io.Closeable; +import java.io.IOException; + import android.os.Bundle; import android.support.v7.app.AppCompatActivity; @@ -56,4 +59,14 @@ public abstract class LoggableActivity extends AppCompatActivity { super.onBackPressed(); ExLog.i(this, TAG, String.format("Back pressed on activity %s", this.getClass().getSimpleName())); } + + public void safeClose(Closeable c) { + if (c != null) { + try { + c.close(); + } catch (IOException e) { + ExLog.ex(this, TAG, e); + } + } + } } diff --git a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/activities/RegattaActivity.java b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/activities/RegattaActivity.java index eb523bae00b..f66bdca92b4 100755 --- a/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/activities/RegattaActivity.java +++ b/mobile/com.sap.sailing.android.tracking.app/src/com/sap/sailing/android/tracking/app/ui/activities/RegattaActivity.java @@ -437,6 +437,9 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF protected String doInBackground(String... urls) { uploadUrl = urls[0]; + DataOutputStream outputStream = null; + FileInputStream imageInputStream = null; + BufferedReader reader = null; try { if (imageFile != null) { URL url = new URL(uploadUrl); @@ -445,11 +448,11 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF urlConnection.setDoOutput(true); urlConnection.setRequestMethod("POST"); urlConnection.setRequestProperty("Content-Type", "image/jpeg"); - DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream()); + outputStream = new DataOutputStream(urlConnection.getOutputStream()); int nRead; byte[] data = new byte[2048]; - FileInputStream imageInputStream = new FileInputStream(imageFile); + imageInputStream = new FileInputStream(imageFile); while ((nRead = imageInputStream.read(data, 0, data.length)) != -1) { outputStream.write(data, 0, nRead); } @@ -458,7 +461,7 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF outputStream.close(); Log.d(TAG, "Image upload response: " + urlConnection.getResponseCode()); if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { - BufferedReader reader = new BufferedReader(new InputStreamReader((urlConnection.getInputStream()))); + reader = new BufferedReader(new InputStreamReader((urlConnection.getInputStream()))); StringBuilder builder = new StringBuilder(); String output; while ((output = reader.readLine()) != null) { @@ -471,6 +474,16 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF } catch (IOException e) { ExLog.e(RegattaActivity.this, TAG, "Error uploading image: " + e.getLocalizedMessage()); cancel(true); + } finally { + if (outputStream != null) { + RegattaActivity.this.safeClose(outputStream); + } + if (imageInputStream != null) { + RegattaActivity.this.safeClose(imageInputStream); + } + if (reader != null) { + RegattaActivity.this.safeClose(reader); + } } return ""; } @@ -508,14 +521,15 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF protected File doInBackground(String... urls) { downloadUrl = urls[0]; File imageFile = null; - + InputStream in = null; + FileOutputStream outputStream = null; try { - InputStream in = new java.net.URL(downloadUrl).openStream(); + in = new java.net.URL(downloadUrl).openStream(); imageFile = getImageFile(getLeaderboardImageFileName(leaderboard.name)); if (!imageFile.exists()){ imageFile.createNewFile(); } - FileOutputStream outputStream = new FileOutputStream(imageFile); + outputStream = new FileOutputStream(imageFile); int read = 0; byte[] bytes = new byte[1024]; @@ -526,6 +540,13 @@ public class RegattaActivity extends AbstractRegattaActivity implements RegattaF in.close(); } catch (Exception e) { e.printStackTrace(); + } finally { + if (in != null) { + safeClose(in); + } + if (outputStream != null) { + safeClose(outputStream); + } } return imageFile; } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index 0990cacc4de..93e1ae7ec11 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -16,9 +16,9 @@ import android.content.Context; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventFactory; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEventFactoryImpl; import com.sap.sailing.domain.abstractlog.race.impl.RaceLogImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; import com.sap.sailing.domain.abstractlog.race.state.impl.RaceStateImpl; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -98,16 +98,15 @@ public class OfflineDataManager extends DataManager { competitors.add(new CompetitorImpl(UUID.randomUUID(), "Team Korea", Color.GREEN, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); competitors.add(new CompetitorImpl(UUID.randomUUID(), "Realteam", Color.BLACK, null, null, null, null, /* timeOnTimeFactor */ null, /* timeOnDistanceAllowancePerNauticalMile */ null)); - RaceLogEventFactory factory = new RaceLogEventFactoryImpl(); RaceLog log = new RaceLogImpl(UUID.randomUUID()); final AbstractLogEventAuthor author = AppPreferences.on(context).getAuthor(); ConfigurationLoader configuration = PreferencesRegattaConfigurationLoader .loadFromPreferences(preferences); - log.add(factory.createStartTimeEvent(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, + log.add(new RaceLogStartTimeEventImpl(new MillisecondsTimePoint(new Date().getTime() - 2000), author, 1, new MillisecondsTimePoint(new Date().getTime() - 1000))); - log.add(factory.createRaceStatusEvent(new MillisecondsTimePoint(new Date().getTime()), + log.add(new RaceLogRaceStatusEventImpl(new MillisecondsTimePoint(new Date().getTime()), AppPreferences.on(context).getAuthor(), 1, RaceLogRaceStatus.FINISHING)); ManagedRace q1 = new ManagedRaceImpl(new ManagedRaceIdentifierImpl("A.B", new FleetImpl("A"), qualifying, raceGroup), diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/BaseActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/BaseActivity.java index efc34c4c054..1d81ab65348 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/BaseActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/BaseActivity.java @@ -1,5 +1,8 @@ package com.sap.sailing.racecommittee.app.ui.activities; +import java.io.Closeable; +import java.io.IOException; + import android.content.Intent; import android.os.Bundle; import android.view.MenuItem; @@ -80,4 +83,14 @@ public class BaseActivity extends SendingServiceAwareActivity { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } + + public void safeClose(Closeable c) { + if (c != null) { + try { + c.close(); + } catch (IOException e) { + ExLog.ex(this, TAG, e); + } + } + } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/ResultsCapturingActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/ResultsCapturingActivity.java index 0c8e6d2f18d..c6ade285df7 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/ResultsCapturingActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/ResultsCapturingActivity.java @@ -208,8 +208,9 @@ public class ResultsCapturingActivity extends SessionActivity { @Override public void onPictureTaken(byte[] data, Camera camera) { + FileOutputStream fos = null; try { - FileOutputStream fos = new FileOutputStream(currentImageFile); + fos = new FileOutputStream(currentImageFile); fos.write(data); fos.close(); photoList.add(Uri.fromFile(currentImageFile)); @@ -217,6 +218,10 @@ public class ResultsCapturingActivity extends SessionActivity { } catch (Exception e) { String toastText = getString(R.string.error_picture_callback); Toast.makeText(ResultsCapturingActivity.this, toastText, Toast.LENGTH_LONG).show(); + } finally { + if (fos != null) { + safeClose(fos); + } } } }; diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SessionActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SessionActivity.java index bbff71a67f2..816b53f4674 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SessionActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/SessionActivity.java @@ -5,6 +5,7 @@ import android.content.DialogInterface.OnClickListener; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; + import com.sap.sailing.android.shared.logging.ExLog; import com.sap.sailing.racecommittee.app.R; @@ -77,5 +78,4 @@ public abstract class SessionActivity extends BaseActivity { ExLog.i(this, TAG, "Do logout now!"); super.onReset(); // resets the data manager and fades the activity } - } diff --git a/mobile/github-advrecyclerview_lib/res/.gitignore b/mobile/github-advrecyclerview_lib/res/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/wiki/.project b/wiki/.project new file mode 100644 index 00000000000..788a2015e18 --- /dev/null +++ b/wiki/.project @@ -0,0 +1,13 @@ + + + wiki + + + + + + + + + + diff --git a/wiki/Log-File-Analysis.md b/wiki/Log-File-Analysis.md new file mode 100644 index 00000000000..5b6ffc4fdba --- /dev/null +++ b/wiki/Log-File-Analysis.md @@ -0,0 +1,110 @@ +# Log File Analysis + +[[_TOC_]] + +## Log File Types + +There are three different types of log files produced by the server landscape under the umbrella of http://www.sapsailing.com: + + - Java server logs (sailing0.log.0, gc.log.0.current, ...) + + - Apache log files (access_log, error_log, ...) + + - Amazon EC2 Elastic Load Balancer (ELB) logs (017363970217_elasticloadbalancing_eu-west-1_ELBGermanLeague_20151118T1320Z_52.18.137.128_18dpodfi.log) + +### Java Server Logs + +The Java server logs contain health, memory and general progress data as well as information about exceptions that occurred, including deadlock situations and important application events such as adding a wind sensor account, starting to track a race, creating a new regatta, etc. The format of a typical Java server log line is + +
      +Nov 03, 2015 6:32:24 PM com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl loadControlPointWithTwoMarks
      +INFO: Migrating right Mark of ControlPointWithTwoMarks Gate White P / White S from old field GATE_RIGHT to CONTROLPOINTWITHTWOMARKS_RIGHT
      +
      + +A typical garbage collection log from gc.log.0.current may look like this: + +
      +      ...
      +      [Ref Enq: 0.0 ms]
      +      [Redirty Cards: 0.2 ms]
      +      [Free CSet: 2.2 ms]
      +   [Eden: 5406.0M(5406.0M)->0.0B(5398.0M) Survivors: 26.0M->32.0M Heap: 8156.2M(9216.0M)->2757.5M(9216.0M)]
      + [Times: user=0.28 sys=0.01, real=0.19 secs]
      +
      + +The `Heap: ...` section gives hints as to the current heap memory consumption before and after the last GC run as well as the maximum heap allocated so far. + +### Apache Log Files + +Our primary, central Apache web server largely acts as a reverse proxy that maps subdomain names to virtual host declarations by means of a configuration file located at `/etc/httpd/conf.d/001-events.conf` which uses all sorts of clever macros to keep these mapping definitions concise. Due to the large number of these virtual hosts and in order to be able to keep the logs apart, we use the "combined" log file format which lists the virtual host name used as the first column in the log entry. This lets an `access_log` entry look like this: + +
      +dutchleague2015.sapsailing.com 94.209.86.140 - - [08/Nov/2015:10:47:31 +0000] "POST /gwt/service/sailing HTTP/1.1" 200 751 "http://dutchleague2015.sapsailing.com/gwt/RaceBoard.html®attaName=Dutch%20Sailing%20League%202015%20-%20Almere" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.78.2 (KHTML, like Gecko) Version/6.1.6 Safari/537.78.2"
      +
      + +After the virtual host name comes the client's IP address, followed by two unused fields regarding authentication, then the time stamp, the request, response code, number of bytes delivered, the referrer URL and the user agent. + +For load-balanced set-ups we have an Amazon Elastic Load Balancer (ELB) dispatch incoming requests to the instances linked to the ELB. The ELB can (and definitely should) be configured to write its own logs (see next section), but those are not in Apache log file format and contain no information about the referrer URL. Using an Apache server on the instances linked to the ELB partly solves this problem by generating logs in the same format that our central Apache server uses. + +In addition to this, the Apache servers on these load-balanced instances perform the same URL rewriting and reverse proxying using the same set of macros that the central Apache server uses. + +**However**, one key problem of these decentralized Apache log files is that the client IP address only identifies the load balancer or reverse proxy instance, not the original client itself. With this, any type of analysis that tries to count the number of visitors will deliver skewed results. Counting the plain number of hits, though, is OK, as is the identification of the most-frequently used referrer URLs which can, e.g., help to identify popular leaderboards and races. + +Still, in order to provide the true client IP in the log files, we use the `X-Forwarded-For` HTTP header field which contains the comma-separated list of "hops" through which the request was reverse-proxied so far. The following combination of Apache `httpd.conf` entries make this work: + +
      +  SetEnvIf X-Forwarded-For "^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*).*$" original_client_ip=$1
      +  LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
      +  LogFormat "%v %{original_client_ip}e %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" first_forwarded_for_ip
      +  CustomLog logs/access_log combined env=!original_client_ip
      +  CustomLog logs/access_log first_forwarded_for_ip env=original_client_ip
      +
      + +This uses the SetEnvIf module, tries to match an IP address at the start of the `X-Forwarded-For` header field, and if found, assigns it to the `original_client_ip` variable. This variable, in turn, decides which of the two `CustomLog` directives is applied to the request. If the variable is set, instead of using the regular `%h` field for the client IP, the variable value is logged by `%{original_client_ip}`. + +### Amazon EC2 Elastic Load Balancer (ELB) Logs + +An Amazon ELB can be configured to write log files to the S3 storage. The general format is [explained here](http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/access-log-collection.html#access-log-entry-format). It contains in particular the client IP where the request originated and can tell timing parameters for request forwarding and processing that otherwise would not be available. + +The format for these logs is + +
      +timestamp elb client:port backend:port request_processing_time backend_processing_time response_processing_time elb_status_code backend_status_code received_bytes sent_bytes "request" "user_agent" ssl_cipher ssl_protocol
      +
      + +It seems a good idea to always capture these logs for archiving purposes. They end up on an S3 bucket, and by default we use `sapsailing-access-logs`. + +Content can be synced from there to a local directory using the following command: + +``s3cmd sync s3://sapsailing-access-logs/elb-access-logs ./elb-access-logs/`` + +Our central web server at `www.sapsailing.com` does this periodically every day, sync'ing the logs to `/var/log/old/elb-access-logs/`. + +## Automatic Log File Rotation to /var/log/old + +When an EC2 server is launched from its Amazon Machine Image (AMI), the /etc/init.d/sailing script is executed with the "start" parameter. This script is really just a link to `/home/sailing/code/configuration/sailing` which comes from the git version checked out to the workspace at `/home/sailing/code`. This script patches the file `/etc/logrotate.d/httpd` such that when log rotation happens, the existence of the directory `/var/log/old/$SERVER_NAME/$SERVER_IP` is ensured and the log files are copied there. + +This way, logs end up in a per server-name and per server-ip directory. + +The general log rotation rules (size, time, compression, etc.) is governed by `/etc/logrotate.conf`. + +## Analysis Tools + +### goaccess + + - mention specific parameters and .goaccess config file required to parse our format + +### apachetop + +### AWStats + + - specific log collection approach configured in /etc/awstats/*.conf script + + - extension for per-virtual-host hit count + + - configuration of central apache to present results (awstats.sapsailing.com) + +### Custom Scripts + + - unique_ips_per_referrer + - convertELBLogToApacheFormat \ No newline at end of file diff --git a/wiki/amazon-ec2.md b/wiki/amazon-ec2.md index 8c288ed3edd..f7d7aeef81c 100644 --- a/wiki/amazon-ec2.md +++ b/wiki/amazon-ec2.md @@ -21,7 +21,6 @@ You may need to select "All generations" instead of "Current generation" to see
       INSTALL_FROM_RELEASE=`name-of-release`
       USE_ENVIRONMENT=live-server
      -MONGODB_PORT=10202
       MONGODB_NAME=myspecificevent
       REPLICATION_CHANNEL=myspecificevent
       SERVER_NAME=MYSPECIFICEVENT
      diff --git a/wiki/creating-ec2-image-from-scratch.md b/wiki/creating-ec2-image-from-scratch.md
      index cbb10c28b51..b9f5b4bae28 100644
      --- a/wiki/creating-ec2-image-from-scratch.md
      +++ b/wiki/creating-ec2-image-from-scratch.md
      @@ -19,7 +19,8 @@ I then did a `yum update` and added the following packages:
        - goaccess
        - postfix (for sending e-mail, e.g., to invite competitors and buoy pingers)
        - tigervnc-server
      - - xdm (to have a rudimentary window manager available for the VNC server)
      + - WindowMaker
      + - xterm
       
       Then I created a mount point /home/sailing and copied the following lines from the /etc/fstab file from an existing SL instance:
       
      @@ -84,7 +85,17 @@ Added the following two lines to `/etc/security/limits.conf`:
       
       This increases the maximum number of open files allowed from the default 1024 to a more appropriate 65k.
       
      -Copied the httpd configuration files `/etc/httpd/conf/httpd.conf`, `/etc/httpd/conf.d/000-macros.conf` and the skeletal `/etc/httpd/conf.d/001-events.conf` from an existing server.
      +Copied the httpd configuration files `/etc/httpd/conf/httpd.conf`, `/etc/httpd/conf.d/000-macros.conf` and the skeletal `/etc/httpd/conf.d/001-events.conf` from an existing server. Make sure the following lines are in httpd.conf:
      +
      +
      +  SetEnvIf X-Forwarded-For "^([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*).*$" original_client_ip=$1
      +  LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
      +  LogFormat "%v %{original_client_ip}e %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" first_forwarded_for_ip
      +  CustomLog logs/access_log combined env=!original_client_ip
      +  CustomLog logs/access_log first_forwarded_for_ip env=original_client_ip
      +
      + +They ensure that the original client IPs are logged also if the Apache server runs behind a reverse proxy or an ELB. See also [the section on log file analysis](/wiki/log-file-analysis#log-file-analysis_log-file-types_apache-log-files). Copied /etc/logrotate.conf from an existing SL instance so that `/var/log/logrotate-target` is used to rotate logs to. diff --git a/wiki/onboarding.md b/wiki/onboarding.md index b03d31f79b9..12d24ae467a 100644 --- a/wiki/onboarding.md +++ b/wiki/onboarding.md @@ -37,11 +37,9 @@ First of all, make sure you've looked at http://www.amazon.de/Patterns-Elements- 2. Bugzilla * Ask the Bugzilla administrator (Frank Mittag, Axel Uhl) to create a bugzilla account for you. * Bugzilla url: http://bugzilla.sapsailing.com/bugzilla/ -3. Race Analysis user - * Add yourself as an user to the Race Analysis suite by adding a Jetty user in the file java\target\configuration\jetty\etc\realm.properties -4. Wiki +3. Wiki * Send a request to Axel Uhl or Simon Marcel Pamies that includes the SHA1 hash of your desired password. Obtain such an SHA1 hash for your password here: http://www.sha1-online.com/. -5. Hudson +4. Hudson * Request a Hudson user by sending e-mail to Axel Uhl, Frank Mittag or Simon Marcel Pamies. #### Steps to build and run the Race Analysis Suite @@ -66,11 +64,11 @@ First of all, make sure you've looked at http://www.amazon.de/Patterns-Elements- * Import all projects from the `mobile/` subdirectory of the git main folder; this in particular contains the race committee app projects * Set the Eclipse target platform to race-analysis-p2-remote.target (located in com.sap.sailing.targetplatform/definitions) * Wait until the target platform has been resolved completely - * In the project com.sap.sailing.gwt.ui create a new subfolder "classes" in the folder WEB-INF * Rebuild all projects 4. Run the Race Analysis Suite * Start the MongoDB * Start the appropriate Eclipse launch configuration (e.g. 'Sailing Server (Proxy)') You´ll find this in the run dropdown + * Run "Security UI sdm" in the run dropdown * Run "SailingGWT" in the run dropdown 5. Within the Race Analysis Suite * Default Login: user "admin", password "admin"