diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracFinishTimeUpdateHandler.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracFinishTimeUpdateHandler.java index 7296f556f9f..a7b4fa74205 100644 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracFinishTimeUpdateHandler.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracFinishTimeUpdateHandler.java @@ -19,14 +19,13 @@ import org.apache.http.message.BasicNameValuePair; import org.json.simple.parser.ParseException; import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; -import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; public class TracTracFinishTimeUpdateHandler extends UpdateHandler { private final static Logger logger = Logger.getLogger(TracTracFinishTimeUpdateHandler.class.getName()); - private final static Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_MINUTE.times(2); private final static String ACTION_STOP_TRACKING = "end_tracking"; private final static String FIELD_TRACKING_END_TIME = "tracking_end_time"; @@ -57,7 +56,8 @@ public class TracTracFinishTimeUpdateHandler extends UpdateHandler { final URI stopTrackingURI = getActionURI(ACTION_STOP_TRACKING); final HttpPost request = new HttpPost(stopTrackingURI); final List params = getDefaultParametersAsNewList(); - params.add(new BasicNameValuePair(FIELD_TRACKING_END_TIME, String.valueOf(newFinishedTime.plus(STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH).asMillis()))); + params.add(new BasicNameValuePair(FIELD_TRACKING_END_TIME, String.valueOf(newFinishedTime.plus( + TrackedRace.STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH).asMillis()))); request.setEntity(new UrlEncodedFormEntity(params)); final HttpClient client = new SystemDefaultHttpClient(); logger.info("Using " + stopTrackingURI.toString() + " to stop tracking"); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracStartTimeUpdateHandler.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracStartTimeUpdateHandler.java index ea6a9ad3838..54a2382852e 100644 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracStartTimeUpdateHandler.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracStartTimeUpdateHandler.java @@ -24,13 +24,12 @@ import org.json.simple.parser.ParseException; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.tracking.StartTimeChangedListener; -import com.sap.sse.common.Duration; +import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sse.common.TimePoint; public class TracTracStartTimeUpdateHandler extends UpdateHandler implements StartTimeChangedListener { private final static Logger logger = Logger.getLogger(TracTracStartTimeUpdateHandler.class.getName()); - private final static Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5); private final static String ACTION = "update_race_start_time"; private final static String ACTION_START_TRACKING = "start_tracking"; private final static String FIELD_RACE_START_TIME = "race_start_time"; @@ -93,7 +92,8 @@ public class TracTracStartTimeUpdateHandler extends UpdateHandler implements Sta final URI startTrackingURI = getActionURI(ACTION_START_TRACKING); final HttpPost request = new HttpPost(startTrackingURI); final List params = getDefaultParametersAsNewList(); - params.add(new BasicNameValuePair(FIELD_TRACKING_START_TIME, String.valueOf(newStartTime.minus(START_TRACKING_THIS_MUCH_BEFORE_RACE_START).asMillis()))); + params.add(new BasicNameValuePair(FIELD_TRACKING_START_TIME, String.valueOf(newStartTime.minus( + TrackedRace.START_TRACKING_THIS_MUCH_BEFORE_RACE_START).asMillis()))); request.setEntity(new UrlEncodedFormEntity(params)); final HttpClient client = new SystemDefaultHttpClient(); logger.info("Using " + startTrackingURI.toString() + " to start tracking"); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java index 7baeb4184e7..f8e010db98c 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedRace.java @@ -77,7 +77,7 @@ import com.sap.sse.common.Util.Pair; */ public interface TrackedRace extends Serializable, IsManagedByCache { final Duration START_TRACKING_THIS_MUCH_BEFORE_RACE_START = Duration.ONE_MINUTE.times(5); - final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_MINUTE.times(1); + final Duration STOP_TRACKING_THIS_MUCH_AFTER_RACE_FINISH = Duration.ONE_SECOND.times(30); final long MAX_TIME_BETWEEN_START_AND_FIRST_MARK_PASSING_IN_MILLISECONDS = 30000; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RaceDetailPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RaceDetailPanel.java index b5413c30a37..f63ded2a00e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RaceDetailPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RaceDetailPanel.java @@ -284,7 +284,7 @@ public class RaceDetailPanel extends SimplePanel { } return bothNullOrEquals(left.courseAreaIdAsString, right.courseAreaIdAsString) - && bothNullOrEquals(left.regattaName, right.regattaName) + && bothNullOrEquals(left.leaderboardName, right.leaderboardName) && bothNullOrEquals(left.raceInfo.seriesName, right.raceInfo.seriesName) && bothNullOrEquals(left.raceInfo.fleetName, right.raceInfo.fleetName) && bothNullOrEquals(left.raceInfo.raceName, right.raceInfo.raceName); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java index d0a743b4a13..b21951c7bca 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaRaceStatesComponent.java @@ -890,8 +890,8 @@ public class RegattaRaceStatesComponent extends AbstractCompositeComponent + * + * When the leaderboard DTO is still empty of {@link #leaderboardNotCurrentlyUpdating not currently being updated}, the + * quick ranks coming from the server will be accepted. Otherwise, once a {@link LeaderboardDTO} has been received, its + * ranking information will take precedence over quick ranks delivered asynchronously from the server. * * @author Axel Uhl (d043530) * @@ -31,15 +36,20 @@ public class QuickRanksDTOFromLeaderboardDTOProvider extends AbstractQuickRanksD private final RaceIdentifier selectedRace; private boolean lastLeaderboardProvidedLegNumbers; private String raceColumnName; + private boolean leaderboardNotCurrentlyUpdating; public QuickRanksDTOFromLeaderboardDTOProvider(RaceCompetitorSet raceCompetitorSet, RaceIdentifier selectedRace) { this.raceCompetitorSet = raceCompetitorSet; this.selectedRace = selectedRace; } + public void setLeaderboardNotCurrentlyUpdating(boolean leaderboardNotCurrentlyUpdating) { + this.leaderboardNotCurrentlyUpdating = leaderboardNotCurrentlyUpdating; + } + @Override public void quickRanksReceivedFromServer(Map quickRanksFromServer) { - if (quickRanks.isEmpty()) { + if (quickRanks.isEmpty() || leaderboardNotCurrentlyUpdating) { for (final Entry e : quickRanksFromServer.entrySet()) { quickRanks.put(e.getKey(), e.getValue()); notifyListeners(e.getKey(), /* oldQuickRank */ null, e.getValue()); @@ -56,7 +66,6 @@ public class QuickRanksDTOFromLeaderboardDTOProvider extends AbstractQuickRanksD } public void updateQuickRanks(final LeaderboardDTO leaderboard) { - RaceColumnDTO raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn == null || !raceColumn.containsRace(selectedRace)) { raceColumnName = getRaceColumnName(leaderboard, selectedRace); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index 15577924386..c76c93bcd18 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -288,6 +288,9 @@ public class RaceBoardPanel leaderboardPanel = createLeaderboardPanel(lifecycle, settings, leaderboardName, leaderboardGroupName, competitorSearchTextBox); addChildComponent(leaderboardPanel); + leaderboardPanel.addVisibilityListener(visible->{ + quickRanksDTOProvider.setLeaderboardNotCurrentlyUpdating(!visible); + }); leaderboardPanel.setTitle(stringMessages.leaderboard()); leaderboardPanel.getElement().getStyle().setMarginLeft(6, Unit.PX); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index e61f2ae62ec..48540151951 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -4531,7 +4531,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } entry.boatClassName = boatClassName; entry.regattaDisplayName = regattaName; - entry.regattaName = leaderboard.getName(); + entry.leaderboardName = leaderboard.getName(); entry.raceInfo = createRaceInfoDTO(seriesName, raceColumn, fleet); entry.currentServerTime = new Date(); entry.buyZoneRadius = buyZoneRadius; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java index 4fdefad43fe..c3c9272bb79 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/RegattaOverviewEntryDTO.java @@ -10,7 +10,7 @@ public class RegattaOverviewEntryDTO implements IsSerializable { public String courseAreaName; public String regattaDisplayName; public RaceInfoDTO raceInfo; - public String regattaName; + public String leaderboardName; public String boatClassName; public Date currentServerTime; public Distance buyZoneRadius; diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEliminatedCompetitorsInLeaderboard.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEliminatedCompetitorsInLeaderboard.java index ab9574de1bb..6da2d1317f1 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEliminatedCompetitorsInLeaderboard.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/operationaltransformation/UpdateEliminatedCompetitorsInLeaderboard.java @@ -1,5 +1,6 @@ package com.sap.sailing.server.operationaltransformation; +import java.util.HashSet; import java.util.Set; import com.sap.sailing.domain.base.Competitor; @@ -19,13 +20,15 @@ public class UpdateEliminatedCompetitorsInLeaderboard extends AbstractLeaderboar @Override public Void internalApplyTo(RacingEventService toState) throws Exception { + // important not to manipulate the operation; create a local copy of the competitors before alterint it; see bug 4247 + final Set myNewEliminatedCompetitors = new HashSet<>(newEliminatedCompetitors); RegattaLeaderboardWithEliminations leaderboard = (RegattaLeaderboardWithEliminations) toState.getLeaderboardByName(getLeaderboardName()); // first un-eliminate those currently eliminated and no longer in newEliminatedCompetitors for (final Competitor c : leaderboard.getEliminatedCompetitors()) { - leaderboard.setEliminated(c, newEliminatedCompetitors.remove(c)); + leaderboard.setEliminated(c, myNewEliminatedCompetitors.remove(c)); } // then eliminated the remaining ones from newEliminatedCompetitors - for (final Competitor c : newEliminatedCompetitors) { + for (final Competitor c : myNewEliminatedCompetitors) { leaderboard.setEliminated(c, true); } updateStoredLeaderboard(toState, leaderboard); diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/AbstractCompositeComponent.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/AbstractCompositeComponent.java index 73bc6b3f7cb..48d1e35f6f7 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/AbstractCompositeComponent.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/AbstractCompositeComponent.java @@ -1,5 +1,8 @@ package com.sap.sse.gwt.client.shared.components; +import java.util.HashSet; +import java.util.Set; + import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.ui.Composite; import com.sap.sse.common.settings.Settings; @@ -8,9 +11,15 @@ import com.sap.sse.gwt.client.shared.settings.ComponentContext; public abstract class AbstractCompositeComponent extends Composite implements Component { private Component parentComponent; private ComponentContext componentContext; + private Set visibilityListeners; + + public static interface VisibilityListener { + void visibilityChanged(boolean visible); + } public AbstractCompositeComponent(Component parent, ComponentContext componentContext) { this.componentContext = componentContext; + this.visibilityListeners = new HashSet<>(); this.parentComponent = parent; if (parentComponent == null) { GWT.log("No parent for component, validate if correct " + this.getClass().getName()); @@ -19,6 +28,29 @@ public abstract class AbstractCompositeComponent GWT.log("No context for component, validate if correct " + this.getClass().getName()); } } + + public void addVisibilityListener(VisibilityListener listener) { + visibilityListeners.add(listener); + } + + public void removeVisibilityListener(VisibilityListener listener) { + visibilityListeners.remove(listener); + } + + @Override + public void setVisible(boolean visible) { + final boolean oldVisible = isVisible(); + super.setVisible(visible); + if (oldVisible != visible) { + notifyVisibilityListeners(visible); + } + } + + private void notifyVisibilityListeners(boolean visible) { + for (final VisibilityListener listener : visibilityListeners) { + listener.visibilityChanged(visible); + } + } public Component getParentComponent() { return parentComponent; diff --git a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF index 549a3404c23..6a0b587aced 100644 --- a/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF +++ b/java/com.tractrac.clientmodule/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: TracTrac Client module Bundle-SymbolicName: com.tractrac.clientmodule -Bundle-Version: 3.7.2 +Bundle-Version: 3.7.3 Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: ., lib/TracAPI.jar diff --git a/java/com.tractrac.clientmodule/README.txt b/java/com.tractrac.clientmodule/README.txt index 1e894f32b7f..f4c2acb8395 100755 --- a/java/com.tractrac.clientmodule/README.txt +++ b/java/com.tractrac.clientmodule/README.txt @@ -16,6 +16,56 @@ It contains also some files: - test.sh -> script that compiles the code in the src folder, creates the test.jar library and execute the code of the example. - Manifest.txt -> manifest used to create the test.jar file +******************************************** +************* TracAPI 3.7.3 **************** +******************************************** +This is a final version. It fixes bugs in the implementation +It keeps the backward compatibility. + +Release date: 24/07/2017 +Build number: 14195 + + 1) Bugs + + - When the specific live delay is updated, the EM sends a message with the new and the + old values to the clients. TracAPI checks if the cached value is equals to the old value and + only in this case, it updates the live delay. If the server sends some wrong values or if a message + is lost, the live delay will never be updated and for this reason this validation has been + removed (Reported By Axel Uhl, 24/07/2017) + +******************************************** +************* TracAPI 3.7.2 **************** +******************************************** +This is a final version. It fixes bugs in the implementation +It keeps the backward compatibility. + +Release date: 21/07/2017 +Build number: 14174 + + 1) Bugs + + - IRace.getCourseArea() is not updated when the race is loaded a second time (Reported By Axel Uhl, 21/07/2017) + +******************************************** +************* TracAPI 3.7.1 **************** +******************************************** +This is a final version. It fixes bugs in the implementation and it adds a some features. +It keeps the backward compatibility. + +Release date: 21/07/2017 +Build number: 14172 + + 1) Features + + - RaceStatusType includes a new value: 9 - Final. The meaning of this value is that the related race has finished and the + splits have been validated (Requested by Chris Terkelsen, 18/07/2017). + + 2) Bugs + + - NullPointerException when the client stops the subscription during the loading progress (it happens sometimes). + The data provider is set to null and one of the threads that sends the positions to the app can use it (Reported + By André Borud, 03/07/2017) + - IRace.getEvent() is null when the race is updated (Reported By Axel Uhl, 21/07/2017) ******************************************** ************* TracAPI 3.7.0 **************** diff --git a/java/com.tractrac.clientmodule/lib/TracAPI-src.jar b/java/com.tractrac.clientmodule/lib/TracAPI-src.jar index 25f1aa9ba75..c90ba50030a 100755 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI-src.jar and b/java/com.tractrac.clientmodule/lib/TracAPI-src.jar differ diff --git a/java/com.tractrac.clientmodule/lib/TracAPI.jar b/java/com.tractrac.clientmodule/lib/TracAPI.jar index 0207a26b72b..60404d42291 100755 Binary files a/java/com.tractrac.clientmodule/lib/TracAPI.jar and b/java/com.tractrac.clientmodule/lib/TracAPI.jar differ diff --git a/java/com.tractrac.clientmodule/pom.xml b/java/com.tractrac.clientmodule/pom.xml index db095952159..ceff921c0b7 100755 --- a/java/com.tractrac.clientmodule/pom.xml +++ b/java/com.tractrac.clientmodule/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.tractrac.clientmodule - 3.7.2 + 3.7.3 eclipse-plugin