Merge branch 'master' into permission-vertical

Change-Id: I8d1fab815610c344e20db356fddc98c998e8f574
This commit is contained in:
Axel Uhl
2018-08-02 13:44:44 +02:00
413 changed files with 10171 additions and 1589 deletions
+34 -4
View File
@@ -4,6 +4,18 @@
#
# chkconfig: 2345 95 10
# description: Sailing contains all sailing services
#
### BEGIN INIT INFO
# Provides: sailing
# Required-Start: $local_fs $network $named $remote_fs
# Should-Start:
# Required-Stop:
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The sailing service
# Description: Start all sailing services required for this instance
### END INIT INFO
# Source function library.
. /etc/init.d/functions
@@ -14,8 +26,8 @@ JAVA_START_INSTANCES="server"
SERVERS_DIR=/home/sailing/servers
GIT_REPOSITORY=/home/sailing/code
APACHE_CONFIG_DIR=/etc/httpd/conf.d
rm /var/log/sailing.out
rm /var/log/sailing.err
echo "Executing with $1" >>/var/log/sailing.out
start_tmux() {
su - sailing -c "/home/sailing/bin/tmuxConsole.sh unattended"
@@ -63,13 +75,21 @@ start_servers() {
stop_servers() {
for conf in $JAVA_START_INSTANCES; do
echo "Stopping Java server $conf"
echo "Stopping Java server $conf" >> /var/log/sailing.out
su - sailing -c "cd $SERVERS_DIR/$conf && ./stop"
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
stop_httpd
sync_logs
done
}
sync_logs() {
echo "Executing logrotate followed by a sync to ensure that logs are synchronized" >> /var/log/sailing.out
logrotate -f /etc/logrotate.conf
sync
}
# launch_httpd(server_name, port, event_id)
launch_httpd() {
echo "Will try to launch httpd so this replica can work with an ELB easily." >>/var/log/sailing.out
@@ -78,7 +98,7 @@ launch_httpd() {
source $SERVERS_DIR/$FIRST_SERVER/env.sh
# Append Apache macro invocation for /internal-server-status based on mod_status and INSTANCE_DNS to $APACHE_CONFIG_DIR/001-events.conf
echo "Appending macro usage for $INSTANCE_DNS/internal-server-status URL for mod_status based Apache monitoring to $APACHE_CONFIG_DIR/001-events.conf" >>/var/log/sailing.out
echo "## SERVER STATUS" >>$APACHE_CONFIG_DIR/001-events.conf
echo "## SERVER STATUS" >>$APACHE_CONFIG_DIR/001-events.conf
echo "Use Status $INSTANCE_DNS internal-server-status" >>$APACHE_CONFIG_DIR/001-events.conf
echo "Launching httpd..." >>/var/log/sailing.out
service httpd start
@@ -87,13 +107,23 @@ launch_httpd() {
fi
}
stop_httpd() {
if [ -x /etc/init.d/httpd ]; then
service httpd stop
echo "Stopped httpd..." >>/var/log/sailing.out
fi
}
# See how we were called.
case "$1" in
start)
/usr/sbin/update-motd
start_servers
touch /var/lock/subsys/sailing
;;
stop)
stop_servers
rm -f /var/lock/subsys/sailing
;;
status)
status java
@@ -15,7 +15,7 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
import com.sap.sailing.datamining.test.util.ConcurrencyTestsUtil;
import com.sap.sailing.datamining.test.util.NullProcessor;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -27,7 +27,7 @@ import com.sap.sse.datamining.components.Processor;
public class TestLeaderboardGroupRetrievalProcessor {
private RacingEventService service;
private Processor<RacingEventService, LeaderboardGroupWithContext> retriever;
private Processor<RacingEventService, HasLeaderboardGroupContext> retriever;
private Collection<LeaderboardGroup> retrievedGroups;
@@ -37,14 +37,14 @@ public class TestLeaderboardGroupRetrievalProcessor {
stub(service.getLeaderboardGroups()).toReturn(getGroupsInService());
retrievedGroups = new HashSet<>();
Processor<LeaderboardGroupWithContext, Void> receiver = new NullProcessor<LeaderboardGroupWithContext, Void>(LeaderboardGroupWithContext.class, Void.class) {
Processor<HasLeaderboardGroupContext, Void> receiver = new NullProcessor<HasLeaderboardGroupContext, Void>(HasLeaderboardGroupContext.class, Void.class) {
@Override
public void processElement(LeaderboardGroupWithContext element) {
public void processElement(HasLeaderboardGroupContext element) {
retrievedGroups.add(element.getLeaderboardGroup());
}
};
Collection<Processor<LeaderboardGroupWithContext, ?>> resultReceivers = new ArrayList<>();
Collection<Processor<HasLeaderboardGroupContext, ?>> resultReceivers = new ArrayList<>();
resultReceivers.add(receiver);
retriever = new LeaderboardGroupRetrievalProcessor(ConcurrencyTestsUtil.getExecutor(), resultReceivers, 0);
}
@@ -188,7 +188,7 @@ AbsRelativeBearingToNextMarkAfterManeuver=Abs. relative bearing to the next mark
RatioBetweenDistanceSailedWithAndWithoutManeuver=Ratio between distance sailed with and without maneuver
RatioBetweenDistanceSailedTowardMiddleAngleProjectionWithAndWithoutManeuver=Ratio between distance sailed toward middle angle projection with and without maneuver
DurationLostByManeuver=Duration lost by maneuver
DurationLostByManeuverTowardMiddleAngleProjection=duration lost by maneuver toward middle angle projection
DurationLostByManeuverTowardMiddleAngleProjection=Duration lost by maneuver toward middle angle projection
JibingCount=Jibing count
TackingCount=Tacking count
AbsTwaAtMaxTurningRate=Abs. TWA at max. turning rate
@@ -198,4 +198,5 @@ PercentageOfMainCurveProgressUntilLowestSpeed=Percentage of main curve progress
PercentageOfMainCurveProgressUntilHighestSpeed=Percentage of main curve progress until highest speed
PercentageOfMainCurveProgressUntilMaxTurningRate=Percentage of main curve progress until max. turning rate speed
AbsTwaAtManeuverMiddle=Abs. TWA at maneuver middle
GpsSamplingRate=GPS sampling rate
GpsSamplingRate=GPS sampling rate
RaceDuration=Race duration
@@ -201,4 +201,5 @@ PercentageOfMainCurveProgressUntilHighestSpeed=Prozentualer Fortschritt der Haup
PercentageOfMainCurveProgressUntilMaxTurningRate=Prozentualer Fortschritt der Hauptkurve bis zum Erreichen von max. Drehrate
ManeuverTypeForCompleteManeuverCurve=Manövertyp für komplette Manöverkurve
AbsTwaAtManeuverMiddle=Abs. TWA während Manövermitte
GpsSamplingRate=GPS-Samplingrate
GpsSamplingRate=GPS-Samplingrate
RaceDuration=Renndauer
@@ -5,12 +5,13 @@ import java.util.Collection;
import com.sap.sailing.datamining.data.HasBravoFixContext;
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
import com.sap.sailing.datamining.data.HasFoilingSegmentContext;
import com.sap.sailing.datamining.data.HasGPSFixContext;
import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
import com.sap.sailing.datamining.data.HasManeuverContext;
import com.sap.sailing.datamining.data.HasManeuverSpeedDetailsContext;
import com.sap.sailing.datamining.data.HasCompleteManeuverCurveWithEstimationDataContext;
import com.sap.sailing.datamining.data.HasMarkPassingContext;
import com.sap.sailing.datamining.data.HasRaceOfCompetitorContext;
import com.sap.sailing.datamining.data.HasRaceResultOfCompetitorContext;
@@ -22,13 +23,13 @@ import com.sap.sailing.datamining.data.HasWindTrackContext;
import com.sap.sailing.datamining.impl.components.BravoFixRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.BravoFixTrackRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompetitorOfRaceInLeaderboardRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompleteManeuverCurveWithEstimationDataRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.FoilingSegmentRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.GPSFixRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.LeaderboardGroupRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.LeaderboardRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.ManeuverRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.ManeuverSpeedDetailsRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.CompleteManeuverCurveWithEstimationDataRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.MarkPassingRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.RaceOfCompetitorRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TrackedLegOfCompetitorRetrievalProcessor;
@@ -36,7 +37,6 @@ import com.sap.sailing.datamining.impl.components.TrackedLegRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.TrackedRaceRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.WindFixRetrievalProcessor;
import com.sap.sailing.datamining.impl.components.WindTrackRetrievalProcessor;
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
import com.sap.sailing.datamining.shared.FoilingSegmentsDataMiningSettings;
import com.sap.sailing.datamining.shared.ManeuverSettings;
import com.sap.sailing.datamining.shared.ManeuverSettingsImpl;
@@ -55,7 +55,7 @@ public class SailingDataRetrievalChainDefinitions {
final DataRetrieverChainDefinition<RacingEventService, HasLeaderboardContext> leaderboardRetrieverChainDefinition = new SimpleDataRetrieverChainDefinition<>(
RacingEventService.class, HasLeaderboardContext.class, "LeaderboardSailingDomainRetrieverChain");
leaderboardRetrieverChainDefinition.startWith(LeaderboardGroupRetrievalProcessor.class, LeaderboardGroupWithContext.class, "LeaderboardGroup");
leaderboardRetrieverChainDefinition.startWith(LeaderboardGroupRetrievalProcessor.class, HasLeaderboardGroupContext.class, "LeaderboardGroup");
leaderboardRetrieverChainDefinition.endWith(LeaderboardGroupRetrievalProcessor.class, LeaderboardRetrievalProcessor.class,
HasLeaderboardContext.class, "Leaderboard");
@@ -16,7 +16,7 @@ public interface HasBravoFixContext {
@Connector(ordinal=1)
BravoFix getBravoFix();
@Connector(messageKey="Speed")
@Connector(messageKey="")
SpeedWithBearing getSpeed();
@Connector(messageKey="Wind")
@@ -2,7 +2,6 @@ package com.sap.sailing.datamining.data;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
@@ -12,8 +11,6 @@ public interface HasLeaderboardContext {
Leaderboard getLeaderboard();
PolarDataService getPolarDataService();
@Dimension(messageKey="Leaderboard", ordinal=1)
String getName();
@@ -4,6 +4,7 @@ import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.Tack;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Speed;
import com.sap.sse.datamining.annotations.Connector;
@@ -14,74 +15,74 @@ import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
public interface HasRaceOfCompetitorContext {
@Connector(scanForStatistics=false)
public HasTrackedRaceContext getTrackedRaceContext();
HasTrackedRaceContext getTrackedRaceContext();
@Connector(messageKey="Competitor")
@Statistic(messageKey="")
public Competitor getCompetitor();
@Statistic(messageKey="Competitor")
Competitor getCompetitor();
@Dimension(messageKey="TackAtStart", ordinal=12)
public Tack getTackAtStart() throws NoWindException;
Tack getTackAtStart() throws NoWindException;
@Dimension(messageKey="DistanceToStarboardSideAtStartOfCompetitor", ordinal=13)
public ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart();
ClusterDTO getPercentageClusterForDistanceToStarboardSideAtStart();
@Dimension(messageKey="RelativeScoreInPercent", ordinal=14)
public ClusterDTO getPercentageClusterForRelativeScore();
ClusterDTO getPercentageClusterForRelativeScore();
@Statistic(messageKey="DistanceAtStart", resultDecimals=2, ordinal=0)
public Distance getDistanceToStartLineAtStart();
Distance getDistanceToStartLineAtStart();
@Statistic(messageKey="DistanceToStarboardSideAtStartOfCompetitor", resultDecimals=2, ordinal=1)
public Double getNormalizedDistanceToStarboardSideAtStartOfCompetitor();
Double getNormalizedDistanceToStarboardSideAtStartOfCompetitor();
@Statistic(messageKey="DistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark", resultDecimals=2, ordinal=1)
public Pair<Double, Double> getNormalizedDistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark();
Pair<Double, Double> getNormalizedDistanceToStarboardSideAtStartOfCompetitorVsRankAtFirstMark();
@Statistic(messageKey="WindwardDistanceToAdvantageousEndOfLineAtStartOfRace", resultDecimals=2, ordinal=2)
public Distance getWindwardDistanceToAdvantageousLineEndAtStartofRace();
Distance getWindwardDistanceToAdvantageousLineEndAtStartofRace();
@Statistic(messageKey="WindwardDistanceToAdvantageousEndOfLineAtStartOfCompetitor", resultDecimals=2, ordinal=2)
public Distance getWindwardDistanceToAdvantageousLineEndAtStartofCompetitor();
Distance getWindwardDistanceToAdvantageousLineEndAtStartofCompetitor();
@Connector(messageKey="SpeedWhenStarting", ordinal=3)
public Speed getSpeedWhenStarting();
Speed getSpeedWhenStarting();
@Connector(messageKey="SpeedTenSecondsBeforeStart", ordinal=4)
public Speed getSpeedTenSecondsBeforeStart();
Speed getSpeedTenSecondsBeforeStart();
@Connector(messageKey="SpeedTenSecondsAfterStart", ordinal=5)
public Speed getSpeedTenSecondsAfterStartOfRace();
Speed getSpeedTenSecondsAfterStartOfRace();
@Statistic(messageKey="RankThirtySecondsAfterStart", resultDecimals=2, ordinal=6)
public Double getRankThirtySecondsAfterStartOfRace();
Double getRankThirtySecondsAfterStartOfRace();
@Statistic(messageKey="RankAfterHalfOfTheFirstLeg", resultDecimals=2, ordinal=7)
public Double getRankAfterHalfOfTheFirstLeg();
Double getRankAfterHalfOfTheFirstLeg();
@Statistic(messageKey="RankAtFirstMark", resultDecimals=2, ordinal=8)
public Double getRankAtFirstMark();
Double getRankAtFirstMark();
@Statistic(messageKey="RankGainsOrLossesBetweenFirstMarkAndFinish", resultDecimals=2, ordinal=9)
public Double getRankGainsOrLossesBetweenFirstMarkAndFinish();
Double getRankGainsOrLossesBetweenFirstMarkAndFinish();
@Statistic(messageKey="NumberOfManeuvers", resultDecimals=0, ordinal=10)
public int getNumberOfManeuvers();
int getNumberOfManeuvers();
@Statistic(messageKey="NumberOfTacks", resultDecimals=0, ordinal=11)
public int getNumberOfTacks();
int getNumberOfTacks();
@Statistic(messageKey="NumberOfJibes", resultDecimals=0, ordinal=12)
public int getNumberOfJibes();
int getNumberOfJibes();
@Statistic(messageKey="NumberOfPenaltyCircles", resultDecimals=0, ordinal=13)
public int getNumberOfPenaltyCircles();
int getNumberOfPenaltyCircles();
@Statistic(messageKey="DistanceTraveled", resultDecimals=1)
public Distance getDistanceTraveled();
Distance getDistanceTraveled();
@Statistic(messageKey="LineLengthAtStart", resultDecimals=1)
public Distance getLineLengthAtStart();
Distance getLineLengthAtStart();
@Statistic(messageKey="AbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor", resultDecimals=2)
Distance getAbsoluteWindwardDistanceToStarboardSideAtStartOfCompetitor();
@@ -94,4 +95,8 @@ public interface HasRaceOfCompetitorContext {
@Statistic(messageKey="RelativeDistanceToAdvantageousEndOfLineAtStartOfRace", resultDecimals=2)
Double getRelativeDistanceToAdvantageousEndOfLineAtStartOfRace();
@Statistic(messageKey="RaceDuration")
Duration getDuration();
}
@@ -8,6 +8,7 @@ import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.NauticalSide;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Duration;
import com.sap.sse.datamining.annotations.Connector;
import com.sap.sse.datamining.annotations.Dimension;
import com.sap.sse.datamining.annotations.Statistic;
@@ -46,10 +47,13 @@ public interface HasTrackedRaceContext {
@Dimension(messageKey="IsTracked", ordinal=9)
public Boolean isTracked();
@Statistic(messageKey="NumberOfCompetitorFixes", resultDecimals=0, ordinal=0)
@Statistic(messageKey="RaceDuration", ordinal=0)
public Duration getDuration();
@Statistic(messageKey="NumberOfCompetitorFixes", resultDecimals=0, ordinal=1)
public int getNumberOfCompetitorFixes();
@Statistic(messageKey="NumberOfMarkFixes", resultDecimals=0, ordinal=1)
@Statistic(messageKey="NumberOfMarkFixes", resultDecimals=0, ordinal=2)
public int getNumberOfMarkFixes();
// Convenience methods for race dependent calculation to avoid code duplication
@@ -11,7 +11,7 @@ public interface HasWindFixContext extends HasWind {
@Connector(scanForStatistics=false)
public HasTrackedRaceContext getTrackedRaceContext();
@Statistic(messageKey="", ordinal=0)
@Statistic(messageKey="WindFix", ordinal=0)
public Wind getWind();
@Statistic(messageKey="windFrom", resultDecimals=1, ordinal=1)
@@ -24,21 +24,24 @@ public class BravoFixRetrievalProcessor extends AbstractRetrievalProcessor<HasTr
@Override
protected Iterable<HasBravoFixContext> retrieveData(HasTrackedLegOfCompetitorContext element) {
Collection<HasBravoFixContext> bravoFixesWithContext = new ArrayList<>();
BravoFixTrack<Competitor> bravoFixTrack = element.getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
if (bravoFixTrack != null) {
bravoFixTrack.lockForRead();
try {
TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
BravoFixTrack<Competitor> bravoFixTrack = element.getTrackedLegContext().getTrackedRaceContext().getTrackedRace().getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
if (bravoFixTrack != null) {
bravoFixTrack.lockForRead();
try {
for (BravoFix bravoFix : bravoFixTrack.getFixes(trackedLegOfCompetitor.getStartTime(), true, trackedLegOfCompetitor.getFinishTime(), true)) {
if (isAborted()) {
break;
}
BravoFixWithContext gpsFixWithContext = new BravoFixWithContext(
new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), bravoFix.getTimePoint()), bravoFix);
bravoFixesWithContext.add(gpsFixWithContext);
}
} finally {
bravoFixTrack.unlockAfterRead();
}
} finally {
bravoFixTrack.unlockAfterRead();
}
}
return bravoFixesWithContext;
@@ -1,7 +1,7 @@
package com.sap.sailing.datamining.impl.components;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasBravoFixTrackContext;
@@ -28,13 +28,9 @@ public class BravoFixTrackRetrievalProcessor extends AbstractRetrievalProcessor<
@Override
protected Iterable<HasBravoFixTrackContext> retrieveData(HasRaceOfCompetitorContext element) {
Collection<HasBravoFixTrackContext> bravoTracksWithContext = new ArrayList<>();
final TrackedRace trackedRace = element.getTrackedRaceContext().getTrackedRace();
final BravoFixTrack<Competitor> bravoFixTrack = trackedRace.getSensorTrack(element.getCompetitor(), BravoFixTrack.TRACK_NAME);
if (bravoFixTrack != null) {
bravoTracksWithContext.add(new BravoFixTrackWithContext(element, bravoFixTrack));
}
return bravoTracksWithContext;
return bravoFixTrack == null ? Collections.emptySet() : Collections.singleton(new BravoFixTrackWithContext(element, bravoFixTrack));
}
}
@@ -24,9 +24,15 @@ public class CompetitorOfRaceInLeaderboardRetrievalProcessor extends
protected Iterable<HasRaceResultOfCompetitorContext> retrieveData(HasLeaderboardContext element) {
Collection<HasRaceResultOfCompetitorContext> raceResultsOfCompetitor = new ArrayList<>();
for (RaceColumn raceColumn : element.getLeaderboard().getRaceColumns()) {
if (isAborted()) {
break;
}
for (Competitor competitor : element.getLeaderboard().getCompetitors()) {
if (isAborted()) {
break;
}
HasRaceResultOfCompetitorContext raceResultOfCompetitorContext = new RaceResultOfCompetitorWithContext(element, raceColumn, competitor,
element.getPolarDataService());
element.getLeaderboardGroupContext().getPolarDataService());
raceResultsOfCompetitor.add(raceResultOfCompetitorContext);
}
}
@@ -48,15 +48,27 @@ public class CompleteManeuverCurveWithEstimationDataRetrievalProcessor extends
Competitor competitor = element.getCompetitor();
ManeuverDetectorWithEstimationDataSupport maneuverDetector = new ManeuverDetectorWithEstimationDataSupportDecoratorImpl(
new ManeuverDetectorImpl(trackedRace, competitor),
element.getTrackedRaceContext().getLeaderboardContext().getPolarDataService());
element.getTrackedRaceContext().getLeaderboardContext().getLeaderboardGroupContext().getPolarDataService());
Iterable<Maneuver> maneuvers = trackedRace.getManeuvers(competitor, false);
if (isAborted()) {
return result;
}
Iterable<CompleteManeuverCurve> maneuverCurves = maneuverDetector.getCompleteManeuverCurves(maneuvers);
if (isAborted()) {
return result;
}
Iterable<CompleteManeuverCurveWithEstimationData> maneuversWithEstimationData = maneuverDetector
.getCompleteManeuverCurvesWithEstimationData(maneuverCurves);
CompleteManeuverCurveWithEstimationData previousManeuver = null;
CompleteManeuverCurveWithEstimationData currentManeuver = null;
for (CompleteManeuverCurveWithEstimationData nextManeuver : maneuversWithEstimationData) {
if (isAborted()) {
break;
}
if (currentManeuver != null) {
CompleteManeuverCurveWithEstimationDataWithContext maneuverWithContext = new CompleteManeuverCurveWithEstimationDataWithContext(
element, currentManeuver, settings, previousManeuver, nextManeuver);
@@ -50,6 +50,9 @@ public class FoilingSegmentRetrievalProcessor extends AbstractRetrievalProcessor
bravoFixTrack.lockForRead();
try {
for (final BravoFix bravoFix : bravoFixTrack.getFixes(startOfRace, /* fromInclusive */ true, end, /* toInclusive */ false)) {
if (isAborted()) {
break;
}
final boolean currentFixIsFoiling =
(bravoFix.isFoiling(settings.getMinimumRideHeight()) &&
(settings.getMinimumSpeedForFoiling() == null || settings.getMinimumSpeedForFoiling().compareTo(
@@ -30,6 +30,9 @@ public class GPSFixRetrievalProcessor extends AbstractRetrievalProcessor<HasTrac
TrackedLegOfCompetitor trackedLegOfCompetitor = element.getTrackedLegOfCompetitor();
if (trackedLegOfCompetitor.getStartTime() != null && trackedLegOfCompetitor.getFinishTime() != null) {
for (GPSFixMoving gpsFix : competitorTrack.getFixes(trackedLegOfCompetitor.getStartTime(), true, trackedLegOfCompetitor.getFinishTime(), true)) {
if (isAborted()) {
break;
}
HasGPSFixContext gpsFixWithContext = new GPSFixWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), gpsFix.getTimePoint()), gpsFix);
gpsFixesWithContext.add(gpsFixWithContext);
@@ -1,30 +1,36 @@
package com.sap.sailing.datamining.impl.components;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.server.RacingEventService;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class LeaderboardGroupRetrievalProcessor extends AbstractRetrievalProcessor<RacingEventService, LeaderboardGroupWithContext> {
public class LeaderboardGroupRetrievalProcessor extends AbstractRetrievalProcessor<RacingEventService, HasLeaderboardGroupContext> {
public LeaderboardGroupRetrievalProcessor(ExecutorService executor,
Collection<Processor<LeaderboardGroupWithContext, ?>> resultReceivers, int retrievalLevel) {
super(RacingEventService.class, LeaderboardGroupWithContext.class, executor, resultReceivers, retrievalLevel);
Collection<Processor<HasLeaderboardGroupContext, ?>> resultReceivers, int retrievalLevel) {
super(RacingEventService.class, HasLeaderboardGroupContext.class, executor, resultReceivers, retrievalLevel);
}
@Override
protected Iterable<LeaderboardGroupWithContext> retrieveData(RacingEventService element) {
final PolarDataService polarDataService = element.getPolarDataService();
return element.getLeaderboardGroups()
.values()
.stream()
.map(lg -> new LeaderboardGroupWithContext(lg, polarDataService))
.collect(Collectors.toSet());
protected Iterable<HasLeaderboardGroupContext> retrieveData(RacingEventService element) {
Set<HasLeaderboardGroupContext> data = new HashSet<>();
PolarDataService polarDataService = element.getPolarDataService();
for (LeaderboardGroup leaderboardGroup : element.getLeaderboardGroups().values()) {
if (isAborted()) {
break;
}
data.add(new LeaderboardGroupWithContext(leaderboardGroup, polarDataService));
}
return data;
}
}
@@ -5,24 +5,27 @@ import java.util.Collection;
import java.util.concurrent.ExecutorService;
import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.datamining.impl.data.LeaderboardGroupWithContext;
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
import com.sap.sailing.datamining.impl.data.LeaderboardWithContext;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.impl.components.AbstractRetrievalProcessor;
public class LeaderboardRetrievalProcessor extends AbstractRetrievalProcessor<LeaderboardGroupWithContext, HasLeaderboardContext> {
public class LeaderboardRetrievalProcessor extends AbstractRetrievalProcessor<HasLeaderboardGroupContext, HasLeaderboardContext> {
public LeaderboardRetrievalProcessor(ExecutorService executor,
Collection<Processor<HasLeaderboardContext, ?>> resultReceivers, int retrievalLevel) {
super(LeaderboardGroupWithContext.class, HasLeaderboardContext.class, executor, resultReceivers, retrievalLevel);
super(HasLeaderboardGroupContext.class, HasLeaderboardContext.class, executor, resultReceivers, retrievalLevel);
}
@Override
protected Iterable<HasLeaderboardContext> retrieveData(LeaderboardGroupWithContext element) {
protected Iterable<HasLeaderboardContext> retrieveData(HasLeaderboardGroupContext element) {
Collection<HasLeaderboardContext> leaderboardsWithContext = new ArrayList<>();
for (Leaderboard leaderboard : element.getLeaderboardGroup().getLeaderboards()) {
leaderboardsWithContext.add(new LeaderboardWithContext(leaderboard, element, element.getPolarDataService()));
if (isAborted()) {
break;
}
leaderboardsWithContext.add(new LeaderboardWithContext(leaderboard, element));
}
return leaderboardsWithContext;
}
@@ -9,6 +9,7 @@ import com.sap.sailing.datamining.data.HasTrackedLegOfCompetitorContext;
import com.sap.sailing.datamining.impl.data.ManeuverWithContext;
import com.sap.sailing.datamining.impl.data.TrackedLegOfCompetitorWithSpecificTimePointWithContext;
import com.sap.sailing.datamining.shared.ManeuverSettings;
import com.sap.sailing.domain.base.Waypoint;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.tracking.Maneuver;
import com.sap.sailing.domain.tracking.ManeuverCurveBoundaries;
@@ -36,6 +37,9 @@ public class ManeuverRetrievalProcessor
TimePoint finishTime = element.getTrackedLegOfCompetitor().getFinishTime();
if (finishTime != null) {
Iterable<Maneuver> maneuvers = null;
if (!isLastLeg(element)) {
finishTime = finishTime.minus(1);
}
try {
maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
} catch (NoWindException e) {
@@ -44,6 +48,10 @@ public class ManeuverRetrievalProcessor
Maneuver previousManeuver = null;
Maneuver currentManeuver = null;
for (Maneuver nextManeuver : maneuvers) {
if (isAborted()) {
break;
}
if (currentManeuver != null) {
ManeuverWithContext maneuverWithContext = new ManeuverWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), currentManeuver.getTimePoint()), currentManeuver,
@@ -66,6 +74,12 @@ public class ManeuverRetrievalProcessor
return maneuversWithContext;
}
private boolean isLastLeg(HasTrackedLegOfCompetitorContext element) {
Waypoint finishWaypoint = element.getTrackedLegContext().getTrackedRaceContext().getRace().getCourse().getLastWaypoint();
Waypoint toWaypoint = element.getTrackedLegOfCompetitor().getLeg().getTo();
return finishWaypoint.equals(toWaypoint);
}
private boolean isManeuverCompliantWithSettings(Maneuver previousManeuver,
ManeuverWithContext currentManeuverWithContext, Maneuver nextManeuver) {
boolean mainCurveAnalysis = settings.isMainCurveAnalysis();
@@ -87,6 +87,10 @@ public class ManeuverSpeedDetailsRetrievalProcessor
double directionChangeForAnalysisSignum = Math.signum(directionChangeInDegreesForAnalysis);
for (SpeedWithBearingStep bearingStep : maneuverBearingSteps) {
if (isAborted()) {
break;
}
currentDirectionChangeSumInDegrees += bearingStep.getCourseChangeInDegrees();
if (previousRoundedTWA != -1
&& Math.signum(currentDirectionChangeSumInDegrees) != directionChangeForAnalysisSignum
@@ -123,6 +127,9 @@ public class ManeuverSpeedDetailsRetrievalProcessor
for (int step = 1, fillingTWA = twaIterationFunction
.apply(previousRoundedTWA); fillingTWA != roundedTWA; fillingTWA = twaIterationFunction
.apply(fillingTWA), ++step) {
if (isAborted()) {
break;
}
if (speedPerTWA[fillingTWA] == 0) {
speedPerTWA[fillingTWA] = previousSpeed
+ diffWithPreviousSpeed * step / diffWithPreviousTWA;
@@ -29,6 +29,9 @@ public class MarkPassingRetrievalProcessor extends AbstractRetrievalProcessor<Ha
try {
Iterable<Maneuver> maneuvers = element.getTrackedLegOfCompetitor().getManeuvers(finishTime, false);
for (Maneuver maneuver : maneuvers) {
if (isAborted()) {
break;
}
if (maneuver.isMarkPassing()) {
maneuversWithContext.add(new MarkPassingWithContext(new TrackedLegOfCompetitorWithSpecificTimePointWithContext(
element.getTrackedLegContext(), element.getTrackedLegOfCompetitor(), maneuver.getTimePoint()), maneuver));
@@ -22,6 +22,9 @@ public class RaceOfCompetitorRetrievalProcessor extends AbstractRetrievalProcess
protected Iterable<HasRaceOfCompetitorContext> retrieveData(HasTrackedRaceContext element) {
Collection<HasRaceOfCompetitorContext> raceOfCompetitorsWithContext = new ArrayList<>();
for (Competitor competitor : element.getTrackedRace().getRace().getCompetitors()) {
if (isAborted()) {
break;
}
HasRaceOfCompetitorContext raceOfCompetitorWithContext = new RaceOfCompetitorWithContext(element, competitor);
raceOfCompetitorsWithContext.add(raceOfCompetitorWithContext);
}
@@ -22,6 +22,9 @@ public class TrackedLegOfCompetitorRetrievalProcessor extends AbstractRetrievalP
protected Iterable<HasTrackedLegOfCompetitorContext> retrieveData(HasTrackedLegContext element) {
Collection<HasTrackedLegOfCompetitorContext> trackedLegOfCompetitorsWithContext = new ArrayList<>();
for (Competitor competitor : element.getTrackedRaceContext().getTrackedRace().getRace().getCompetitors()) {
if (isAborted()) {
break;
}
HasTrackedLegOfCompetitorContext trackedLegOfCompetitorWithContext = new TrackedLegOfCompetitorWithContext(element, element.getTrackedLeg().getTrackedLeg(competitor));
trackedLegOfCompetitorsWithContext.add(trackedLegOfCompetitorWithContext);
}
@@ -23,6 +23,9 @@ public class TrackedLegRetrievalProcessor extends AbstractRetrievalProcessor<Has
Collection<HasTrackedLegContext> trackedLegsWithContext = new ArrayList<>();
int legNumber = 1;
for (TrackedLeg trackedLeg : element.getTrackedRace().getTrackedLegs()) {
if (isAborted()) {
break;
}
HasTrackedLegContext trackedLegWithContext = new TrackedLegWithContext(element, trackedLeg, legNumber);
trackedLegsWithContext.add(trackedLegWithContext);
legNumber++;
@@ -25,7 +25,13 @@ public class TrackedRaceRetrievalProcessor extends AbstractRetrievalProcessor<Ha
protected Iterable<HasTrackedRaceContext> retrieveData(HasLeaderboardContext element) {
Collection<HasTrackedRaceContext> trackedRacesWithContext = new ArrayList<>();
for (RaceColumn raceColumn : element.getLeaderboard().getRaceColumns()) {
if (isAborted()) {
break;
}
for (Fleet fleet : raceColumn.getFleets()) {
if (isAborted()) {
break;
}
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
Regatta regatta = trackedRace.getTrackedRegatta().getRegatta();
@@ -33,6 +33,9 @@ public class WindFixRetrievalProcessor extends AbstractRetrievalProcessor<HasWin
windTrack.lockForRead();
try {
for (final Wind wind : windTrack.getFixes()) {
if (isAborted()) {
break;
}
windFixesWithContext.add(new WindFixWithContext(element.getTrackedRaceContext(), wind, element.getWindSourceType()));
}
} finally {
@@ -31,6 +31,9 @@ public class WindTrackRetrievalProcessor extends AbstractRetrievalProcessor<HasT
Collection<HasWindTrackContext> windTracksWithContext = new ArrayList<>();
final TrackedRace trackedRace = element.getTrackedRace();
for (final WindSource windSource : trackedRace.getWindSources()) {
if (isAborted()) {
break;
}
if (!trackedRace.getWindSourcesToExclude().contains(windSource)) {
final WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource);
windTracksWithContext.add(new WindTrackWithContext(element, windTrack, windSource));
@@ -64,6 +64,9 @@ public abstract class AbstractParallelAverageAggregationProcessor<T extends Comp
Map<GroupKey, T> minAggregation = minAggregationProcessor.getResult();
Map<GroupKey, T> maxAggregation = maxAggregationProcessor.getResult();
for (Entry<GroupKey, T> sumAggregationEntry : sumAggregation.entrySet()) {
if (isAborted()) {
break;
}
GroupKey key = sumAggregationEntry.getKey();
result.put(key, new AverageWithStatsImpl<>(
/* average */ divide(sumAggregationEntry.getValue(), elementAmountPerKey.get(key).longValue()),
@@ -19,8 +19,6 @@ public abstract class AbstractParallelSumAggregationProcessor<T> extends
super(executor, resultReceivers, "Sum");
results = new HashMap<>();
}
protected abstract T add(T t1, T t2);
@Override
protected void handleElement(GroupedDataEntry<T> element) {
@@ -31,6 +29,8 @@ public abstract class AbstractParallelSumAggregationProcessor<T> extends
results.put(key, add(results.get(key), element.getDataEntry()));
}
}
protected abstract T add(T t1, T t2);
@Override
protected Map<GroupKey, T> getResult() {
@@ -47,6 +47,9 @@ public class ParallelBearingAverageDegreesAggregationProcessor
protected Map<GroupKey, Double> aggregateResult() {
Map<GroupKey, Double> result = new HashMap<>();
for (Entry<GroupKey, BearingCluster> clusterEntry : results.entrySet()) {
if (isAborted()) {
break;
}
GroupKey key = clusterEntry.getKey();
result.put(key, clusterEntry.getValue().getAverage().getDegrees());
}
@@ -50,6 +50,9 @@ public class ParallelDistanceMedianAggregationProcessor
protected Map<GroupKey, Distance> aggregateResult() {
Map<GroupKey, Distance> result = new HashMap<>();
for (Entry<GroupKey, List<Distance>> groupedValuesEntry : groupedValues.entrySet()) {
if (isAborted()) {
break;
}
result.put(groupedValuesEntry.getKey(), getMedianOf(groupedValuesEntry.getValue()));
}
return result;
@@ -4,17 +4,14 @@ import com.sap.sailing.datamining.data.HasLeaderboardContext;
import com.sap.sailing.datamining.data.HasLeaderboardGroupContext;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.polars.PolarDataService;
public class LeaderboardWithContext implements HasLeaderboardContext {
private final Leaderboard leaderboard;
private final HasLeaderboardGroupContext leaderboardGroupContext;
private final PolarDataService polarDataService;
public LeaderboardWithContext(Leaderboard leaderboard, HasLeaderboardGroupContext leaderboardGroupContext, PolarDataService polarDataService) {
public LeaderboardWithContext(Leaderboard leaderboard, HasLeaderboardGroupContext leaderboardGroupContext) {
this.leaderboard = leaderboard;
this.leaderboardGroupContext = leaderboardGroupContext;
this.polarDataService = polarDataService;
}
public HasLeaderboardGroupContext getLeaderboardGroupContext() {
@@ -31,11 +28,6 @@ public class LeaderboardWithContext implements HasLeaderboardContext {
return getLeaderboard().getBoatClass();
}
@Override
public PolarDataService getPolarDataService() {
return polarDataService;
}
@Override
public String getName() {
return getLeaderboard().getName();
@@ -1,5 +1,9 @@
package com.sap.sailing.datamining.impl.data;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.sap.sailing.datamining.Activator;
@@ -25,9 +29,12 @@ import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.WindPositionMode;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
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.MillisecondsDurationImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.datamining.data.Cluster;
import com.sap.sse.datamining.shared.impl.dto.ClusterDTO;
@@ -240,50 +247,56 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
@Override
public int getNumberOfManeuvers() {
return getNumberOfTacks() + getNumberOfJibes();
Set<ManeuverType> maneuverTypes = new HashSet<>();
maneuverTypes.add(ManeuverType.TACK);
maneuverTypes.add(ManeuverType.JIBE);
return getNumberOf(maneuverTypes);
}
@Override
public int getNumberOfTacks() {
return getNumberOf(ManeuverType.TACK);
return getNumberOf(Collections.singleton(ManeuverType.TACK));
}
@Override
public int getNumberOfJibes() {
return getNumberOf(ManeuverType.JIBE);
return getNumberOf(Collections.singleton(ManeuverType.JIBE));
}
@Override
public int getNumberOfPenaltyCircles() {
return getNumberOf(ManeuverType.PENALTY_CIRCLE);
return getNumberOf(Collections.singleton(ManeuverType.PENALTY_CIRCLE));
}
private int getNumberOf(ManeuverType maneuverType) {
private int getNumberOf(Set<ManeuverType> maneuverTypes) {
int number = 0;
TrackedRace trackedRace = getTrackedRace();
if (trackedRace != null) {
TimePoint from = null;
TimePoint to = null;
Competitor competitor = getCompetitor();
Course course = trackedRace.getRace().getCourse();
Waypoint startWaypoint = course.getFirstWaypoint();
MarkPassing startPassing = trackedRace.getMarkPassing(getCompetitor(), startWaypoint);
TimePoint start = startPassing != null ? startPassing.getTimePoint() : trackedRace.getStartOfRace();
List<Waypoint> waypoints = Util.createList(course.getWaypoints());
Waypoint finishWaypoint = course.getLastWaypoint();
MarkPassing finishPassing = trackedRace.getMarkPassing(getCompetitor(), finishWaypoint);
TimePoint end;
if (finishPassing != null) {
end = finishPassing.getTimePoint();
} else {
end = trackedRace.getEndOfRace();
if (end == null) {
TimePoint endOfTracking = trackedRace.getEndOfTracking();
TimePoint now = MillisecondsTimePoint.now();
end = endOfTracking != null && endOfTracking.before(now) ? endOfTracking : now;
int fromIndex = 0;
while (fromIndex < waypoints.size()) {
MarkPassing markPassing = trackedRace.getMarkPassing(competitor, waypoints.get(fromIndex));
TimePoint passingTime = markPassing != null ? markPassing.getTimePoint() : null;
if (passingTime != null) {
if (from == null) {
from = passingTime;
} else {
to = passingTime;
}
}
fromIndex++;
}
for (Maneuver maneuver : trackedRace.getManeuvers(getCompetitor(), start, end, false)) {
if (maneuver.getType() == maneuverType) {
number++;
if (from != null && to != null) {
for (Maneuver maneuver : trackedRace.getManeuvers(getCompetitor(), from, to, false)) {
if (maneuverTypes.contains(maneuver.getType())) {
number++;
}
}
}
}
@@ -346,4 +359,18 @@ public class RaceOfCompetitorWithContext implements HasRaceOfCompetitorContext {
return distance / length;
}
@Override
public Duration getDuration() {
Duration duration = null;
TrackedRace race = getTrackedRace();
Course course = race.getRace().getCourse();
MarkPassing startPassing = race.getMarkPassing(competitor, course.getFirstWaypoint());
MarkPassing finishPassing = race.getMarkPassing(competitor, course.getLastWaypoint());
if (startPassing != null && finishPassing != null) {
long durationMillis = finishPassing.getTimePoint().asMillis() - startPassing.getTimePoint().asMillis();
duration = new MillisecondsDurationImpl(durationMillis);
}
return duration;
}
}
@@ -17,8 +17,10 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.LineDetails;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sse.common.Duration;
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;
public class TrackedRaceWithContext implements HasTrackedRaceContext {
@@ -113,6 +115,26 @@ public class TrackedRaceWithContext implements HasTrackedRaceContext {
public Boolean isTracked() {
return getTrackedRace().hasStarted(MillisecondsTimePoint.now());
}
@Override
public Duration getDuration() {
Duration duration = null;
TrackedRace race = getTrackedRace();
TimePoint start = race.getStartOfRace();
if (start == null) {
start = race.getStartOfTracking();
}
if (start != null) {
TimePoint end = race.getEndOfRace();
if (end == null) {
end = race.getEndOfTracking();
}
if (end != null) {
duration = new MillisecondsDurationImpl(end.asMillis() - start.asMillis());
}
}
return duration;
}
@Override
public int getNumberOfCompetitorFixes() {
@@ -130,11 +130,14 @@ public class IncrementalManeuverComputationTest extends AbstractManeuverDetectio
performanceMeasurementStartedAt = System.currentTimeMillis();
List<Maneuver> normallyDetectedManeuvers = normalManeuverDetector.detectManeuvers();
long millisForNormalManeuverDetection = System.currentTimeMillis() - performanceMeasurementStartedAt;
int performanceBenefitOfIncrementalManeuverDetectionInPercent = (int) ((1.0 * (millisForNormalManeuverDetection - millisForIncrementalManeuverDetection)
/ millisForNormalManeuverDetection) * 100);
assertEquals("Incrementally calculated maneuvers differ from normally calculated maneuvers",
normallyDetectedManeuvers, incrementallyDetectedManeuvers);
assertTrue(
"Incremental maneuver detection was not 30% faster in detecting maneuvers incrementally, than the full maneuver detection",
millisForIncrementalManeuverDetection * 1.3 < millisForNormalManeuverDetection);
"Incremental maneuver detection was not 20% faster in detecting maneuvers incrementally, than the full maneuver detection. The actual performance benefit was: "
+ performanceBenefitOfIncrementalManeuverDetectionInPercent + "%",
performanceBenefitOfIncrementalManeuverDetectionInPercent >= 20);
}
}
@@ -15,6 +15,7 @@ import com.sap.sailing.domain.tractracadapter.LoadingQueueDoneCallBack;
import com.sap.sailing.domain.tractracadapter.Receiver;
import com.sap.sse.common.Util;
import com.tractrac.model.lib.api.route.IControlRoute;
import com.tractrac.model.lib.api.route.IPathRoute;
import com.tractrac.subscription.lib.api.control.IControlRouteChangeListener;
public class RouteAssemblyTest extends AbstractTracTracLiveTest {
@@ -66,6 +67,11 @@ public class RouteAssemblyTest extends AbstractTracTracLiveTest {
first = false;
}
}
@Override
public void gotRouteChange(IPathRoute pathRoute, long timeStamp) {
// will never be invoked for sailing events
}
});
}
@@ -37,6 +37,7 @@ import com.tractrac.model.lib.api.event.IEvent;
import com.tractrac.model.lib.api.event.IRace;
import com.tractrac.model.lib.api.route.IControl;
import com.tractrac.model.lib.api.route.IControlRoute;
import com.tractrac.model.lib.api.route.IPathRoute;
import com.tractrac.model.lib.api.route.IRoute;
import com.tractrac.subscription.lib.api.IEventSubscriber;
import com.tractrac.subscription.lib.api.IRaceSubscriber;
@@ -97,6 +98,13 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<IControlRoute,
public void gotRouteChange(IControlRoute controlRoute, long timeStamp) {
enqueue(new Triple<IControlRoute, Long, Void>(controlRoute, timeStamp, null));
}
@Override
public void gotRouteChange(IPathRoute pathRoute, long timeStamp) {
// will never be invoked for sailing events; Jorge Llodra (2018-07-30):
// "The IControlRouteChangeListener has been extended adding a new method to get updates of a
// IPathRoute. If you are managing "sailing events" this method will never be invoked."
}
};
}
@@ -100,9 +100,9 @@ public interface CompleteManeuverCurveWithEstimationData extends Timed, Position
Distance getDistanceToClosestMark();
Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees();
Double getTargetTackAngleInDegrees();
Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees();
Double getTargetJibeAngleInDegrees();
/**
* Gets whether a mark was crossed within the maneuver curve.
@@ -27,14 +27,15 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
private final boolean markPassing;
private final Position position;
private final Distance distanceToClosestMark;
private final Double deviationOfManeuverAngleFromTargetTackAngleInDegrees;
private final Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
private final Double targetTackAngleInDegrees;
private final Double targetJibeAngleInDegrees;
public CompleteManeuverCurveWithEstimationDataImpl(Position position, ManeuverMainCurveWithEstimationData mainCurve,
ManeuverCurveWithUnstableCourseAndSpeedWithEstimationData curveWithUnstableCourseAndSpeed, Wind wind,
int tackingCount, int jibingCount, boolean maneuverStartsByRunningAwayFromWind,
Bearing relativeBearingToNextMarkBeforeManeuver, Bearing relativeBearingToNextMarkAfterManeuver,
boolean markPassing, Distance distanceToClosestMark, Double deviationOfManeuverAngleFromTargetTackAngleInDegrees, Double deviationOfManeuverAngleFromTargetJibeAngleInDegrees) {
boolean markPassing, Distance distanceToClosestMark, Double targetTackAngleInDegrees,
Double targetJibeAngleInDegrees) {
this.position = position;
this.mainCurve = mainCurve;
this.curveWithUnstableCourseAndSpeed = curveWithUnstableCourseAndSpeed;
@@ -46,8 +47,8 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
this.relativeBearingToNextMarkAfterManeuver = relativeBearingToNextMarkAfterManeuver;
this.markPassing = markPassing;
this.distanceToClosestMark = distanceToClosestMark;
this.deviationOfManeuverAngleFromTargetTackAngleInDegrees = deviationOfManeuverAngleFromTargetTackAngleInDegrees;
this.deviationOfManeuverAngleFromTargetJibeAngleInDegrees = deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
this.targetTackAngleInDegrees = targetTackAngleInDegrees;
this.targetJibeAngleInDegrees = targetJibeAngleInDegrees;
}
@Override
@@ -99,20 +100,20 @@ public class CompleteManeuverCurveWithEstimationDataImpl implements CompleteMane
public Position getPosition() {
return position;
}
@Override
public Distance getDistanceToClosestMark() {
return distanceToClosestMark;
}
@Override
public Double getDeviationOfManeuverAngleFromTargetTackAngleInDegrees() {
return deviationOfManeuverAngleFromTargetTackAngleInDegrees;
public Double getTargetTackAngleInDegrees() {
return targetTackAngleInDegrees;
}
@Override
public Double getDeviationOfManeuverAngleFromTargetJibeAngleInDegrees() {
return deviationOfManeuverAngleFromTargetJibeAngleInDegrees;
public Double getTargetJibeAngleInDegrees() {
return targetJibeAngleInDegrees;
}
}
@@ -278,7 +278,8 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
stepWithHighestSpeed.getSpeedWithBearing(), stepWithHighestSpeed.getTimePoint(),
maneuverCurve.getMainCurveBoundaries().getTimePoint(),
maneuverCurve.getMainCurveBoundaries().getMaxTurningRateInDegreesPerSecond(), courseAtMaxTurningRate,
distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(), distanceSailedIfNotManeuvering,
distanceSailedWithinManeuver, projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(),
distanceSailedIfNotManeuvering,
projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(),
Math.abs(maneuverCurve.getMainCurveBoundaries().getDirectionChangeInDegrees())
/ maneuverCurve.getMainCurveBoundaries().getDuration().asSeconds(),
@@ -338,9 +339,9 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
gpsFixesCountFromPreviousManeuver, durationAndAvgSpeedWithBearingAfter.getB(),
durationAndAvgSpeedWithBearingAfter.getA(), gpsFixesCountToNextManeuver, distanceSailedWithinManeuver,
projectedManeuverLoss.getDistanceSailedProjectedOnMiddleManeuverAngle(), distanceSailedIfNotManeuvering,
projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(), gpsFixCountWithinWholeCurve,
longestGpsFixIntervalBetweenTwoFixes, intervalBetweenLastFixOfCurveAndNextFix,
intervalBetweenFirstFixOfCurveAndPreviousFix);
projectedManeuverLoss.getDistanceSailedIfNotManeuveringProjectedOnMiddleManeuverAngle(),
gpsFixCountWithinWholeCurve, longestGpsFixIntervalBetweenTwoFixes,
intervalBetweenLastFixOfCurveAndNextFix, intervalBetweenFirstFixOfCurveAndPreviousFix);
TimePoint maneuverTimePoint = maneuverCurve.getMainCurveBoundaries().getTimePoint();
Position maneuverPosition = maneuverDetector.track.getEstimatedPosition(maneuverTimePoint,
/* extrapolate */false);
@@ -357,8 +358,8 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
.getManeuverCurveWithStableSpeedAndCourseBoundaries().getSpeedWithBearingAfter().getBearing());
BoatClass boatClass = maneuverDetector.trackedRace.getRace().getBoatOfCompetitor(maneuverDetector.competitor)
.getBoatClass();
Double deviationFromTackAngle = null;
Double deviationFromJibeAngle = null;
Double targetTackAngle = null;
Double targetJibeAngle = null;
Speed boatSpeed = curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore()
.compareTo(curveWithUnstableCourseAndSpeed.getSpeedWithBearingAfter()) < 0
? curveWithUnstableCourseAndSpeed.getSpeedWithBearingBefore()
@@ -369,11 +370,11 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
SpeedWithBearingWithConfidence<Void> closestJibeTwa = polarDataService.getClosestTwaTws(ManeuverType.JIBE,
boatSpeed, curveWithUnstableCourseAndSpeed.getDirectionChangeInDegrees(), boatClass);
if (closestTackTwa != null) {
deviationFromTackAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
targetTackAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
closestTackTwa.getObject().getBearing().getDegrees(), ManeuverType.TACK);
}
if (closestJibeTwa != null) {
deviationFromJibeAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
targetJibeAngle = polarDataService.getManeuverAngleInDegreesFromTwa(
closestJibeTwa.getObject().getBearing().getDegrees(), ManeuverType.JIBE);
}
}
@@ -383,7 +384,7 @@ public class ManeuverDetectorWithEstimationDataSupportDecoratorImpl
curveWithUnstableCourseAndSpeed, wind, numberOfTacks, numberOfJibes,
maneuverStartsByRunningAwayFromWind, relativeBearingToNextMarkPassingBeforeManeuver,
relativeBearingToNextMarkPassingAfterManeuver, maneuverCurve.isMarkPassing(), closestDistanceToMark,
deviationFromTackAngle, deviationFromJibeAngle);
targetTackAngle, targetJibeAngle);
}
public Distance getClosestDistanceToMark(TimePoint timePoint) {
@@ -53,6 +53,13 @@ public interface CandidateFinder {
*/
Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceStartTimeChange();
/**
* Notifies this finder about the race's start of tracking time having changed. In case of a race that infers
* the race start time from the start mark passings, a change in start of tracking needs to adjust the time range
* in which candidates are considered valid.
*/
Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterStartOfTrackingChange();
/**
* Notifies this finder about the race's finished time having changed. The candidates collections are adjusted
* accordingly: new candidates may be added if the finished time was moved to a later point in time and therefore
@@ -195,6 +195,25 @@ public class MarkPassingUpdateListener extends AbstractRaceChangeListener {
});
}
@Override
public void startOfTrackingChanged(TimePoint oldStartOfTracking, TimePoint newStartOfTracking) {
markPassingCalculator.enqueueUpdate(new StorePositionUpdateStrategy() {
@Override
public void storePositionUpdate(Map<Competitor, List<GPSFix>> competitorFixes,
Map<Mark, List<GPSFix>> markFixes, List<Waypoint> addedWaypoints, List<Waypoint> removedWaypoints,
IntHolder smallestChangedWaypointIndex,
List<Triple<Competitor, Integer, TimePoint>> fixedMarkPassings,
List<Pair<Competitor, Integer>> removedMarkPassings,
List<Pair<Competitor, Integer>> suppressedMarkPassings, List<Competitor> unSuppressedMarkPassings, CandidateFinder candidateFinder, CandidateChooser candidateChooser) {
final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> newAndRemovedCandidatesPerCompetitor =
candidateFinder.getCandidateDeltasAfterStartOfTrackingChange();
for (final Entry<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> i : newAndRemovedCandidatesPerCompetitor.entrySet()) {
candidateChooser.calculateMarkPassDeltas(i.getKey(), i.getValue().getA(), i.getValue().getB());
}
}
});
}
@Override
public void finishedTimeChanged(TimePoint oldFinishedTime, TimePoint newFinishedTime) {
markPassingCalculator.enqueueUpdate(new StorePositionUpdateStrategy() {
@@ -37,6 +37,7 @@ import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
import com.sap.sailing.domain.tracking.GPSFixTrack;
import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.impl.MarkPositionAtTimePointCacheImpl;
import com.sap.sailing.domain.tracking.impl.TimedComparator;
import com.sap.sse.common.Bearing;
@@ -1455,12 +1456,26 @@ public class CandidateFinderImpl implements CandidateFinder {
/**
* If the {@link #race}'s regatta is configured to infer the start times from start mark passings then {@code null}
* must be tolerated as a value for {@code from}, leading to an open interval starting at the
* {@link TimePoint#BeginningOfTime beginning of time}. However, if the start time is expected to be set and not
* inferred, mark passings need to be detected only from the start minus some tolerance interval. In this case,
* an interval that has {@code null} as its {@code from} time point and thus is considered empty will be returned.
* It hence returns {@code null} from its {@link TimeRangeWithNullStartMeaningEmpty#getTimeRangeOrNull()} method.
* {@link TrackedRace#getStartOfTracking()} or, if not set, the {@link TimePoint#BeginningOfTime beginning of time}.
* However, if the start time is expected to be set and not inferred, mark passings need to be detected only from
* the start minus some tolerance interval. In this case, an interval that has {@code null} as its {@code from} time
* point and thus is considered empty will be returned. It hence returns {@code null} from its
* {@link TimeRangeWithNullStartMeaningEmpty#getTimeRangeOrNull()} method.
*/
private TimeRangeWithNullStartMeaningEmpty getTimeRangeOrNull(TimePoint from, TimePoint to) {
final TimePoint effectiveFrom = getEffectiveFrom(from);
return new TimeRangeWithNullStartMeaningEmpty(effectiveFrom, to);
}
/**
* If the {@link #race}'s regatta is configured to infer the start times from start mark passings then {@code null}
* must be tolerated as a value for {@code from}, leading to an open interval starting at the
* {@link TrackedRace#getStartOfTracking()} or, if not set, the {@link TimePoint#BeginningOfTime beginning of time}.
* However, if the start time is expected to be set and not inferred, mark passings need to be detected only from
* the start minus some tolerance interval. In this case, for an interval that has {@code null} as its {@code from} time
* point and thus is considered empty, {@code null} will be returned.
*/
private TimePoint getEffectiveFrom(TimePoint from) {
final TimePoint effectiveFrom;
if (from == null && race.getTrackedRegatta().getRegatta().useStartTimeInference()) {
// need to check the whole track to be able to find start mark passings
@@ -1470,15 +1485,22 @@ public class CandidateFinderImpl implements CandidateFinder {
} else {
effectiveFrom = from;
}
return new TimeRangeWithNullStartMeaningEmpty(effectiveFrom, to);
return effectiveFrom;
}
@Override
public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceStartTimeChange() {
final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
final TimePoint newNonInferredStartTime = race.getStartOfRace(/* inferred */ false);
final TimePoint newTimePointWhenToStartConsideringCandidates = getTimePointWhenToStartConsideringCandidates(newNonInferredStartTime);
final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newTimePointWhenToStartConsideringCandidates);
final TimePoint newEffectiveTimePointWhenToStartConsideringCandidates = getEffectiveFrom(newTimePointWhenToStartConsideringCandidates);
final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newEffectiveTimePointWhenToStartConsideringCandidates);
return getCandidateDeltasAfterTimingChange(newEffectiveTimePointWhenToStartConsideringCandidates, newTimeRange);
}
private Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterTimingChange(
final TimePoint newTimePointWhenToStartConsideringCandidates,
final TimeRangeWithNullStartMeaningEmpty newTimeRange) {
final Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> result;
if (!Util.equalsWithNull(newTimeRange, timeRangeForValidCandidates)) {
if (newTimeRange.getTimeRangeOrNull() == null) {
result = clearAllCandidates();
@@ -1499,6 +1521,15 @@ public class CandidateFinderImpl implements CandidateFinder {
return result;
}
@Override
public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterStartOfTrackingChange() {
final TimePoint newNonInferredStartTime = race.getStartOfRace(/* inferred */ false);
final TimePoint newTimePointWhenToStartConsideringCandidates = getTimePointWhenToStartConsideringCandidates(newNonInferredStartTime);
final TimePoint newEffectiveTimePointWhenToStartConsideringCandidates = getEffectiveFrom(newTimePointWhenToStartConsideringCandidates);
final TimeRangeWithNullStartMeaningEmpty newTimeRange = timeRangeForValidCandidates.getWithNewFrom(newEffectiveTimePointWhenToStartConsideringCandidates);
return getCandidateDeltasAfterTimingChange(newEffectiveTimePointWhenToStartConsideringCandidates, newTimeRange);
}
@Override
public Map<Competitor, Pair<Iterable<Candidate>, Iterable<Candidate>>> getCandidateDeltasAfterRaceFinishedTimeChange(
TimePoint oldFinishedTime, TimePoint newFinishedTime) {
@@ -205,6 +205,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
owner.addListener(this);
}
@FunctionalInterface
private interface CrossTrackErrorMeterRetriever {
double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry);
}
@@ -220,12 +221,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
*/
public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
boolean waitForLatest) throws NoWindException {
CrossTrackErrorMeterRetriever absoluteMetersRetriever = new CrossTrackErrorMeterRetriever() {
@Override
public double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry) {
return cacheEntry.getAbsoluteDistanceInMetersSumFromStart();
}
};
CrossTrackErrorMeterRetriever absoluteMetersRetriever = cacheEntry->cacheEntry.getAbsoluteDistanceInMetersSumFromStart();
return getAbsoluteOrSignedAverageCrossTrackError(competitor, from, to, upwindOnly, waitForLatest, absoluteMetersRetriever);
}
@@ -240,20 +236,15 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
*/
public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly,
boolean waitForLatest) throws NoWindException {
CrossTrackErrorMeterRetriever signedMetersRetriever = new CrossTrackErrorMeterRetriever() {
@Override
public double getDistanceInMetersSumFromStart(CrossTrackErrorSumAndNumberOfFixes cacheEntry) {
return cacheEntry.getSignedDistanceInMetersSumFromStart();
}
};
CrossTrackErrorMeterRetriever signedMetersRetriever = cacheEntry->cacheEntry.getSignedDistanceInMetersSumFromStart();
return getAbsoluteOrSignedAverageCrossTrackError(competitor, from, to, upwindOnly, waitForLatest, signedMetersRetriever);
}
/**
* @param absoluteMetersRetriever determines whether the absolute or signed cross track error will be aggregated
* @param absoluteOrSignedMetersRetriever determines whether the absolute or signed cross track error will be aggregated
*/
private Distance getAbsoluteOrSignedAverageCrossTrackError(Competitor competitor, TimePoint from, TimePoint to,
boolean upwindOnly, boolean waitForLatest, CrossTrackErrorMeterRetriever absoluteMetersRetriever)
boolean upwindOnly, boolean waitForLatest, CrossTrackErrorMeterRetriever absoluteOrSignedMetersRetriever)
throws NoWindException {
Track<CrossTrackErrorSumAndNumberOfFixes> cacheForCompetitor = cachePerCompetitor.get(competitor, waitForLatest);
double distanceInMeters = 0;
@@ -268,7 +259,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
final MarkPassing legStartMarkPassing = owner.getMarkPassing(competitor, leg.getFrom());
if (legStartMarkPassing != null) {
if (!upwindOnly || trackedLeg.getLegType(legStartMarkPassing.getTimePoint()) == LegType.UPWIND) {
TimePoint start;
final TimePoint start;
final TimePoint legStart = legStartMarkPassing.getTimePoint();
if (legStart.compareTo(from) < 0) {
// the interval requested starts after this leg's start:
@@ -277,7 +268,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
start = legStart;
}
final MarkPassing legEndMarkPassing = owner.getMarkPassing(competitor, leg.getTo());
TimePoint end;
final TimePoint end;
if (legEndMarkPassing == null || legEndMarkPassing.getTimePoint().compareTo(to) >= 0) {
// no next mark passing, or next mark passing is beyond the "to" time point; aggregate up to "to"
end = to;
@@ -294,7 +285,7 @@ public class CrossTrackErrorCache extends AbstractRaceChangeListener {
}
CrossTrackErrorSumAndNumberOfFixes endAggregate = cacheForCompetitor.getLastFixAtOrBefore(end);
if (endAggregate != null) {
distanceInMeters += absoluteMetersRetriever.getDistanceInMetersSumFromStart(endAggregate) - absoluteMetersRetriever.getDistanceInMetersSumFromStart(startAggregate);
distanceInMeters += absoluteOrSignedMetersRetriever.getDistanceInMetersSumFromStart(endAggregate) - absoluteOrSignedMetersRetriever.getDistanceInMetersSumFromStart(startAggregate);
count += endAggregate.getFixCountFromStart() - startAggregate.getFixCountFromStart();
startAggregate = endAggregate;
}
@@ -1,10 +1,11 @@
package com.sap.sailing.gwt.autoplay.client.configs;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.user.client.Window;
import com.sap.sailing.gwt.autoplay.client.app.AutoPlayClientFactory;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings;
import com.sap.sse.gwt.settings.SettingsToUrlSerializer;
import com.sap.sse.gwt.settings.UrlBuilderUtil;
@@ -21,7 +22,7 @@ public abstract class AutoPlayConfiguration {
public void openSettingsDialog(EventDTO selectedEvent, StrippedLeaderboardDTO leaderboard,
OnSettingsCallback holder, PerspectiveCompositeSettings<?> settings, AutoPlayContextDefinition apcd,
UserService userService) {
Window.alert("This configuration does not have settings");
Notification.notify("This configuration does not have settings", NotificationType.WARNING);
}
/**
@@ -6,8 +6,13 @@
<div class="innerContent">
<h5 class="articleSubheadline">July 2018</h5>
<ul class="bulletList">
<li>In <tt>RaceBoard.html</tt> there is a new feature for maneuver loss visualization. There is a setting in the map settings and in the maneuver pop up.
<li>The Maneuver Table now uses the same color coding for competitors as the leaderboard to help
recognize competitor tracks for selected maneuvers more easily.</li>
<li>In <tt>RaceBoard.html</tt> there is a new feature for maneuver loss visualization. There is a setting in the map settings and in the maneuver pop up.</li>
<li>In <tt>RaceBoard.html</tt> when zooming into a specific time range, the time slider will provide a "reset zoom" button in expanded mode.</li>
<li>Issues with sporadic incorrect zoom/pan states in the Race Board / race viewer have been fixed.</li>
<li>Fixed an issue with the "Winning Lanes" mode for large races that could lead to full tails for
all competitors to be loaded instead of only the ones for the podium competitors.</li>
</ul>
<h5 class="articleSubheadline">June 2018</h5>
@@ -180,18 +180,18 @@
text-overflow: ellipsis;
}
.regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
.regattacompetition_phase_fleet_race_title_big {
width: 27%;
}
@media (min-width: 375px) {
.regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
.regattacompetition_phase_fleet_race_title_big {
width: 33%;
}
}
@media (min-width: 700px) {
.regattacompetition_phase_fleetfullwidth, .regattacompetition_phase_fleet_race_title {
.regattacompetition_phase_fleet_race_title_big {
width: 40%;
}
}
@@ -17,6 +17,9 @@ import com.sap.sailing.gwt.home.shared.partials.regattacompetition.RegattaCompet
public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
private static RegattaCompetitionFleetUiBinder uiBinder = GWT.create(RegattaCompetitionFleetUiBinder.class);
private int fleetCount = -1;
private RegattaCompetitionFleetRace raceView;
interface RegattaCompetitionFleetUiBinder extends UiBinder<Widget, RegattaCompetitionFleet> {
}
@@ -32,8 +35,9 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
@Override
public RegattaCompetitionRaceView addRaceView(SimpleRaceMetadataDTO race, RegattaCompetitionPresenter presenter) {
RegattaCompetitionFleetRace raceView = new RegattaCompetitionFleetRace(race, presenter);
raceView = new RegattaCompetitionFleetRace(race, presenter);
raceContainerUi.add(raceView);
updateRaceViewIfReady();
return raceView;
}
@@ -42,6 +46,8 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
getElement().getStyle().setWidth(100.0 / fleetCount, Unit.PCT);
setStyleName(local_res.css().regattacompetition_phase_fleetfullwidth(), fleetCount < 2);
setStyleName(local_res.css().regattacompetition_phase_fleetcompact(), fleetCount > 4);
this.fleetCount = fleetCount;
updateRaceViewIfReady();
}
@Override
@@ -64,5 +70,10 @@ public class RegattaCompetitionFleet extends AbstractRegattaCompetitionFleet {
protected Element getFleetCornerUiElement() {
return fleetCornerUi;
}
private void updateRaceViewIfReady() {
if (raceView != null && fleetCount > 1) {
raceView.removeBigRaceTitleCSS();
}
}
}
@@ -65,5 +65,9 @@ public class RegattaCompetitionFleetRace extends AbstractRegattaCompetitionFleet
protected String getRaceUntrackedStyleName() {
return local_res.css().regattacompetition_phase_fleet_raceuntracked();
}
public void removeBigRaceTitleCSS() {
raceNameUi.removeClassName(local_res.css().regattacompetition_phase_fleet_race_title_big());
}
}
@@ -1,15 +1,15 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattacompetition.RegattaCompetitionResources" />
<div class="{local_res.css.regattacompetition_phase_fleet_race}" style="display:block; text-decoration:none;">
<div class="{local_res.css.regattacompetition_phase_fleet_race_title}" ui:field="raceNameUi"></div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_subtitle}">
<div class="{local_res.css.regattacompetition_phase_fleet_race_state}" ui:field="raceStateUi"></div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_date}" ui:field="raceDateUi"></div>
</div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_title} {local_res.css.regattacompetition_phase_fleet_race_title_big}" ui:field="raceNameUi"></div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_subtitle}">
<div class="{local_res.css.regattacompetition_phase_fleet_race_state}" ui:field="raceStateUi"></div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_date}" ui:field="raceDateUi"></div>
</div>
<div class="{local_res.css.regattacompetition_phase_fleet_race_arrow}"></div>
</div>
</div>
</ui:UiBinder>
@@ -33,5 +33,6 @@ public interface RegattaCompetitionResources extends SharedHomeResources {
String regattacompetition_phase_fleet_raceplanned();
String regattacompetition_phase_fleet_race_state();
String regattacompetition_phase_fleet_race_date();
String regattacompetition_phase_fleet_race_title_big();
}
}
@@ -1,6 +1,5 @@
package com.sap.sailing.gwt.home.shared.places.user.profile.preferences;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
import com.sap.sailing.gwt.home.communication.user.profile.CompetitorSuggestionResult;
@@ -17,6 +16,8 @@ import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggested
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.dispatch.shared.commands.VoidResult;
/**
@@ -95,7 +96,7 @@ public class UserPreferencesPresenter<C extends ClientFactoryWithDispatch & Erro
new AsyncCallback<CompetitorSuggestionResult>() {
@Override
public void onFailure(Throwable caught) {
Window.alert("Error while loading competitor suggestion");
Notification.notify("Error while loading competitor suggestion", NotificationType.ERROR);
}
@Override
@@ -6,7 +6,6 @@ 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.http.client.UrlBuilder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
@@ -21,6 +20,8 @@ import com.sap.sailing.gwt.settings.client.regattaoverview.RegattaOverviewContex
import com.sap.sailing.gwt.settings.client.regattaoverview.RegattaRaceStatesSettings;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.settings.SettingsToUrlSerializer;
public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
@@ -60,7 +61,7 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
.deserializeFromCurrentLocation(new RegattaOverviewContextDefinition());
if (regattaOverviewContextDefinition.getEvent() == null) {
Window.alert("Missing parameter");
Notification.notify("Missing parameter", NotificationType.ERROR);
return;
}
@@ -20,7 +20,6 @@ public class GetBoatPositionsAction extends AbstractGetMapRelatedDataAction<Comp
@Override
public void execute(final AsyncCallback<CompactBoatPositionsDTO> callback) {
Map<String, Date> fromByCompetitorIdAsString = new HashMap<String, Date>();
System.out.println(fromByCompetitorIdAsString);
for (Map.Entry<CompetitorDTO, Date> fromEntry : getFrom().entrySet()) {
fromByCompetitorIdAsString.put(fromEntry.getKey().getIdAsString(), fromEntry.getValue());
}
@@ -22,6 +22,8 @@ import com.sap.sailing.gwt.ui.shared.RaceRecordDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
public abstract class AbstractEventManagementPanel extends AbstractRegattaPanel {
protected final TrackedRacesListComposite trackedRacesListComposite;
@@ -121,7 +123,7 @@ public abstract class AbstractEventManagementPanel extends AbstractRegattaPanel
builder.append(")");
builder.append("\n");
}
Window.alert(builder.toString());
Notification.notify(builder.toString(), NotificationType.ERROR);
result = false;
} else {
result = true;
@@ -8,7 +8,6 @@ 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.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
@@ -25,6 +24,8 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
public abstract class AbstractFileImportWidget extends Composite {
@@ -89,7 +90,7 @@ public abstract class AbstractFileImportWidget extends Composite {
void onFileImportComplete(SubmitCompleteEvent event) {
SensorDataImportResponse importResponse = SensorDataImportResponse.parse(event.getResults());
if (importResponse == null) {
Window.alert(StringMessages.INSTANCE.unexpectedErrorDuringFileImport());
Notification.notify(StringMessages.INSTANCE.unexpectedErrorDuringFileImport(), NotificationType.ERROR);
} else {
SensorDataImportResultsDialog.showResults(importResponse);
if (importResponse.didSucceedImportingAnyFile()) {
@@ -50,6 +50,8 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.FlushableCellTable;
@@ -282,7 +284,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel implement
refreshRaceLog(column, fleet, false);
}
}
Window.alert(stringMessages.raceLogReloaded());
Notification.notify(stringMessages.raceLogReloaded(), NotificationType.ERROR);
}
});
vPanel.add(reloadAllRaceLogs);
@@ -431,7 +433,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel implement
@Override
public void onSuccess(Void result) {
if (showAlerts) {
Window.alert(stringMessages.raceLogReloaded());
Notification.notify(stringMessages.raceLogReloaded(), NotificationType.SUCCESS);
}
}
}));
@@ -13,7 +13,6 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.sap.sailing.domain.common.dto.BoatDTO;
@@ -24,6 +23,8 @@ import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel;
@@ -283,7 +284,7 @@ public class BoatTableWrapper<S extends RefreshableSelectionModel<BoatDTO>> exte
@Override
public void onSuccess(Void result) {
Window.alert(getStringMessages().successfullyAllowedBoatReset(boats.toString()));
Notification.notify(getStringMessages().successfullyAllowedBoatReset(boats.toString()), NotificationType.SUCCESS);
}
});
}
@@ -3,7 +3,6 @@ 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;
@@ -11,6 +10,8 @@ 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.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
public class CompetitorInvitationHelper {
@@ -27,13 +28,13 @@ public class CompetitorInvitationHelper {
public void inviteCompetitors(Set<CompetitorDTO> competitors, String leaderboardName) {
if (competitors.size() == 0){
Window.alert(stringMessages.selectAtLeastOneCompetitorForInvitation());
Notification.notify(stringMessages.selectAtLeastOneCompetitorForInvitation(), NotificationType.ERROR);
} else {
boolean emailProvidedForAll = isEmailProvidedForAll(competitors);
if (emailProvidedForAll) {
openChooseEventDialogAndSendMails(competitors, leaderboardName);
} else {
Window.alert(stringMessages.notAllCompetitorsProvideEmail());
Notification.notify(stringMessages.notAllCompetitorsProvideEmail(), NotificationType.ERROR);
}
}
}
@@ -61,12 +62,12 @@ public class CompetitorInvitationHelper {
@Override
public void onFailure(Throwable caught) {
Window.alert(stringMessages.sendingMailsFailed() + caught.getMessage());
Notification.notify(stringMessages.sendingMailsFailed() + caught.getMessage(), NotificationType.ERROR);
}
@Override
public void onSuccess(Void result) {
Window.alert(stringMessages.sendingMailsSuccessful());
Notification.notify(stringMessages.sendingMailsSuccessful(), NotificationType.SUCCESS);
}
});
}
@@ -14,7 +14,6 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.view.client.CellPreviewEvent;
@@ -32,6 +31,8 @@ import com.sap.sse.common.Color;
import com.sap.sse.common.Util;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel;
@@ -479,7 +480,7 @@ public class CompetitorTableWrapper<S extends RefreshableSelectionModel<Competit
@Override
public void onSuccess(Void result) {
Window.alert(getStringMessages().successfullyAllowedCompetitorReset(competitors.toString()));
Notification.notify(getStringMessages().successfullyAllowedCompetitorReset(competitors.toString()), NotificationType.SUCCESS);
}
});
}
@@ -8,7 +8,6 @@ import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
@@ -24,6 +23,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel;
import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
@@ -96,12 +97,12 @@ public class CompetitorToBoatMappingsDialog extends DataEntryDialog<Map<Competit
if (!isLinkedToBoat(selectedCompetitor, selectedBoat) && !isBoatUsed(selectedBoat)) {
linkBoatToSelectedCompetitor(selectedCompetitor, selectedBoat);
} else {
Window.alert(stringMessages.boatAlreadyLinked());
Notification.notify(stringMessages.boatAlreadyLinked(), NotificationType.ERROR);
}
} else {
// check if boat is already used with another competitor
if (isBoatUsed(selectedBoat)) {
Window.alert(stringMessages.boatAlreadyLinked());
Notification.notify(stringMessages.boatAlreadyLinked(), NotificationType.ERROR);
} else {
linkBoatToSelectedCompetitor(selectedCompetitor, selectedBoat);
}
@@ -3,7 +3,6 @@ package com.sap.sailing.gwt.ui.adminconsole;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -12,6 +11,8 @@ import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sap.sailing.domain.common.impl.DeviceConfigurationQRCodeUtils;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
public class DeviceConfigurationQRIdentifierDialog extends DialogBox {
public static final String rcAppApkPath = "/apps/com.sap.sailing.racecommittee.app.apk";
@@ -38,7 +39,7 @@ public class DeviceConfigurationQRIdentifierDialog extends DialogBox {
@Override
protected String generateEncodedQRCodeContent() {
if (identifierBox.getValue().contains("#")) {
Window.alert(stringMessages.notCapableOfGeneratingACodeForIdentifier());
Notification.notify(stringMessages.notCapableOfGeneratingACodeForIdentifier(), NotificationType.ERROR);
} else if (!identifierBox.getValue().isEmpty() && !serverBox.getValue().isEmpty()) {
String apkUrl = getServerUrlWithoutFinalSlash() + rcAppApkPath;
return DeviceConfigurationQRCodeUtils.composeQRContent(URL.encodeQueryString(identifierBox.getValue()), apkUrl, URL.encodeQueryString(accessToken));
@@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole;
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.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
@@ -11,6 +10,8 @@ import com.google.gwt.user.client.ui.HorizontalPanel;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.shared.UserDTO;
@@ -36,7 +37,7 @@ public class DeviceConfigurationUserDetailComposite extends DeviceConfigurationD
@Override
public void onClick(ClickEvent event) {
if (identifierBox.getValue() == null || identifierBox.getValue().isEmpty()) {
Window.alert(stringMessages.thereIsNoIdentifierSet());
Notification.notify(stringMessages.thereIsNoIdentifierSet(), NotificationType.ERROR);
} else {
UserDTO currentUser = userService.getCurrentUser();
if (currentUser == null) {
@@ -7,7 +7,6 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
@@ -24,6 +23,8 @@ 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;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator;
@@ -148,7 +149,7 @@ public class ExpeditionAllInOneAfterImportHandler {
@Override
public void ok(Set<CompetitorDTO> competitors) {
if (competitors.isEmpty()) {
Window.alert(stringMessages.importCanceledNoCompetitorAdded());
Notification.notify(stringMessages.importCanceledNoCompetitorAdded(), NotificationType.ERROR);
} else {
sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(),
competitors, new AsyncCallback<Void>() {
@@ -337,7 +338,7 @@ public class ExpeditionAllInOneAfterImportHandler {
@Override
public final void cancel() {
Window.alert(stringMessages.importCanceledByUser());
Notification.notify(stringMessages.importCanceledByUser(), NotificationType.WARNING);
}
}
}
@@ -7,7 +7,6 @@ import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
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;
import com.google.gwt.user.client.ui.CheckBox;
@@ -36,6 +35,8 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
@@ -153,7 +154,7 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas
busyIndicator.setBusy(false);
final ExpeditionDataImportResponse response = ExpeditionDataImportResponse.parse(event.getResults());
if (response == null) {
Window.alert(StringMessages.INSTANCE.unexpectedErrorDuringFileImport());
Notification.notify(StringMessages.INSTANCE.unexpectedErrorDuringFileImport(), NotificationType.ERROR);
} else if (response.hasEventId()) {
new ExpeditionAllInOneAfterImportHandler(response.getEventId(), response.getRegattaName(),
response.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceEntries(),
@@ -40,6 +40,8 @@ import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.IconResources;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.celltable.ImagesBarCell;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
@@ -258,10 +260,10 @@ public class IgtimiAccountsPanel extends FlowPanel {
@Override
public void onSuccess(Boolean result) {
if (result) {
Window.alert(stringMessages.successfullyAuthorizedAccessToIgtimiUser(editedObject.geteMail()));
Notification.notify(stringMessages.successfullyAuthorizedAccessToIgtimiUser(editedObject.geteMail()), NotificationType.SUCCESS);
updateAllAccounts(sailingService, filterAccountsPanel, stringMessages, errorReporter);
} else {
Window.alert(stringMessages.couldNotAuthorizedAccessToIgtimiUser(editedObject.geteMail()));
Notification.notify(stringMessages.couldNotAuthorizedAccessToIgtimiUser(editedObject.geteMail()), NotificationType.ERROR);
}
}
});
@@ -328,7 +330,7 @@ public class IgtimiAccountsPanel extends FlowPanel {
@Override
public void onSuccess(Void result) {
Window.alert(stringMessages.successfullyRemoveIgtimiAccount(eMailOfAccountToRemove));
Notification.notify(stringMessages.successfullyRemoveIgtimiAccount(eMailOfAccountToRemove), NotificationType.INFO);
removeFrom.getList().remove(eMailOfAccountToRemove);
}
});
@@ -71,6 +71,8 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.celltable.FlushableCellTable;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
@@ -382,7 +384,7 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
otherExistingLeaderboard.addAll(availableLeaderboardList);
otherExistingLeaderboard.remove(leaderboardDTO);
if (leaderboardDTO.type.isMetaLeaderboard()) {
Window.alert(stringMessages.metaLeaderboardCannotBeChanged());
Notification.notify(stringMessages.metaLeaderboardCannotBeChanged(), NotificationType.ERROR);
} else {
AbstractLeaderboardDialog<?> dialog;
switch (leaderboardDTO.type) {
@@ -439,7 +441,7 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
leaderboardDTO.scoringScheme));
break;
default:
Window.alert(stringMessages.unknownLeaderboardType(leaderboardDTO.type.name()));
Notification.notify(stringMessages.unknownLeaderboardType(leaderboardDTO.type.name()), NotificationType.ERROR);
}
}
}
@@ -533,7 +535,7 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
@Override
public void onClick(ClickEvent event) {
if (getSelectedLeaderboard().type.isRegattaLeaderboard()) {
Window.alert(stringMessages.cannotAddRacesToRegattaLeaderboardButOnlyToRegatta());
Notification.notify(stringMessages.cannotAddRacesToRegattaLeaderboardButOnlyToRegatta(), NotificationType.ERROR);
} else {
addRaceColumnsToLeaderboard();
}
@@ -655,7 +657,7 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
@Override
public void onSuccess(Boolean result) {
if (!result) {
Window.alert(stringMessages.failedToSetNewStartTime());
Notification.notify(stringMessages.failedToSetNewStartTime(), NotificationType.ERROR);
}
}
});
@@ -682,7 +684,7 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
@Override
public void onSuccess(Pair<Boolean, Boolean> result) {
if (!result.getA() || !result.getB()) {
Window.alert(stringMessages.failedToSetNewFinishingAndFinishTime());
Notification.notify(stringMessages.failedToSetNewFinishingAndFinishTime(), NotificationType.ERROR);
}
}
});
@@ -53,6 +53,8 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.URLEncoder;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
@@ -988,7 +990,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel implements
setDescriptionEditable(false);
updateGroup(selectedGroup);
} else {
Window.alert(stringMessages.pleaseEnterNonEmptyDescription() + ".");
Notification.notify(stringMessages.pleaseEnterNonEmptyDescription() + ".", NotificationType.ERROR);
descriptionTextArea.setText(selectedGroup.description);
}
}
@@ -59,6 +59,8 @@ import com.sap.sse.common.Util;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
@@ -141,7 +143,7 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher {
public void onClick(ClickEvent event) {
Set<MediaTrack> selected = refreshableSelectionModel.getSelectedSet();
if (selected.isEmpty()) {
Window.alert(stringMessages.noSelection());
Notification.notify(stringMessages.noSelection(), NotificationType.ERROR);
} else {
new MultiURLChangeDialog(mediaService, stringMessages, selected, errorReporter,
new Runnable() {
@@ -24,6 +24,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public class PairingListCreationDialog extends DataEntryDialog<PairingListTemplateDTO> {
@@ -176,7 +178,7 @@ public class PairingListCreationDialog extends DataEntryDialog<PairingListTempla
new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
Window.alert(stringMessages.successfullyFilledRaceLogsFromPairingList());
Notification.notify(stringMessages.successfullyFilledRaceLogsFromPairingList(), NotificationType.SUCCESS);
}
@Override
@@ -13,7 +13,6 @@ import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
@@ -31,6 +30,8 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sse.gwt.client.IconResources;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.IntegerBox;
import com.sap.sse.gwt.client.controls.listedit.GenericStringListInlineEditorComposite;
import com.sap.sse.gwt.client.controls.listedit.StringListEditorComposite;
@@ -418,7 +419,7 @@ public class SeriesEditDialog extends DataEntryDialog<SeriesDescriptor> {
}
validateAndUpdate();
} else {
Window.alert(getStringMessages().pleaseSelectASeriesFirst());
Notification.notify(getStringMessages().pleaseSelectASeriesFirst(), NotificationType.ERROR);
}
}
});
@@ -66,6 +66,8 @@ import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.async.MarkedAsyncCallback;
import com.sap.sse.gwt.client.celltable.FlushableCellTable;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
@@ -235,7 +237,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
}
}).show();
} else {
Window.alert(stringMessages.canNotRegisterBoats());
Notification.notify(stringMessages.canNotRegisterBoats(), NotificationType.ERROR);
}
} else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_MAP_DEVICES.equals(value)) {
new RegattaLogTrackingDeviceMappingsDialog(sailingService, stringMessages, errorReporter,
@@ -757,7 +759,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
@Override
public void onSuccess(Void result) {
Window.alert(stringMessages.notificationRegattaConfigurationUpdatedUsingByMarks());
Notification.notify(stringMessages.notificationRegattaConfigurationUpdatedUsingByMarks(), NotificationType.SUCCESS);
}
}));
}
@@ -847,7 +849,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
@Override
public void onSuccess(Boolean result) {
if (!result) {
Window.alert(stringMessages.failedToSetNewStartTime());
Notification.notify(stringMessages.failedToSetNewStartTime(), NotificationType.ERROR);
} else {
trackedRacesListComposite.regattaRefresher.fillRegattas();
}
@@ -874,7 +876,7 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
@Override
public void onSuccess(Pair<Boolean, Boolean> result) {
if (!result.getA() || !result.getB()) {
Window.alert(stringMessages.failedToSetNewFinishingAndFinishTime());
Notification.notify(stringMessages.failedToSetNewFinishingAndFinishTime(), NotificationType.ERROR);
} else {
trackedRacesListComposite.regattaRefresher.fillRegattas();
}
@@ -944,12 +946,12 @@ public class SmartphoneTrackingEventManagementPanel extends AbstractLeaderboardC
getLocaleInfo(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Window.alert(stringMessages.sendingMailsFailed() + caught.getMessage());
Notification.notify(stringMessages.sendingMailsFailed() + caught.getMessage(), NotificationType.ERROR);
}
@Override
public void onSuccess(Void result) {
Window.alert(stringMessages.sendingMailsSuccessful());
Notification.notify(stringMessages.sendingMailsSuccessful(), NotificationType.SUCCESS);
}
});
}
@@ -15,7 +15,6 @@ import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
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.ui.Button;
import com.google.gwt.user.client.ui.CaptionPanel;
@@ -48,6 +47,8 @@ import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback;
@@ -475,7 +476,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat
@Override
public void onSuccess(Void result) {
regattaRefresher.fillRegattas();
Window.alert(stringMessages.successfullyCreatedRegattas());
Notification.notify(stringMessages.successfullyCreatedRegattas(), NotificationType.SUCCESS);
}
});
}
@@ -18,7 +18,6 @@ import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
@@ -34,6 +33,8 @@ import com.sap.sailing.gwt.ui.client.MediaServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.media.TimeFormatUtil;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
/**
* This dialog allows to change multiple urls for mediatracks at once. It will determine the longest common prefix, that
@@ -135,7 +136,7 @@ public class MultiURLChangeDialog extends DialogBox {
@Override
public void onFailure(Throwable caught) {
Window.alert(stringMessages.multiUrlChangeCannotSave());
Notification.notify(stringMessages.multiUrlChangeCannotSave(), NotificationType.ERROR);
}
});
}
@@ -150,7 +151,7 @@ public class MultiURLChangeDialog extends DialogBox {
final String maxPrefixForAll = maxPrefixForAll();
if (maxPrefixForAll.length() == 0) {
Window.alert(this.stringMessages.multiUrlNoPrefixWarning());
Notification.notify(this.stringMessages.multiUrlNoPrefixWarning(), NotificationType.WARNING);
}
replacePartIn.setText(maxPrefixForAll);
updateUI();
@@ -24,7 +24,6 @@ import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.typedarrays.shared.Int8Array;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
@@ -59,6 +58,8 @@ import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.datetime.DateAndTimeInput;
import com.sap.sse.gwt.client.controls.datetime.DateTimeInput.Accuracy;
@@ -617,7 +618,7 @@ public class MultiVideoDialog extends DialogBox {
@Override
public void noResult() {
Window.alert(stringMessages.serverURLInvalid());
Notification.notify(stringMessages.serverURLInvalid(), NotificationType.ERROR);
}
@Override
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Número de carreras que ha completado un competidor o en las
averageNumberOfOperationsPerMessage=Número promedio de operaciones por mensaje
showUncorrectedTotalPoints=Mostrar puntos totales no corregidos
setStartTimeReceived=Fijar hora de inicio recibida
setStartTimeReceivedDescription=Fija la HoraInicioRecibida del RegistroRastreado seleccionado que no es persistente. Esto significa que el nuevo valor se ignorará después del reinicio del servidor.
setStartTimeReceivedDescription=Fija la startTimeReceived de la TrackedRace seleccionada en el valor proporcionado. Deje el valor en blanco para eliminar la startTimeReceived actual.
setStartTimeReceivedNotice=Esta modificación no es persistente, es decir, el valor nuevo se olvidará cuando se reinicie el servidor.
lastScoreCorrectionsTime=Última hora de corrección de puntuación
lastScoreCorrectionsComment=Último comentario de corrección de puntuación
setTimeToNow=Fijar la hora a "ahora"
@@ -1275,11 +1276,13 @@ uploadSuccessful=Carga correcta
fileUploadResult=Carga de archivos: {0} {1}. En caso de error, compruebe que su servicio de alojamiento de archivos está configurado correctamente.
removeUploadedFile=Eliminar archivo
showCompetitorBoatColumn=Embarcación del competidor
showCompetitorSailIdColumn=ID de vela
showCompetitorSailIdColumnTooltip=Muestra el ID de vela más la bandera del país o imagen del competidor. Si está disponible, se prioriza la imagen de competidor a la bandera del país. Se mostrarán ambos iconos si se fija "{0}".
showCompetitorShortNameColumn=Denominación breve de competidor
showCompetitorShortNameColumnTooltip=Muestra el nombre breve más la bandera del país o imagen del competidor. Si está disponible, se prioriza la imagen de competidor a la bandera del país. Se mostrarán ambos iconos si se fija "{0}".
showCompetitorFullNameColumn=Nombre completo del competidor
showCompetitorNationalityColumn=Siempre mostrar la nacionalidad del competidor
showCompetitorNationalityColumnTooltip=Muestra ambos, las banderas de país así como las imágenes de competidor, si están disponibles.
alwaysShowCompetitorNationalityColumn=Siempre mostrar la nacionalidad del competidor
alwaysShowCompetitorNationalityColumnTooltip=Muestra ambos, las banderas de país así como las imágenes de competidor, si están disponibles.
loadingDimensionValues=Cargando valores de dimensión
inviteBuoyTenders=Invitar a balizadores
orMultipleEmails=o varios correos electrónicos separados por una coma
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=Windfinder
windFinderWindSourceTypeTooltip=Viento medido de uno o más puntos de www.windfinder.com
windFinder=Windfinder
enterTagsForTheVideo=Indique las etiquetas para el vídeo
enterIdOfWindfinderReviewedSpotCollection=Indique el ID de una colección de puntos de Windfinder revisada, por ejemplo "schilksee"
enterIdOfWindFinderReviewedSpotCollection=Indique el ID de una colección de puntos de Windfinder revisada, por ejemplo "schilksee"
windFinderSpotCollectionsList=Colecciones de puntos de WindFinder
enterTagsForTheImage=Indique las etiquetas para la imagen
unableToResolveWindFinderSpotId=Imposible resolver el punto Windfinder con ID {0}: {1}
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Nombre de courses que le concurrent a terminées, ou pour les
averageNumberOfOperationsPerMessage=Nombre moyen d''opérations par message
showUncorrectedTotalPoints=Afficher total des points non corrigé
setStartTimeReceived=Afficher heure de départ reçue
setStartTimeReceivedDescription=Définit l''heure de départ reçue de la course suivie sélectionnée non persistante. Cela signifie que la nouvelle valeur sera oubliée une fois que le serveur sera relancé.
setStartTimeReceivedDescription=Définit l''heure de départ reçue de la course suivie sélectionnée sur la valeur indiquée. Ne renseignez pas cette valeur si vous voulez supprimer l''actuelle heure de départ reçue définie.
setStartTimeReceivedNotice=Cette modification n''est pas persistante. Cela signifie que la nouvelle valeur sera oubliée une fois que le serveur sera redémarré.
lastScoreCorrectionsTime=Dernière heure de correction du score
lastScoreCorrectionsComment=Dernier commentaire sur la correction du score
setTimeToNow=Définir heure sur "maintenant"
@@ -1275,11 +1276,13 @@ uploadSuccessful=Chargement réussi
fileUploadResult=Chargement du fichier : {0} {1}.\nEn cas d''erreur, vérifiez que votre service de stockage de fichier est correctement configuré.
removeUploadedFile=Supprimer fichier chargé
showCompetitorBoatColumn=Bateau du concurrent
showCompetitorSailIdColumn=ID de voile
showCompetitorSailIdColumnTooltip=Affiche l''ID de voile ainsi que le drapeau national ou l''image du concurrent. Si les deux sont disponibles, l''image du concurrent aura la priorité sur le drapeau national. Si le code "{0}" est activé, les deux icônes seront affichées.
showCompetitorShortNameColumn=Nom court du concurrent
showCompetitorShortNameColumnTooltip=Affiche le nom court ainsi que le drapeau national ou l''image du concurrent. Si les deux sont disponibles, l''image du concurrent aura la priorité sur le drapeau national. Si le code "{0}" est activé, les deux icônes seront affichées.
showCompetitorFullNameColumn=Nom complet du concurrent
showCompetitorNationalityColumn=Afficher toujours la nationalité du concurrent
showCompetitorNationalityColumnTooltip=Si disponibles, afficher les deux : le drapeau national ainsi que l''image du concurrent
alwaysShowCompetitorNationalityColumn=Afficher toujours la nationalité du concurrent
alwaysShowCompetitorNationalityColumnTooltip=Si disponibles, afficher les deux : le drapeau national ainsi que l''image du concurrent
loadingDimensionValues=Chargement des valeurs de dimension
inviteBuoyTenders=Inviter navire baliseur
orMultipleEmails=ou plusieurs adresses e-mails séparées par des virgules
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
windFinderWindSourceTypeTooltip=Vent mesuré d''un ou plusieurs endroits de www.windfinder.com
windFinder=WindFinder
enterTagsForTheVideo=Entrez des balises pour la vidéo.
enterIdOfWindfinderReviewedSpotCollection=Entrez l''ID d''un ensemble d''endroits WindFinder révisé, par exemple, "Schilksee".
enterIdOfWindFinderReviewedSpotCollection=Entrez l''ID d''un ensemble d''endroits WindFinder révisé, par exemple, "Schilksee".
windFinderSpotCollectionsList=Ensemble d''endroits WindFinder
enterTagsForTheImage=Entrez des balises pour l''image.
unableToResolveWindFinderSpotId=Impossible de traiter l''endroit WindFinder ayant l''ID {0} : {1}
@@ -1163,7 +1163,8 @@ racesScoredTooltip=このリーダーボードにおいて競技者が完了し
averageNumberOfOperationsPerMessage=メッセージごとの操作の平均数
showUncorrectedTotalPoints=未修正総得点表示
setStartTimeReceived=設定済スタート時刻を受信
setStartTimeReceivedDescription=これにより、永続的でない選択した TrackedRace の startTimeReceived が設定されます。したがって、サーバが再起動された後は新規の値は忘れられます。
setStartTimeReceivedDescription=選択した TrackedRace の startTimeReceived が指定した値に設定されます。値を空白のままにすると、現在設定されている startTimeReceived は削除されます。
setStartTimeReceivedNotice=この変更は永続的なものではありません。つまり、新しい値はサーバが再起動したときに失われます。
lastScoreCorrectionsTime=最終得点修正時刻
lastScoreCorrectionsComment=最終得点修正コメント
setTimeToNow=時刻を ''現在'' に設定
@@ -1275,11 +1276,13 @@ uploadSuccessful=正常にアップロード済
fileUploadResult=ファイルアップロード: {0} {1}\nエラー発生の場合は、ファイルストレージサービスが適切に設定されていることを確認してください。
removeUploadedFile=アップロード済ファイルの削除
showCompetitorBoatColumn=競技者の艇
showCompetitorSailIdColumn=セール ID
showCompetitorSailIdColumnTooltip=セール ID に加えて国旗または競技者画像を表示します。競技者画像が利用可能な場合はそれを国旗よりも優先させます。"{0}" が設定されている場合、両方のアイコンが表示されます。
showCompetitorShortNameColumn=競技者の名前 (短)
showCompetitorShortNameColumnTooltip=名前 (短) に加えて国旗または競技者画像を表示します。競技者画像が利用可能な場合はそれを国旗よりも優先させます。"{0}" が設定されている場合、両方のアイコンが表示されます。
showCompetitorFullNameColumn=競技者氏名
showCompetitorNationalityColumn=競技者国籍を常に表示
showCompetitorNationalityColumnTooltip=国旗と競技者画像 (利用可能な場合) の両方を表示
alwaysShowCompetitorNationalityColumn=競技者国籍を常に表示
alwaysShowCompetitorNationalityColumnTooltip=国旗と競技者画像 (利用可能な場合) の両方を表示
loadingDimensionValues=次元値ロード中
inviteBuoyTenders=ブイ入札の招待
orMultipleEmails=または複数の電子メールをカンマで区切り
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=Windfinder
windFinderWindSourceTypeTooltip=www.windfinder.com の 1 つ以上のスポットから風を測定しました
windFinder=Windfinder
enterTagsForTheVideo=動画のタグを入力
enterIdOfWindfinderReviewedSpotCollection=レビューする Windfinder スポットコレクションの ID を入力 (例: "schilksee")
enterIdOfWindFinderReviewedSpotCollection=レビューする Windfinder スポットコレクションの ID を入力 (例: "schilksee")
windFinderSpotCollectionsList=WindFinder スポットコレクション
enterTagsForTheImage=画像のタグを入力
unableToResolveWindFinderSpotId=ID {0} で Windfinder スポットを決定できませんでした: {1}
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Número de corridas que o competidor concluiu ou nas quais ob
averageNumberOfOperationsPerMessage=Número médio de operações por mensagem
showUncorrectedTotalPoints=Visualizar total de pontos não corrigidos
setStartTimeReceived=Definir hora de partida recebida
setStartTimeReceivedDescription=Isto define a hora de partida recebida da corrida rastreada selecionada que não é persistente. Isto significa que o novo valor será esquecido após a reinicialização do servidor.
setStartTimeReceivedDescription=Define a hora de partida recebida da corrida rastreada selecionada para o valor fornecido. Deixe o valor em branco para remover a hora de partida recebida definida atualmente.
setStartTimeReceivedNotice=Esta modificação não é persistente, ou seja, o novo valor será esquecido quando o servidor for reiniciado.
lastScoreCorrectionsTime=Hora de correção da última pontuação
lastScoreCorrectionsComment=Comentário de correção da última pontuação
setTimeToNow=Definir hora para ''agora''
@@ -1275,11 +1276,13 @@ uploadSuccessful=Carregamento efetuado com êxito
fileUploadResult=Carregamento de arquivo: {0} {1}.\nEm caso de erro, verifique se seu serviço de armazenamento de arquivos está configurado de modo apropriado.
removeUploadedFile=Remover arquivo carregado
showCompetitorBoatColumn=Barco do competidor
showCompetitorSailIdColumn=ID da vela
showCompetitorSailIdColumnTooltip=Exibe o ID da vela mais a bandeira de nacionalidade ou a imagem do competidor. Se disponível, é priorizada uma imagem do competidor em relação a uma bandeira da nacionalidade. Se "{0}" estiver definido, ambos os ícones serão exibidos.
showCompetitorShortNameColumn=Nome abreviado do competidor
showCompetitorShortNameColumnTooltip=Exibe o nome abreviado mais a bandeira de nacionalidade ou a imagem do competidor. Se disponível, é priorizada uma imagem do competidor em relação a uma bandeira da nacionalidade. Se "{0}" estiver definido, ambos os ícones serão exibidos.
showCompetitorFullNameColumn=Nome completo do competidor
showCompetitorNationalityColumn=Exibir sempre a nacionalidade do competidor
showCompetitorNationalityColumnTooltip=Exibir ambos, bandeiras de nacionalidade e imagens do competidor, se disponíveis
alwaysShowCompetitorNationalityColumn=Exibir sempre a nacionalidade do competidor
alwaysShowCompetitorNationalityColumnTooltip=Exibir ambos, bandeiras de nacionalidade e imagens do competidor, se disponíveis
loadingDimensionValues=Carregando valores de dimensão
inviteBuoyTenders=Convidar navios-balizadores
orMultipleEmails=ou vários e-mails separados por vírgula
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
windFinderWindSourceTypeTooltip=Vento medido de um ou mais locais de www.windfinder.com
windFinder=WindFinder
enterTagsForTheVideo=Inserir etiquetas para o vídeo
enterIdOfWindfinderReviewedSpotCollection=Inserir ID de uma coleção revisada de locais do WindFinder, por exemplo, "schilksee"
enterIdOfWindFinderReviewedSpotCollection=Inserir ID de uma coleção revisada de locais do WindFinder, por exemplo, "schilksee"
windFinderSpotCollectionsList=Coleções de locais do WindFinder
enterTagsForTheImage=Inserir etiquetas para a imagem
unableToResolveWindFinderSpotId=Impossível resolver local do WindFinder com ID {0}: {1}
@@ -1163,7 +1163,8 @@ racesScoredTooltip=Число гонок, которые участник зав
averageNumberOfOperationsPerMessage=Среднее число операций на сообщение
showUncorrectedTotalPoints=Показать неисправленный общий балл
setStartTimeReceived=Установить полученное время старта
setStartTimeReceivedDescription=Устанавливает полученное время старта для выбранной отслеживаемой гонки, которое не хранится постоянно. Это значит, что после перезагрузки сервера новое значение будет забыто.
setStartTimeReceivedDescription=Устанавливает введенное значение для полученного времени старта выбранной отслеживаемой гонки. Оставьте значение пустым, чтобы удалить текущее установленное полученное время старта.
setStartTimeReceivedNotice=Это изменение не хранится, т.е. новое значение будет забыто после перезагрузки сервера.
lastScoreCorrectionsTime=Время последнего исправления оценки
lastScoreCorrectionsComment=Комментарий последнего исправления оценки
setTimeToNow=Установить время ''сейчас''
@@ -1275,11 +1276,13 @@ uploadSuccessful=Отправлено успешно
fileUploadResult=Отправка файла: {0} {1}.\nВ случае ошибки проверьте правильность конфигурации службы хранилища файлов.
removeUploadedFile=Удалить отправленный файл
showCompetitorBoatColumn=Лодка участника
showCompetitorSailIdColumn=Ид. паруса
showCompetitorSailIdColumnTooltip=Показывает ид. паруса плюс государственный флаг или изображение участника. Изображение участника, при наличии, имеет приоритет над государственным флагом. Если установлен параметр "{0}", будут отображены оба значка.
showCompetitorShortNameColumn=Краткое имя участника
showCompetitorShortNameColumnTooltip=Показывает краткое имя плюс государственный флаг или изображение участника. Изображение участника, при наличии, имеет приоритет над государственным флагом. Если установлен параметр "{0}", будут отображены оба значка.
showCompetitorFullNameColumn=Полное имя участника
showCompetitorNationalityColumn=Всегда показывать государственную принадлежность участника
showCompetitorNationalityColumnTooltip=Показывать и флаги государств, и изображения участников (при наличии)
alwaysShowCompetitorNationalityColumn=Всегда показывать государственную принадлежность участника
alwaysShowCompetitorNationalityColumnTooltip=Показывать и флаги государств, и изображения участников (при наличии)
loadingDimensionValues=Загрузка значений измерения
inviteBuoyTenders=Пригласить лоцманов
orMultipleEmails=или несколько адресов эл. почты через запятую
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
windFinderWindSourceTypeTooltip=Измерения ветра из одного или нескольких мест www.windfinder.com
windFinder=WindFinder
enterTagsForTheVideo=Введите теги для видео
enterIdOfWindfinderReviewedSpotCollection=Введите ид. просмотренной коллекции мест WindFinder (например, "schilksee")
enterIdOfWindFinderReviewedSpotCollection=Введите ид. просмотренной коллекции мест WindFinder (например, "schilksee")
windFinderSpotCollectionsList=Коллекции мест WindFinder
enterTagsForTheImage=Введите теги для изображения
unableToResolveWindFinderSpotId=Не удалось разрешить место WindFinder по ид. {0}: {1}
@@ -1163,7 +1163,8 @@ racesScoredTooltip=参赛队完成并记录在此积分榜上的比赛轮次数
averageNumberOfOperationsPerMessage=各消息操作的平均数
showUncorrectedTotalPoints=显示未更正的总分
setStartTimeReceived=设置接收的开始时间
setStartTimeReceivedDescription=设置非持久的所选 TrackedRace 的 startTimeReceived。这意味着,重启服务器后,将忘记新值。
setStartTimeReceivedDescription=将所选 TrackedRace 的 startTimeReceived 设置为提供的值。将此值留空,以移除当前设置的 startTimeReceived。
setStartTimeReceivedNotice=此更改并不持久,即重启服务器后,新值将被忘记。
lastScoreCorrectionsTime=上次得分更正时间
lastScoreCorrectionsComment=上次得分更正评论
setTimeToNow=将时间设为“现在”
@@ -1275,11 +1276,13 @@ uploadSuccessful=上传成功
fileUploadResult=文件上传: {0} {1}。\n如果出错,请检查文件存储服务配置是否正确。
removeUploadedFile=移除上传的文件
showCompetitorBoatColumn=参赛队的船只
showCompetitorSailIdColumn=帆号
showCompetitorSailIdColumnTooltip=显示帆号和国籍旗帜或参赛队图像。如果可用,参赛队图像优先于国籍旗帜。如果设置 "{0}",将显示这两种图标。
showCompetitorShortNameColumn=参赛队短名称
showCompetitorShortNameColumnTooltip=显示短名称和国籍旗帜或参赛队图像。如果可用,参赛队图像优先于国籍旗帜。如果设置 "{0}",将显示这两种图标。
showCompetitorFullNameColumn=参赛队全名
showCompetitorNationalityColumn=始终显示参赛队国籍
showCompetitorNationalityColumnTooltip=如果可用,显示两者:国籍旗帜和参赛队图像
alwaysShowCompetitorNationalityColumn=始终显示参赛队国籍
alwaysShowCompetitorNationalityColumnTooltip=如果可用,显示两者:国籍旗帜和参赛队图像
loadingDimensionValues=正在加载尺寸值
inviteBuoyTenders=邀请浮标供应船
orMultipleEmails=或使用逗号隔开的多个电子邮件
@@ -1970,7 +1973,7 @@ windFinderWindSourceTypeName=WindFinder
windFinderWindSourceTypeTooltip=Www.windfinder.com 中一个或多个地点的测量风力
windFinder=WindFinder
enterTagsForTheVideo=为视频输入标记
enterIdOfWindfinderReviewedSpotCollection=输入经检查的 WindFinder 地点集合的编号,例如 "schilksee"
enterIdOfWindFinderReviewedSpotCollection=输入经检查的 WindFinder 地点集合的编号,例如 "schilksee"
windFinderSpotCollectionsList=WindFinder 地点集合
enterTagsForTheImage=为图像输入标记
unableToResolveWindFinderSpotId=无法解析编号为{0}的 WindFinder 地点:{1}
@@ -10,6 +10,7 @@ import com.google.gwt.typedarrays.shared.Int8Array;
*/
public class JSDownloadUtils {
private static final Double REQUIRED_SIZE = 10000000.0;
protected static final Double MAX_MEMORY_USAGE_FOR_DL = 1024 * 1024 * 1024 * 2d;
public interface JSDownloadCallback {
void progress(Double current, Double total);
@@ -43,7 +44,7 @@ public class JSDownloadUtils {
getDataFast(url, callback, total, REQUIRED_SIZE);
} else {
//fallback will always work, if cors is supported, does not require any other server configuration
getDataSlow(url, callback, REQUIRED_SIZE);
getDataSlow(url, callback, REQUIRED_SIZE, MAX_MEMORY_USAGE_FOR_DL);
}
}
});
@@ -53,75 +54,77 @@ public class JSDownloadUtils {
* Fast file download method based on range requests, only the first and the last REQUIRED_SIZE is loaded.
*/
private native static void getDataFast(String url, JSDownloadCallback callback, Double length, Double REQUIRED_SIZE) /*-{
try {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.setRequestHeader("Range", "bytes=0-" + REQUIRED_SIZE);
xhr.responseType = "arraybuffer";
xhr.onprogress = function(evt) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
}
xhr.error = function(error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
xhr.onreadystatechange = function() {
var state = xhr.readyState;
if (state == 4) {
if (xhr.response) {
var startLength = xhr.response.byteLength;
var start = new Int8Array(xhr.response);
try {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.setRequestHeader("Range", "bytes=0-" + REQUIRED_SIZE);
xhr.responseType = "arraybuffer";
xhr.onprogress = function(evt) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
}
xhr.error = function(error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
try {
var xhr2 = new XMLHttpRequest();
xhr2.open("GET", url, true);
xhr2.setRequestHeader("Range", "bytes=" + (length - REQUIRED_SIZE));
xhr2.responseType = "arraybuffer";
xhr2.onprogress = function(evt) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
}
xhr2.error = function(error) {
xhr.onreadystatechange = function() {
var state = xhr.readyState;
if (state == 4) {
if (xhr.response) {
var startLength = xhr.response.byteLength;
var start = new Int8Array(xhr.response);
try {
var xhr2 = new XMLHttpRequest();
xhr2.open("GET", url, true);
xhr2.setRequestHeader("Range", "bytes="
+ (length - REQUIRED_SIZE) + "-");
xhr2.responseType = "arraybuffer";
xhr2.onprogress = function(evt) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
}
xhr2.error = function(error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
xhr2.onreadystatechange = function() {
var state = xhr2.readyState;
if (state == 4) {
if (xhr2.response) {
var endLength = xhr2.response.byteLength;
var end = new Int8Array(xhr2.response);
var sparse = length - startLength
- endLength;
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
}
}
};
xhr2.send();
} catch (error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
xhr2.onreadystatechange = function() {
var state = xhr2.readyState;
if (state == 4) {
if (xhr2.response) {
var endLength = xhr2.response.byteLength;
var end = new Int8Array(xhr2.response);
var sparse = length - startLength - endLength;
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
}
}
};
xhr2.send();
} catch (error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
}
}
};
xhr.send();
} catch (error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
}-*/;
};
xhr.send();
} catch (error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
}-*/;
/**
* Determines if a server can deliver a file with range requests, and if so returns the size of the file
*/
private native static void getFileSizeIfFastPath(String url, JSSizeCallback callback) /*-{
try {
try {
var xhr = new XMLHttpRequest();
xhr.open("HEAD", url, true);
xhr.responseType = "arraybuffer";
xhr.error = function(error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSSizeCallback::size(Ljava/lang/Double;)(-1.0);
}
xhr.onreadystatechange = function() {
var state = xhr.readyState;
var state = xhr.readyState;
if (state == 4) {
if (xhr.response) {
var length = xhr.getResponseHeader("Content-Length");
@@ -141,29 +144,36 @@ public class JSDownloadUtils {
/**
* If range requests are not possible, the whole file is downloaded and then slices to the required parts
*/
private native static void getDataSlow(String url, JSDownloadCallback callback, Double REQUIRED_SIZE) /*-{
private native static void getDataSlow(String url, JSDownloadCallback callback, Double REQUIRED_SIZE,
Double maxMemoryUsage) /*-{
try {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onprogress = function(evt) {
//ensure not more memory is used by the tab than commonly available in browsers
if (evt.total > maxMemoryUsage || evt.loaded > maxMemoryUsage) {
xhr.abort();
}
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::progress(Ljava/lang/Double;Ljava/lang/Double;)(evt.loaded, evt.total);
}
xhr.error = function(error) {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)(error);
}
xhr.onreadystatechange = function() {
var state = xhr.readyState;
var state = xhr.readyState;
if (state == 4) {
if (xhr.response) {
var length = xhr.response.byteLength;
var start = new Int8Array(xhr.response.slice(0, REQUIRED_SIZE));
var end = new Int8Array(xhr.response.slice(length - REQUIRED_SIZE));
var start = new Int8Array(xhr.response.slice(0,
REQUIRED_SIZE));
var end = new Int8Array(xhr.response.slice(length
- REQUIRED_SIZE));
var sparse = length - 2 * REQUIRED_SIZE;
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::complete(Lcom/google/gwt/typedarrays/shared/Int8Array;Lcom/google/gwt/typedarrays/shared/Int8Array;Ljava/lang/Double;)(start, end, sparse);
} else {
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)("No result");
callback.@com.sap.sailing.gwt.ui.client.media.JSDownloadUtils.JSDownloadCallback::error(Ljava/lang/Object;)("No result");
}
}
};
@@ -18,7 +18,6 @@ import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.media.client.Audio;
import com.google.gwt.media.client.MediaBase;
import com.google.gwt.typedarrays.shared.Int8Array;
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;
@@ -41,6 +40,8 @@ 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.MimeType;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
import com.sap.sse.gwt.client.controls.datetime.DateAndTimeInput;
import com.sap.sse.gwt.client.controls.datetime.DateTimeInput.Accuracy;
@@ -400,7 +401,7 @@ public class NewMediaDialog extends DataEntryDialog<MediaTrack> {
protected void mp4MetadataResult(VideoMetadataDTO result) {
if (!result.isDownloadable()) {
Window.alert(stringMessages.couldNotDownload(mediaTrack.url));
Notification.notify(stringMessages.couldNotDownload(mediaTrack.url), NotificationType.ERROR);
manualMimeTypeSelection(result.getMessage(), mediaTrack);
} else {
mediaTrack.duration = result.getDuration();
@@ -11,11 +11,11 @@ import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
@@ -43,6 +43,8 @@ import com.sap.sse.common.filter.Filter;
import com.sap.sse.common.filter.FilterSet;
import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.shared.components.AbstractCompositeComponent;
@@ -133,7 +135,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent<AbstractSe
};
}
}, stringMessages.waypoint());
final DateTimeFormat timeFormat = DateTimeFormat.getFormat("HH:mm:ss");
final DateTimeFormat timeFormat = DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_FULL);
wayPointSelectionTable.addColumn(new Column<Util.Pair<Integer, Date>, SafeHtml>(new AnchorCell()) {
@Override
public SafeHtml getValue(final Pair<Integer, Date> object) {
@@ -216,7 +218,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent<AbstractSe
}
});
} else {
Window.alert(stringMessages.warningSettingFixedPassing(currentWaypoints.get(waypoint).getName()));
Notification.notify(stringMessages.warningSettingFixedPassing(currentWaypoints.get(waypoint).getName()), NotificationType.WARNING);
}
}
}
@@ -5,9 +5,11 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -64,7 +66,6 @@ import com.google.gwt.maps.client.events.rightclick.RightClickMapHandler;
import com.google.gwt.maps.client.mvc.MVCArray;
import com.google.gwt.maps.client.overlays.Polyline;
import com.google.gwt.maps.client.overlays.PolylineOptions;
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.HTMLPanel;
@@ -97,6 +98,7 @@ import com.sap.sailing.gwt.ui.shared.racemap.CanvasOverlayV3;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.settings.AbstractSettings;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.async.AsyncActionsExecutor;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
@@ -132,6 +134,8 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
private final RaceIdentifierToLeaderboardRaceColumnAndFleetMapper raceIdentifierToLeaderboardRaceColumnAndFleetMapper;
protected boolean nonTrackingWarningWasDisplayed;
private final Set<MarkDTO> marksCurrentlyRequestedViaRemoteCall = new HashSet<>();
public EditMarkPositionPanel(Component<?> parent, ComponentContext<?> context, final RaceMap raceMap,
final SingleRaceLeaderboardPanel leaderboardPanel,
RegattaAndRaceIdentifier selectedRaceIdentifier, String leaderboardName, final StringMessages stringMessages,
@@ -735,10 +739,7 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
}
raceMap.unregisterAllCourseMarkInfoWindowClickHandlers();
} else {
if (currentFixPositionChooser != null) {
currentFixPositionChooser.cancel();
currentFixPositionChooser = null;
}
cancelFixPositionChooserAndNotification();
marksPanel.deselectMark();
selectedMark = null;
if (sideBySideComponentViewer != null) {
@@ -754,6 +755,17 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
super.setVisible(visible);
}
private void cancelFixPositionChooserAndNotification() {
if (currentFixPositionChooser != null) {
currentFixPositionChooser.cancel();
currentFixPositionChooser = null;
if (notificationTimer.isRunning()) {
notificationTimer.run();
notificationTimer.cancel();
}
}
}
private void checkIfTracking(Runnable continuation) {
if (nonTrackingWarningWasDisplayed) {
continuation.run();
@@ -761,14 +773,14 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
sailingService.checkIfRaceIsTracking(selectedRaceIdentifier, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
Window.alert(stringMessages.serverError());
Notification.notify(stringMessages.serverError(), Notification.NotificationType.ERROR);
continuation.run();
}
@Override
public void onSuccess(Boolean result) {
if (Boolean.FALSE.equals(result)) {
Window.alert(stringMessages.positionEditOnNonTrackingRace());
Notification.notify(stringMessages.positionEditOnNonTrackingRace(), Notification.NotificationType.WARNING);
nonTrackingWarningWasDisplayed = true;
}
continuation.run();
@@ -859,11 +871,10 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
}
private void selectMark(MarkDTO mark) {
selectedMark = mark;
if (currentFixPositionChooser != null) {
currentFixPositionChooser.cancel();
currentFixPositionChooser = null;
if (selectedMark != mark) {
cancelFixPositionChooserAndNotification();
}
selectedMark = mark;
if (selectedMark != null) {
if (marksFromToTimes.get(selectedMark) != null) {
// For some reason the time slider does not change with this method only if you comment out line 430 and 432 in TimePanel it works
@@ -905,24 +916,43 @@ public class EditMarkPositionPanel extends AbstractRaceChart<AbstractSettings> i
@Override
public void onSelectionChange(SelectionChangeEvent event) {
final MarkDTO mark = marksPanel.getSelectedMark();
retrieveAndSelectMarkIfNecessary(mark, null);
}
protected void retrieveAndSelectMarkIfNecessary(final MarkDTO mark, final Runnable callback) {
if (mark != null && (marks.get(mark) == null || marks.get(mark).isEmpty())) {
if (mark != null) {
markPositionService.getMarkTrack(raceIdentifierToLeaderboardRaceColumnAndFleetMapper.getLeaderboardNameAndRaceColumnNameAndFleetName(selectedRaceIdentifier),
if (marksCurrentlyRequestedViaRemoteCall.add(mark)) {
markPositionService.getMarkTrack(
raceIdentifierToLeaderboardRaceColumnAndFleetMapper
.getLeaderboardNameAndRaceColumnNameAndFleetName(selectedRaceIdentifier),
mark.getIdAsString(), new AsyncCallback<MarkTrackDTO>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError(stringMessages.errorCommunicatingWithServer()+": "+caught.getMessage());
marksCurrentlyRequestedViaRemoteCall.remove(mark);
errorReporter.reportError(
stringMessages.errorCommunicatingWithServer() + ": " + caught.getMessage());
}
@Override
public void onSuccess(MarkTrackDTO result) {
marksCurrentlyRequestedViaRemoteCall.remove(mark);
createMarkTrackUi(mark, result.getFixes());
selectMark(mark);
if (callback != null) {
callback.run();
}
}
});
}
else {
// remote call of the same mark already in progress -> ignore this request
}
} else {
selectMark(mark);
if (callback != null) {
callback.run();
}
}
}
@@ -85,22 +85,27 @@ public class MarksPanel extends AbstractCompositeComponent<AbstractSettings> {
@Override
public void update(int index, final MarkDTO mark, String value) {
final Date timePoint = parent.timer.getTime();
select(mark);
if (parent.hasFixAtTimePoint(mark, timePoint)) {
parent.showNotification(stringMessages.pleaseSelectOtherTimepoint(), NotificationType.ERROR);
} else {
parent.createFixPositionChooserToAddFixToMark(mark, new Callback<Position, Exception>() {
@Override
public void onFailure(Exception reason) {
parent.resetCurrentFixPositionChooser();
parent.retrieveAndSelectMarkIfNecessary(mark, new Runnable() {
@Override
public void run() {
if (parent.hasFixAtTimePoint(mark, timePoint)) {
parent.showNotification(stringMessages.pleaseSelectOtherTimepoint(), NotificationType.ERROR);
} else {
parent.createFixPositionChooserToAddFixToMark(mark, new Callback<Position, Exception>() {
@Override
public void onFailure(final Exception reason) {
parent.resetCurrentFixPositionChooser();
}
@Override
public void onSuccess(Position result) {
parent.addMarkFix(mark, timePoint, result);
parent.resetCurrentFixPositionChooser();
}
});
}
@Override
public void onSuccess(Position result) {
parent.addMarkFix(mark, timePoint, result);
parent.resetCurrentFixPositionChooser();
}
});
}
}
});
}
});
markTable.addColumn(addFixColumn);
@@ -622,116 +622,123 @@ public class RaceMap extends AbstractCompositeComponent<RaceMapSettings> impleme
loadLibraries.add(LoadLibrary.GEOMETRY);
Runnable onLoad = new Runnable() {
@Override
public void run() {
MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false);
map = new MapWidget(mapOptions);
rootPanel.add(map, 0, 0);
if (showHeaderPanel) {
Image sapLogo = createSAPLogo();
rootPanel.add(sapLogo);
}
map.setControls(ControlPosition.LEFT_TOP, topLeftControlsWrapperPanel);
adjustLeftControlsIndent();
@Override
public void run() {
MapOptions mapOptions = getMapOptions(showMapControls, /* wind up */ false);
map = new MapWidget(mapOptions);
rootPanel.add(map, 0, 0);
if (showHeaderPanel) {
Image sapLogo = createSAPLogo();
rootPanel.add(sapLogo);
}
RaceMap.this.raceMapImageManager.loadMapIcons(map);
map.setSize("100%", "100%");
map.addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
public void onEvent(ZoomChangeMapEvent event) {
if (!autoZoomIn && !autoZoomOut && !orientationChangeInProgress) {
// stop automatic zoom after a manual zoom event; automatic zoom in zoomMapToNewBounds will restore old settings
final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors());
settings = new RaceMapSettings(settings, clearedZoomSettings);
}
// TODO bug489 when in wind-up mode, avoid zooming out too far; perhaps zoom back in if zoomed out too far
}
});
map.addDragEndHandler(new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// stop automatic zoom after a manual drag event
autoZoomIn = false;
autoZoomOut = false;
final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList, settings.getZoomSettings().isZoomToSelectedCompetitors());
settings = new RaceMapSettings(settings, clearedZoomSettings);
}
});
map.addIdleHandler(new IdleMapHandler() {
@Override
public void onEvent(IdleMapEvent event) {
// the "idle"-event is raised at the end of map-animations
if (autoZoomIn) {
// finalize zoom-in that was started with panTo() in zoomMapToNewBounds()
map.setZoom(autoZoomLevel);
autoZoomIn = false;
}
if (autoZoomOut) {
// finalize zoom-out that was started with setZoom() in zoomMapToNewBounds()
map.panTo(autoZoomLatLngBounds.getCenter());
autoZoomOut = false;
}
}
});
map.addBoundsChangeHandler(new BoundsChangeMapHandler() {
@Override
public void onEvent(BoundsChangeMapEvent event) {
int newZoomLevel = map.getZoom();
if (!isAutoZoomInProgress() && (newZoomLevel != currentZoomLevel)) {
removeTransitions();
}
if ((streamletOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
streamletOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
}
if ((simulationOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
simulationOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
}
currentMapBounds = map.getBounds();
currentZoomLevel = newZoomLevel;
headerPanel.getElement().getStyle().setWidth(map.getOffsetWidth(), Unit.PX);
}
});
// If there was a time change before the API was loaded, reset the time
if (lastTimeChangeBeforeInitialization != null) {
timeChanged(lastTimeChangeBeforeInitialization, null);
lastTimeChangeBeforeInitialization = null;
}
// Initialize streamlet canvas for wind visualization; it shouldn't be doing anything unless it's visible
streamletOverlay = new WindStreamletsRaceboardOverlay(getMap(), /* zIndex */ 0,
timer, raceIdentifier, sailingService, asyncActionsExecutor, stringMessages, coordinateSystem);
streamletOverlay.addToMap();
if (settings.isShowWindStreamletOverlay()) {
streamletOverlay.setColors(settings.isShowWindStreamletColors());
streamletOverlay.setVisible(true);
}
map.setControls(ControlPosition.LEFT_TOP, topLeftControlsWrapperPanel);
adjustLeftControlsIndent();
if (isSimulationEnabled) {
// determine availability of polar diagram
setHasPolar();
// initialize simulation canvas
simulationOverlay = new RaceSimulationOverlay(getMap(), /* zIndex */ 0, raceIdentifier, sailingService, stringMessages, asyncActionsExecutor, coordinateSystem);
simulationOverlay.addToMap();
showSimulationOverlay(settings.isShowSimulationOverlay());
}
if (showHeaderPanel) {
createHeaderPanel(map);
}
if (showMapControls) {
createSettingsButton(map);
}
// Data has been initialized
RaceMap.this.isMapInitialized = true;
RaceMap.this.redraw();
trueNorthIndicatorPanel.redraw();
showAdditionalControls(map);
RaceMap.this.managedInfoWindow = new ManagedInfoWindow(map);
}
RaceMap.this.raceMapImageManager.loadMapIcons(map);
map.setSize("100%", "100%");
map.addZoomChangeHandler(new ZoomChangeMapHandler() {
@Override
public void onEvent(ZoomChangeMapEvent event) {
if (!autoZoomIn && !autoZoomOut && !orientationChangeInProgress) {
// stop automatic zoom after a manual zoom event; automatic zoom in zoomMapToNewBounds will
// restore old settings
final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList,
settings.getZoomSettings().isZoomToSelectedCompetitors());
settings = new RaceMapSettings(settings, clearedZoomSettings);
}
// TODO bug489 when in wind-up mode, avoid zooming out too far; perhaps zoom back in if zoomed
// out too far
}
});
map.addDragEndHandler(new DragEndMapHandler() {
@Override
public void onEvent(DragEndMapEvent event) {
// stop automatic zoom after a manual drag event
autoZoomIn = false;
autoZoomOut = false;
final List<RaceMapZoomSettings.ZoomTypes> emptyList = Collections.emptyList();
RaceMapZoomSettings clearedZoomSettings = new RaceMapZoomSettings(emptyList,
settings.getZoomSettings().isZoomToSelectedCompetitors());
settings = new RaceMapSettings(settings, clearedZoomSettings);
}
});
map.addIdleHandler(new IdleMapHandler() {
@Override
public void onEvent(IdleMapEvent event) {
// the "idle"-event is raised at the end of map-animations
if (autoZoomIn) {
// finalize zoom-in that was started with panTo() in zoomMapToNewBounds()
map.setZoom(autoZoomLevel);
autoZoomIn = false;
}
if (autoZoomOut) {
// finalize zoom-out that was started with setZoom() in zoomMapToNewBounds()
map.panTo(autoZoomLatLngBounds.getCenter());
autoZoomOut = false;
}
redraw();
}
});
map.addBoundsChangeHandler(new BoundsChangeMapHandler() {
@Override
public void onEvent(BoundsChangeMapEvent event) {
int newZoomLevel = map.getZoom();
if (!isAutoZoomInProgress() && (newZoomLevel != currentZoomLevel)) {
removeTransitions();
}
if ((streamletOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
streamletOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
}
if ((simulationOverlay != null) && !map.getBounds().equals(currentMapBounds)) {
simulationOverlay.onBoundsChanged(newZoomLevel != currentZoomLevel);
}
currentMapBounds = map.getBounds();
currentZoomLevel = newZoomLevel;
headerPanel.getElement().getStyle().setWidth(map.getOffsetWidth(), Unit.PX);
}
});
// If there was a time change before the API was loaded, reset the time
if (lastTimeChangeBeforeInitialization != null) {
timeChanged(lastTimeChangeBeforeInitialization, null);
lastTimeChangeBeforeInitialization = null;
}
// Initialize streamlet canvas for wind visualization; it shouldn't be doing anything unless it's
// visible
streamletOverlay = new WindStreamletsRaceboardOverlay(getMap(), /* zIndex */ 0, timer, raceIdentifier,
sailingService, asyncActionsExecutor, stringMessages, coordinateSystem);
streamletOverlay.addToMap();
if (settings.isShowWindStreamletOverlay()) {
streamletOverlay.setColors(settings.isShowWindStreamletColors());
streamletOverlay.setVisible(true);
}
if (isSimulationEnabled) {
// determine availability of polar diagram
setHasPolar();
// initialize simulation canvas
simulationOverlay = new RaceSimulationOverlay(getMap(), /* zIndex */ 0, raceIdentifier,
sailingService, stringMessages, asyncActionsExecutor, coordinateSystem);
simulationOverlay.addToMap();
showSimulationOverlay(settings.isShowSimulationOverlay());
}
if (showHeaderPanel) {
createHeaderPanel(map);
}
if (showMapControls) {
createSettingsButton(map);
}
// Data has been initialized
RaceMap.this.isMapInitialized = true;
RaceMap.this.redraw();
trueNorthIndicatorPanel.redraw();
showAdditionalControls(map);
RaceMap.this.managedInfoWindow = new ManagedInfoWindow(map);
}
};
LoadApi.go(onLoad, loadLibraries, sensor, GoogleMapAPIKey.V3_PARAMS);
LoadApi.go(onLoad, loadLibraries, sensor, GoogleMapAPIKey.V3_PARAMS);
}
/**
@@ -12,6 +12,7 @@ import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
class ManeuverTableData {
private final String competitorName;
private final String competitorColor;
private final Date timePoint;
private final Date timePointBefore;
private final ManeuverType maneuverType;
@@ -24,8 +25,9 @@ class ManeuverTableData {
private final double directionChange;
private final boolean markPassing;
ManeuverTableData(final CompetitorDTO competitor, final ManeuverDTO maneuver) {
ManeuverTableData(final CompetitorDTO competitor, final String competitorColor, final ManeuverDTO maneuver) {
this.competitorName = competitor.getName();
this.competitorColor = competitorColor;
this.timePoint = maneuver.getTimePoint();
this.timePointBefore = maneuver.getTimePointBefore();
this.maneuverType = maneuver.getType();
@@ -43,6 +45,10 @@ class ManeuverTableData {
return competitorName;
}
public String getCompetitorColor() {
return competitorColor;
}
public Date getTimePoint() {
return timePoint;
}
@@ -34,12 +34,13 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.gwt.ui.actions.GetManeuversForCompetitorsAction;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.ManeuverTypeFormatter;
import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionProvider;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel.LeaderBoardStyle;
import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sse.common.Color;
import com.sap.sse.common.InvertibleComparator;
import com.sap.sse.common.SortingOrder;
import com.sap.sse.common.TimeRange;
@@ -74,7 +75,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
private final ManeuverTablePanelResources resources = GWT.create(ManeuverTablePanelResources.class);
private final StringMessages stringMessages;
private final CompetitorSelectionProvider competitorSelectionModel;
private final RegattaAndRaceIdentifier raceIdentifier;
private final RaceCompetitorSelectionProvider competitorSelectionModel;
private final SimplePanel contentPanel = new SimplePanel();
private final Label importantMessageLabel = new Label();
@@ -88,7 +90,7 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
public ManeuverTablePanel(final Component<?> parent, ComponentContext<?> context,
final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor,
final RegattaAndRaceIdentifier raceIdentifier, final StringMessages stringMessages,
final CompetitorSelectionProvider competitorSelectionModel, final ErrorReporter errorReporter,
final RaceCompetitorSelectionProvider competitorSelectionModel, final ErrorReporter errorReporter,
final Timer timer, final ManeuverTableSettings initialSettings,
final TimeRangeWithZoomModel timeRangeWithZoomProvider, final LeaderBoardStyle style,
final UserService userService) {
@@ -104,10 +106,11 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
userStatusChangeHandler.onUserStatusChange(userService.getCurrentUser(), /* preAuthenticated */ true);
this.resources.css().ensureInjected();
this.settings = initialSettings;
this.raceIdentifier = raceIdentifier;
this.competitorSelectionModel = competitorSelectionModel;
this.stringMessages = stringMessages;
this.competitorDataProvider = new CachedManeuverTableDataProvider(timeRangeWithZoomProvider, timer,
raceIdentifier, sailingService, asyncActionsExecutor);
sailingService, asyncActionsExecutor);
this.competitorSelectionModel.addCompetitorSelectionChangeListener(this);
timer.addTimeListener(this);
final FlowPanel rootPanel = new FlowPanel();
@@ -261,14 +264,23 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
return column;
}
private SortableColumn<ManeuverTableData, String> createCompetitorColumn() {
private SortableColumn<ManeuverTableData, ManeuverTableData> createCompetitorColumn() {
InvertibleComparator<ManeuverTableData> comparator = new InvertibleComparatorAdapter<ManeuverTableData>() {
@Override
public int compare(ManeuverTableData o1, ManeuverTableData o2) {
return o1.getCompetitorName().compareTo(o2.getCompetitorName());
}
};
return new SortableColumn<ManeuverTableData, String>(new TextCell(), SortingOrder.ASCENDING) {
return new SortableColumn<ManeuverTableData, ManeuverTableData>(new AbstractCell<ManeuverTableData>() {
@Override
public void render(Context context, ManeuverTableData data, SafeHtmlBuilder sb) {
final String color = data.getCompetitorColor();
final String divStyle = color == null ? "border: none;" : "border-bottom: 2px solid " + color + ";";
sb.appendHtmlConstant("<div style=\"" + divStyle + "\">");
sb.appendEscaped(data.getCompetitorName());
sb.appendHtmlConstant("</div>");
}
}, SortingOrder.ASCENDING) {
@Override
public InvertibleComparator<ManeuverTableData> getComparator() {
return comparator;
@@ -280,8 +292,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
}
@Override
public String getValue(ManeuverTableData object) {
return object.getCompetitorName();
public ManeuverTableData getValue(ManeuverTableData object) {
return object;
}
};
}
@@ -319,7 +331,8 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
for (final Entry<CompetitorDTO, Iterable<ManeuverDTO>> entry : cachedData.entrySet()) {
for (ManeuverDTO maneuver : entry.getValue()) {
if (settings.getSelectedManeuverTypes().contains(maneuver.getType())) {
data.add(new ManeuverTableData(entry.getKey(), maneuver));
final Color competitorColor = competitorSelectionModel.getColor(entry.getKey(), raceIdentifier);
data.add(new ManeuverTableData(entry.getKey(), competitorColor.getAsHtml(), maneuver));
}
}
}
@@ -427,15 +440,12 @@ public class ManeuverTablePanel extends AbstractCompositeComponent<ManeuverTable
private class CachedManeuverTableDataProvider extends CachedRaceDataProvider<CompetitorDTO, ManeuverDTO> {
private final AsyncActionsExecutor asyncActionsExecutor;
private final RegattaAndRaceIdentifier raceIdentifier;
private final SailingServiceAsync sailingService;
private CachedManeuverTableDataProvider(final TimeRangeProvider timeRangeProvider, final Timer timer,
final RegattaAndRaceIdentifier raceIdentifier, final SailingServiceAsync sailingService,
final AsyncActionsExecutor asyncActionsExecutor) {
final SailingServiceAsync sailingService, final AsyncActionsExecutor asyncActionsExecutor) {
super(timeRangeProvider, timer, m -> m.getTimePoint(), LOADING_OFFSET_TO_NEXT_MANEUVER_PROVIDER, true);
this.asyncActionsExecutor = asyncActionsExecutor;
this.raceIdentifier = raceIdentifier;
this.sailingService = sailingService;
}
@@ -31,7 +31,6 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.Header;
import com.google.gwt.user.cellview.client.SafeHtmlHeader;
import com.google.gwt.user.cellview.client.TextHeader;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Anchor;
@@ -633,7 +632,7 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel {
@Override
public void onSuccess(Void noarg) {
updateScoreCorrectionInformation(lastScoreCorrectionComment, lastScoreCorrectionTime);
Window.alert(stringMessages.successfullyUpdatedScores());
Notification.notify(stringMessages.successfullyUpdatedScores(), NotificationType.SUCCESS);
}
@Override
@@ -15,7 +15,6 @@ import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Timer;
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.CheckBox;
@@ -35,6 +34,8 @@ import com.sap.sailing.gwt.ui.client.MediaTracksRefresher;
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.progressbar.CustomProgressBar;
public class MasterDataImportPanel extends VerticalPanel {
@@ -268,7 +269,7 @@ public class MasterDataImportPanel extends VerticalPanel {
buffer.append(regattaName + "\n");
}
}
Window.alert(buffer.toString());
Notification.notify(buffer.toString(), NotificationType.SUCCESS);
}
@@ -319,7 +320,7 @@ public class MasterDataImportPanel extends VerticalPanel {
}
private void showErrorAlert(String string) {
Window.alert(string);
Notification.notify(string, NotificationType.ERROR);
}
private void addContentToLeftPanel(VerticalPanel contentPanel) {
@@ -49,12 +49,10 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
raceDetailsToShow.add(DetailType.RACE_TIME_TRAVELED);
final SingleRaceLeaderboardSettings additiveSettings = LeaderboardSettingsFactory.getInstance().createNewSettingsWithCustomRaceDetails(raceDetailsToShow);
((RaceBoardComponentContext) leaderboardPanel.getComponentContext()).addModesPatching(leaderboardPanel, additiveSettings, new OnSettingsReloadedCallback<SingleRaceLeaderboardSettings>() {
@Override
public void onSettingsReloaded(SingleRaceLeaderboardSettings patchedSettings) {
leaderboardPanel.updateSettings(patchedSettings);
}
});
}
@@ -79,14 +77,11 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
defaultSettings.isShowEstimatedDuration(),
defaultSettings.getStartCountDownFontSizeScaling(),
defaultSettings.isShowManeuverLossVisualization());
((RaceBoardComponentContext) raceMap.getComponentContext()).addModesPatching(raceMap, additiveSettings, new OnSettingsReloadedCallback<RaceMapSettings>() {
@Override
public void onSettingsReloaded(RaceMapSettings patchedSettings) {
raceMap.updateSettings(patchedSettings);
}
});
}
@@ -129,17 +124,16 @@ public class WinningLanesMode extends RaceBoardModeWithPerRaceCompetitors {
stopReceivingLeaderboard();
adjustLeaderboardSettings();
}
if (adjustedLeaderboardSettings && tailLength != null) {
adjustMapSettings();
}
if (getLeaderboardForSpecificTimePoint() == null && tailLength != null && getLeaderboard() != null && getRaceColumn() != null) {
loadLeaderboardForSpecificTimePoint(getLeaderboard().name, getRaceColumn().getName(), getTimer().getTime());
}
if (!adjustedCompetitorSelection && getLeaderboardForSpecificTimePoint() != null && getCompetitorsInRace() != null) {
stopReceivingCompetitorsInRace();
adjustedCompetitorSelection = true;
updateCompetitorSelection();
}
if (adjustedLeaderboardSettings && tailLength != null && adjustedCompetitorSelection) {
adjustMapSettings();
}
updateCompetitorSelection();
}
}
@@ -17,6 +17,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.DateFormat;
@@ -221,13 +222,22 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi
private VideoMetadataDTO checkMetadataByFullFileDownload(URL input)
throws ParserConfigurationException, SAXException, IOException {
try (IsoFile isof = new IsoFile(Channels.newChannel(input.openStream()))) {
boolean canDownload = true;
Date recordStartedTimer = determineRecordingStart(isof);
Duration duration = determineDuration(isof);
boolean spherical = determine360(isof);
removeTempFiles(isof);
return new VideoMetadataDTO(canDownload, duration, spherical, recordStartedTimer, "");
final File tmp = File.createTempFile("upload", "metadataCheck");
try {
final ReadableByteChannel rbc = Channels.newChannel(input.openStream());
try (FileOutputStream fos = new FileOutputStream(tmp)) {
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
try (IsoFile isof = new IsoFile(tmp)) {
final boolean canDownload = true;
final Date recordStartedTimer = determineRecordingStart(isof);
final Duration duration = determineDuration(isof);
final boolean spherical = determine360(isof);
removeTempFiles(isof);
return new VideoMetadataDTO(canDownload, duration, spherical, recordStartedTimer, "");
}
}
} finally {
Files.delete(tmp.toPath());
}
}
@@ -276,8 +286,9 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi
Field field = box.getClass().getDeclaredField("dataFile");
field.setAccessible(true);
File data = (File) field.get(box);
data.delete();
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
Files.delete(data.toPath());
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException
| IOException e) {
logger.log(Level.WARNING, "Could not delete mp4 temp files", e);
}
}
@@ -1514,7 +1514,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
assert from != null;
TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
WindInfoForRaceDTO result = getAveragedWindInfo(new MillisecondsTimePoint(from), millisecondsStepWidth, numberOfFixes,
windSourceTypeNames, trackedRace, /* onlyUpToNewestEvent */ true, includeCombinedWindForAllLegMiddles);
windSourceTypeNames, trackedRace, /* onlyUpToNewestEvent FIXME why not pass through onlyUpToNewestEvent here??? */ true, includeCombinedWindForAllLegMiddles);
return result;
}
@@ -1853,7 +1853,6 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
boolean extrapolate, LegIdentifier simulationLegIdentifier,
byte[] md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID,
Date timeToGetTheEstimatedDurationFor, boolean estimatedDurationRequired) throws NoWindException {
Duration estimatedDuration = null;
final HashSet<String> raceCompetitorIdsAsStrings;
final TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier);
// if md5OfIdsAsStringOfCompetitorParticipatingInRaceInAlphanumericOrderOfTheirID is null, Arrays.equals will return false, and the
@@ -1866,10 +1865,12 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
raceCompetitorIdsAsStrings.add(c.getId().toString());
}
}
if(estimatedDurationRequired){
estimatedDuration = getEstimationForTargetTime(timeToGetTheEstimatedDurationFor, estimatedDuration, trackedRace);
final Duration estimatedDuration;
if (estimatedDurationRequired) {
estimatedDuration = getEstimationForTargetTime(timeToGetTheEstimatedDurationFor, trackedRace);
} else {
estimatedDuration = null;
}
final Map<CompetitorDTO, List<GPSFixDTOWithSpeedWindTackAndLegType>> boatPositions = getBoatPositionsInternal(raceIdentifier,
fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate);
final CoursePositionsDTO coursePositions = getCoursePositions(raceIdentifier, date);
@@ -1880,18 +1881,17 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
SimulationService simulationService = getService().getSimulationService();
simulationResultVersion = simulationService.getSimulationResultsVersion(simulationLegIdentifier);
}
return new CompactRaceMapDataDTO(boatPositions, coursePositions, courseSidelines, quickRanks,
simulationResultVersion, raceCompetitorIdsAsStrings, estimatedDuration);
}
private Duration getEstimationForTargetTime(Date time, Duration estimatedDuration, final TrackedRace trackedRace) {
if(trackedRace != null){
private Duration getEstimationForTargetTime(Date time, final TrackedRace trackedRace) {
Duration estimatedDuration = null;
if (trackedRace != null) {
try {
estimatedDuration = trackedRace.getEstimatedTimeToComplete(new MillisecondsTimePoint(time)).getExpectedDuration();
} catch (NotEnoughDataHasBeenAddedException | NoWindException e) {
e.printStackTrace();
} finally{
logger.log(Level.WARNING, "Problem computing the estimated race duration", e);
}
}
return estimatedDuration;
@@ -58,6 +58,8 @@ import com.sap.sailing.gwt.ui.simulator.windpattern.WindPatternDisplay;
import com.sap.sailing.simulator.util.SailingSimulatorConstants;
import com.sap.sse.common.impl.RGBColor;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator;
import com.sap.sse.gwt.client.player.Timer;
@@ -998,7 +1000,7 @@ public class SimulatorMap extends AbsolutePanel implements RequiresDataInitializ
}
} else {
Window.alert("No course set, please initialize the course with Start-End input");
Notification.notify("No course set, please initialize the course with Start-End input", NotificationType.ERROR);
}
}
@@ -1,9 +1,11 @@
package com.sap.sailing.polars.datamining.components;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.polars.PolarDataService;
import com.sap.sailing.polars.datamining.data.HasBackendPolarBoatClassContext;
import com.sap.sailing.polars.datamining.data.impl.BoatClassWithBackendPolarContext;
@@ -20,11 +22,15 @@ public class BackendPolarsBoatClassRetrievalProcessor extends AbstractRetrievalP
@Override
protected Iterable<HasBackendPolarBoatClassContext> retrieveData(RacingEventService element) {
Set<HasBackendPolarBoatClassContext> data = new HashSet<>();
PolarDataService polarDataService = element.getPolarDataService();
return polarDataService.getAllBoatClassesWithPolarSheetsAvailable()
.stream()
.map(bc -> new BoatClassWithBackendPolarContext(bc, polarDataService))
.collect(Collectors.toSet());
for (BoatClass boatClass : polarDataService.getAllBoatClassesWithPolarSheetsAvailable()) {
if (isAborted()) {
break;
}
data.add(new BoatClassWithBackendPolarContext(boatClass, polarDataService));
}
return data;
}
}
@@ -25,6 +25,9 @@ public class PolarCompetitorRetrievalProcessor extends AbstractRetrievalProcesso
TrackedRace trackedRace = element.getTrackedRace();
Set<HasCompetitorPolarContext> competitorWithContext = new HashSet<>();
for (Competitor competitor : trackedRace.getRace().getCompetitors()) {
if (isAborted()) {
break;
}
competitorWithContext.add(new CompetitorWithPolarContext(competitor, trackedRace, element.getLeg(), element));
}
return competitorWithContext;
@@ -25,6 +25,9 @@ public class PolarFleetRetrievalProcessor extends AbstractRetrievalProcessor<Has
Set<HasFleetPolarContext> fleetWithContext = new HashSet<>();
RaceColumn raceColumn = element.getRaceColumn();
for (Fleet fleet : raceColumn.getFleets()) {
if (isAborted()) {
break;
}
fleetWithContext.add(new FleetWithPolarContext(fleet, raceColumn, element));
}
return fleetWithContext;
@@ -59,6 +59,9 @@ public class PolarGPSFixRetrievalProcessor extends AbstractRetrievalProcessor<Ha
try {
Iterable<GPSFixMoving> fixes = track.getFixes(startTime, true, finishTime, false);
for (GPSFixMoving fix : fixes) {
if (isAborted()) {
break;
}
WindWithConfidence<Pair<Position, TimePoint>> wind = trackedRace.getWindWithConfidence(
fix.getPosition(),
fix.getTimePoint(),
@@ -1,9 +1,11 @@
package com.sap.sailing.polars.datamining.components;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.polars.datamining.data.HasLeaderboardGroupPolarContext;
import com.sap.sailing.polars.datamining.data.impl.LeaderboardGroupWithPolarContext;
import com.sap.sailing.server.RacingEventService;
@@ -19,11 +21,14 @@ public class PolarLeaderboardGroupRetrievalProcessor extends AbstractRetrievalPr
@Override
protected Iterable<HasLeaderboardGroupPolarContext> retrieveData(RacingEventService element) {
return element.getLeaderboardGroups()
.values()
.stream()
.map(lg -> new LeaderboardGroupWithPolarContext(lg))
.collect(Collectors.toSet());
Set<HasLeaderboardGroupPolarContext> data = new HashSet<>();
for (LeaderboardGroup leaderboardGroup : element.getLeaderboardGroups().values()) {
if (isAborted()) {
break;
}
data.add(new LeaderboardGroupWithPolarContext(leaderboardGroup));
}
return data;
}
}

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