Checking only Permission.CAN_REPLAY_DURING_LIVE_RACES to provide

respective functionality (removed url parameter handling)
This commit is contained in:
Benjamin Barth committed 2016-02-03 14:59:31 +01:00
1 parent 6bb463af27
commit 5ba87eb856
5 files changed
+342 -319

No files matched your search

@@ -79,7 +79,7 @@ public class PlayerActivity extends AbstractActivity {
final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default */);
return new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard,
showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, /* canReplayWhileLiveIsPossible */false, autoSelectMedia, defaultMedia);
showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, autoSelectMedia, defaultMedia);
}
private void createErrorView(String errorMessage, Throwable errorReason, AcceptsOneWidget panel) {
@@ -1,299 +1,334 @@
package com.sap.sailing.gwt.ui.client;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements RaceTimesInfoProviderListener {
private final RaceTimesInfoProvider raceTimesInfoProvider;
private RegattaAndRaceIdentifier selectedRace;
private boolean autoAdjustPlayMode;
private RaceTimesInfoDTO lastRaceTimesInfo;
/**
* When a marker update is required but min/max are not yet initialized, this flag is set. If later
* {@link #setMinMax(Date, Date, boolean)} is invoked and this flag is set, a {@link #redrawAllMarkers(RaceTimesInfoDTO)}
* will be issued and the flag is cleared.
*/
private boolean redrawAllMarkersPendingForMinMaxBeingInitialized;
public RaceTimePanel(Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible, boolean isScreenLargeEnoughToOfferChartSupport,
RegattaAndRaceIdentifier selectedRaceIdentifier) {
super(timer, timeRangeProvider, stringMessages, canReplayWhileLiveIsPossible, isScreenLargeEnoughToOfferChartSupport);
this.raceTimesInfoProvider = raceTimesInfoProvider;
selectedRace = null;
autoAdjustPlayMode = true;
selectedRace = selectedRaceIdentifier;
if (!raceTimesInfoProvider.containsRaceIdentifier(selectedRace)) {
raceTimesInfoProvider.addRaceIdentifier(selectedRace, true);
}
}
/**
* If the race's start time is already known and the <code>time</code> is before the start we can set the count-down label
*/
@Override
protected String getTimeToStartLabelText(Date time) {
String result = null;
RaceTimesInfoDTO selectedRaceTimes = raceTimesInfoProvider.getRaceTimesInfo(selectedRace);
if (selectedRaceTimes.startOfRace != null) {
if (time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) {
long timeToStartInMs = selectedRaceTimes.startOfRace.getTime() - time.getTime();
result = timeToStartInMs < 1000 ? stringMessages.start() : stringMessages.timeToStart(DateAndTimeFormatterUtil.formatElapsedTime(timeToStartInMs));
} else {
long timeSinceStartInMs = time.getTime() - selectedRaceTimes.startOfRace.getTime();
result = stringMessages.timeSinceStart(DateAndTimeFormatterUtil.formatElapsedTime(timeSinceStartInMs));
}
}
return result;
}
@Override
public void updateSettings(RaceTimePanelSettings newSettings) {
super.updateSettings(newSettings);
raceTimesInfoProvider.setRequestInterval(newSettings.getRefreshInterval());
}
@Override
public RaceTimePanelSettings getSettings() {
RaceTimePanelSettings result = new RaceTimePanelSettings();
result.setRefreshInterval(timer.getRefreshInterval());
result.setRaceTimesInfo(raceTimesInfoProvider.getRaceTimesInfo(selectedRace));
return result;
}
@Override
public SettingsDialogComponent<RaceTimePanelSettings> getSettingsDialogComponent() {
return new RaceTimePanelSettingsDialogComponent(getSettings(), stringMessages);
}
private void updateTimeInfo(RaceTimesInfoDTO raceTimesInfo) {
if (raceTimesInfo == null) {
// in case the race is not tracked anymore we reset the time slider
resetTimeSlider();
} else {
// timer will only accept this update if the delay hasn't been updated explicitly
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) &&
(raceTimesInfo.newestTrackingEvent != null || raceTimesInfo.endOfRace != null || raceTimesInfo.endOfTracking != null)) {
// we set here the min and max of the time slider, the start and end of the race as well as the known
// leg markers
boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
setLiveGenerallyPossible(liveModeToBeMadePossible);
setJumpToLiveEnablement(liveModeToBeMadePossible && timer.getPlayMode() != PlayModes.Live);
if (autoAdjustPlayMode && liveModeToBeMadePossible) {
timer.setPlayMode(PlayModes.Live);
}
updatePlayPauseButtonsVisibility(timer.getPlayMode());
if (liveModeToBeMadePossible && !canReplayWhileLiveIsPossible() &&
timer.getPlayMode()==PlayModes.Replay && timer.getPlayState()==PlayStates.Playing) {
// pause timer because it must not be playing in replay mode while the race is live
timer.pause();
}
boolean timerAlreadyInitialized = getFromTime() != null && getToTime() != null && timeSlider.getCurrentValue() != null;
if (!timeRangeProvider.isZoomed()) {
updateMinMax(raceTimesInfo);
if (!timerAlreadyInitialized) {
initTimerPosition(raceTimesInfo);
}
updateLegMarkers(raceTimesInfo);
}
} else {
// the tracked race did not start yet or has no events yet
// maybe show a special state for this like "Race did not start yet"
}
}
lastRaceTimesInfo = raceTimesInfo; // TODO bug 3122: when not redrawn yet because min/max not initialized yet, further redraw is disabled by this.
}
@Override
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
super.onTimeZoomChanged(zoomStartTimepoint, zoomEndTimepoint);
timeSlider.setZoomed(true);
setMinMax(zoomStartTimepoint, zoomEndTimepoint, false);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
@Override
public void onTimeZoomReset() {
super.onTimeZoomReset();
timeSlider.setZoomed(false);
timeSlider.setMinValue(new Double(timeRangeProvider.getFromTime().getTime()), false);
timeSlider.setMaxValue(new Double(timeRangeProvider.getToTime().getTime()), false);
timeSlider.setCurrentValue(new Double(timer.getTime().getTime()), true);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
/**
* If and only if the {@link #selectedRace}'s timing is described by the {@link #raceTimesInfoProvider} and
* according to the timing the current live time point is after the start of tracking or at least after three
* minutes before the race, and the current live time point is not after the end of tracking then live mode will be
* made possible (<code>true</code> will be returned).
*/
@Override
protected boolean isLiveModeToBeMadePossible() {
long liveTimePointInMillis = timer.getLiveTimePointInMillis();
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
return lastRaceTimesInfo != null &&
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()) ||
(lastRaceTimesInfo.startOfRace != null && liveTimePointInMillis > lastRaceTimesInfo.startOfRace.getTime() - RaceTimesCalculationUtil.MIN_TIME_BEFORE_RACE_START)) &&
(lastRaceTimesInfo.endOfTracking == null || liveTimePointInMillis <= lastRaceTimesInfo.endOfTracking.getTime());
}
@Override
public void playStateChanged(PlayStates playState, PlayModes playMode) {
super.playStateChanged(playState, playMode);
switch (playMode) {
case Replay:
autoAdjustPlayMode = false;
break;
case Live:
break;
}
}
/**
* Obtains the min/max range for the slider bar from <code>newRaceTimesInfo</code> and adjusts the slider bar if
* needed. Since we extend the slider bar to the right when playing across the "end of time," we don't want to
* constrain it back again here. Therefore, the max value is never reduced here but at best initially set if it
* was <code>null</code> before, or extended to a later point in time.
*/
private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) {
Util.Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.caluclateRaceMinMax(timer, newRaceTimesInfo);
Date min = raceMinMax.getA();
Date max = raceMinMax.getB();
// never reduce max if it was already set
if (min != null && max != null && (getToTime() == null || getToTime().before(max))) {
setMinMax(min, max, /* fireEvent */ false); // no event because we guarantee time to be between min and max
}
}
@Override
public void setMinMax(Date min, Date max, boolean fireEvent) {
super.setMinMax(min, max, fireEvent);
if (redrawAllMarkersPendingForMinMaxBeingInitialized && timeSlider.isMinMaxInitialized()) {
redrawAllMarkers(lastRaceTimesInfo);
redrawAllMarkersPendingForMinMaxBeingInitialized = false;
}
}
/**
* When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was
* finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the
* {@link RaceTimesInfoDTO#endOfRace end of the race}. If that happens to be undefined (<code>null</code>), the
* {@link RaceTimesInfoDTO#startOfRace start of the race} is used instead. If that isn't available either, the timer
* remains unchanged.
* <p>
*
* When in {@link PlayModes#Live} mode, tries to advance the timer to the time point of the
* {@link RaceTimesInfoDTO#timePointOfNewestEvent timePointOfNewestEvent} received from the tracking infrastructure
* so far and puts the timer into {@link PlayStates#Playing play mode}.
*/
private void initTimerPosition(RaceTimesInfoDTO newRaceTimesInfo) {
// initialize timer position
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.newestTrackingEvent != null) {
timer.setTime(newRaceTimesInfo.newestTrackingEvent.getTime());
}
timer.play();
break;
case Replay:
// set time to start of race
if (newRaceTimesInfo.startOfRace != null) {
timer.setTime(newRaceTimesInfo.startOfRace.getTime());
}
break;
}
}
/**
* Expected to be called before {@link #lastRaceTimesInfo} has been updated to <code>newRaceTimesInfo</code>
*/
private void updateLegMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
boolean requiresMarkerUpdate = true;
// updating the sliderbar markers requires a lot of time, therefore we need to do this only if required
if (lastRaceTimesInfo != null && lastRaceTimesInfo.markPassingTimes.size() == newRaceTimesInfo.markPassingTimes.size()) {
requiresMarkerUpdate = false;
int numberOfLegs = newRaceTimesInfo.markPassingTimes.size();
for (int i = 0; i < numberOfLegs; i++) {
if (!Util.equalsWithNull(newRaceTimesInfo.markPassingTimes.get(i).firstPassingDate, lastRaceTimesInfo.markPassingTimes.get(i).firstPassingDate)) {
requiresMarkerUpdate = true;
break;
}
}
if ((lastRaceTimesInfo.startOfRace == null && newRaceTimesInfo.startOfRace != null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace == null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace != null
&& lastRaceTimesInfo.startOfRace.getTime() != newRaceTimesInfo.startOfRace.getTime())) {
requiresMarkerUpdate = true;
}
if ((lastRaceTimesInfo.endOfRace == null && newRaceTimesInfo.endOfRace != null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace == null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace != null
&& lastRaceTimesInfo.endOfRace.getTime() != newRaceTimesInfo.endOfRace.getTime())) {
requiresMarkerUpdate = true;
}
}
if (requiresMarkerUpdate) {
if (timeSlider.isMinMaxInitialized()) { // TODO bug 3122 later, the lastRaceTimesInfo will be updated even if not redrawn because min/max not initialized
redrawAllMarkers(newRaceTimesInfo);
} else {
redrawAllMarkersPendingForMinMaxBeingInitialized = true;
}
}
}
private void redrawAllMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
List<MarkPassingTimesDTO> markPassingTimes = newRaceTimesInfo.getMarkPassingTimes();
timeSlider.clearMarkers();
if (newRaceTimesInfo.startOfRace != null) {
long markerTime = newRaceTimesInfo.startOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("S", new Double(markerTime));
}
}
int markPassingCounter = 1;
for (MarkPassingTimesDTO markPassingTimesDTO: markPassingTimes) {
// ignore the start mark passing
if (markPassingCounter > 1 && markPassingTimesDTO.firstPassingDate != null) {
long markerTime = markPassingTimesDTO.firstPassingDate.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker(markPassingTimesDTO.getName(), new Double(markerTime));
}
}
markPassingCounter++;
}
if (newRaceTimesInfo.endOfRace != null) {
long markerTime = newRaceTimesInfo.endOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("E", new Double(markerTime));
}
}
timeSlider.redraw();
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
updateTimeInfo(raceTimesInfos.get(selectedRace));
}
}
package com.sap.sailing.gwt.ui.client;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.player.TimeRangeWithZoomProvider;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
import com.sap.sse.gwt.client.shared.components.SettingsDialogComponent;
import com.sap.sse.security.ui.client.UserService;
import com.sap.sse.security.ui.client.UserStatusEventHandler;
import com.sap.sse.security.ui.shared.UserDTO;
public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements RaceTimesInfoProviderListener {
private final RaceTimesInfoProvider raceTimesInfoProvider;
private RegattaAndRaceIdentifier selectedRace;
private boolean autoAdjustPlayMode;
private RaceTimesInfoDTO lastRaceTimesInfo;
private boolean hasCanReplayDuringLiveRacesPermission = false;
private final UserService userService;
private final UserStatusEventHandler userStatusEventHandler = new UserStatusEventHandler() {
@Override
public void onUserStatusChange(UserDTO user) {
RaceTimePanel.this.hasCanReplayDuringLiveRacesPermission = user != null && user.hasPermission(
Permission.CAN_REPLAY_DURING_LIVE_RACES.getStringPermission(), SailingPermissionsForRoleProvider.INSTANCE);
}
};
/**
* When a marker update is required but min/max are not yet initialized, this flag is set. If later
* {@link #setMinMax(Date, Date, boolean)} is invoked and this flag is set, a {@link #redrawAllMarkers(RaceTimesInfoDTO)}
* will be issued and the flag is cleared.
*/
private boolean redrawAllMarkersPendingForMinMaxBeingInitialized;
public RaceTimePanel(UserService userService, Timer timer, TimeRangeWithZoomProvider timeRangeProvider, StringMessages stringMessages,
RaceTimesInfoProvider raceTimesInfoProvider, boolean canReplayWhileLiveIsPossible, boolean isScreenLargeEnoughToOfferChartSupport,
RegattaAndRaceIdentifier selectedRaceIdentifier) {
super(timer, timeRangeProvider, stringMessages, canReplayWhileLiveIsPossible, isScreenLargeEnoughToOfferChartSupport);
this.userService = userService;
this.raceTimesInfoProvider = raceTimesInfoProvider;
selectedRace = null;
autoAdjustPlayMode = true;
selectedRace = selectedRaceIdentifier;
if (!raceTimesInfoProvider.containsRaceIdentifier(selectedRace)) {
raceTimesInfoProvider.addRaceIdentifier(selectedRace, true);
}
}
@Override
protected void onLoad() {
super.onLoad();
userService.addUserStatusEventHandler(userStatusEventHandler);
userStatusEventHandler.onUserStatusChange(userService.getCurrentUser());
}
@Override
protected void onUnload() {
super.onUnload();
userService.removeUserStatusEventHandler(userStatusEventHandler);
}
@Override
protected boolean canReplayWhileLiveIsPossible() {
return this.hasCanReplayDuringLiveRacesPermission;
}
/**
* If the race's start time is already known and the <code>time</code> is before the start we can set the count-down label
*/
@Override
protected String getTimeToStartLabelText(Date time) {
String result = null;
RaceTimesInfoDTO selectedRaceTimes = raceTimesInfoProvider.getRaceTimesInfo(selectedRace);
if (selectedRaceTimes.startOfRace != null) {
if (time.before(selectedRaceTimes.startOfRace) || time.equals(selectedRaceTimes.startOfRace)) {
long timeToStartInMs = selectedRaceTimes.startOfRace.getTime() - time.getTime();
result = timeToStartInMs < 1000 ? stringMessages.start() : stringMessages.timeToStart(DateAndTimeFormatterUtil.formatElapsedTime(timeToStartInMs));
} else {
long timeSinceStartInMs = time.getTime() - selectedRaceTimes.startOfRace.getTime();
result = stringMessages.timeSinceStart(DateAndTimeFormatterUtil.formatElapsedTime(timeSinceStartInMs));
}
}
return result;
}
@Override
public void updateSettings(RaceTimePanelSettings newSettings) {
super.updateSettings(newSettings);
raceTimesInfoProvider.setRequestInterval(newSettings.getRefreshInterval());
}
@Override
public RaceTimePanelSettings getSettings() {
RaceTimePanelSettings result = new RaceTimePanelSettings();
result.setRefreshInterval(timer.getRefreshInterval());
result.setRaceTimesInfo(raceTimesInfoProvider.getRaceTimesInfo(selectedRace));
return result;
}
@Override
public SettingsDialogComponent<RaceTimePanelSettings> getSettingsDialogComponent() {
return new RaceTimePanelSettingsDialogComponent(getSettings(), stringMessages);
}
private void updateTimeInfo(RaceTimesInfoDTO raceTimesInfo) {
if (raceTimesInfo == null) {
// in case the race is not tracked anymore we reset the time slider
resetTimeSlider();
} else {
// timer will only accept this update if the delay hasn't been updated explicitly
timer.setLivePlayDelayInMillis(raceTimesInfo.delayToLiveInMs);
if ((raceTimesInfo.startOfTracking != null || raceTimesInfo.startOfRace != null) &&
(raceTimesInfo.newestTrackingEvent != null || raceTimesInfo.endOfRace != null || raceTimesInfo.endOfTracking != null)) {
// we set here the min and max of the time slider, the start and end of the race as well as the known
// leg markers
boolean liveModeToBeMadePossible = isLiveModeToBeMadePossible();
setLiveGenerallyPossible(liveModeToBeMadePossible);
setJumpToLiveEnablement(liveModeToBeMadePossible && timer.getPlayMode() != PlayModes.Live);
if (autoAdjustPlayMode && liveModeToBeMadePossible) {
timer.setPlayMode(PlayModes.Live);
}
updatePlayPauseButtonsVisibility(timer.getPlayMode());
if (liveModeToBeMadePossible && !canReplayWhileLiveIsPossible() &&
timer.getPlayMode()==PlayModes.Replay && timer.getPlayState()==PlayStates.Playing) {
// pause timer because it must not be playing in replay mode while the race is live
timer.pause();
}
boolean timerAlreadyInitialized = getFromTime() != null && getToTime() != null && timeSlider.getCurrentValue() != null;
if (!timeRangeProvider.isZoomed()) {
updateMinMax(raceTimesInfo);
if (!timerAlreadyInitialized) {
initTimerPosition(raceTimesInfo);
}
updateLegMarkers(raceTimesInfo);
}
} else {
// the tracked race did not start yet or has no events yet
// maybe show a special state for this like "Race did not start yet"
}
}
lastRaceTimesInfo = raceTimesInfo; // TODO bug 3122: when not redrawn yet because min/max not initialized yet, further redraw is disabled by this.
}
@Override
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
super.onTimeZoomChanged(zoomStartTimepoint, zoomEndTimepoint);
timeSlider.setZoomed(true);
setMinMax(zoomStartTimepoint, zoomEndTimepoint, false);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
@Override
public void onTimeZoomReset() {
super.onTimeZoomReset();
timeSlider.setZoomed(false);
timeSlider.setMinValue(new Double(timeRangeProvider.getFromTime().getTime()), false);
timeSlider.setMaxValue(new Double(timeRangeProvider.getToTime().getTime()), false);
timeSlider.setCurrentValue(new Double(timer.getTime().getTime()), true);
timeSlider.clearMarkersAndLabelsAndTicks();
redrawAllMarkers(lastRaceTimesInfo);
}
/**
* If and only if the {@link #selectedRace}'s timing is described by the {@link #raceTimesInfoProvider} and
* according to the timing the current live time point is after the start of tracking or at least after three
* minutes before the race, and the current live time point is not after the end of tracking then live mode will be
* made possible (<code>true</code> will be returned).
*/
@Override
protected boolean isLiveModeToBeMadePossible() {
long liveTimePointInMillis = timer.getLiveTimePointInMillis();
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
return lastRaceTimesInfo != null &&
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()) ||
(lastRaceTimesInfo.startOfRace != null && liveTimePointInMillis > lastRaceTimesInfo.startOfRace.getTime() - RaceTimesCalculationUtil.MIN_TIME_BEFORE_RACE_START)) &&
(lastRaceTimesInfo.endOfTracking == null || liveTimePointInMillis <= lastRaceTimesInfo.endOfTracking.getTime());
}
@Override
public void playStateChanged(PlayStates playState, PlayModes playMode) {
super.playStateChanged(playState, playMode);
switch (playMode) {
case Replay:
autoAdjustPlayMode = false;
break;
case Live:
break;
}
}
/**
* Obtains the min/max range for the slider bar from <code>newRaceTimesInfo</code> and adjusts the slider bar if
* needed. Since we extend the slider bar to the right when playing across the "end of time," we don't want to
* constrain it back again here. Therefore, the max value is never reduced here but at best initially set if it
* was <code>null</code> before, or extended to a later point in time.
*/
private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) {
Util.Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.caluclateRaceMinMax(timer, newRaceTimesInfo);
Date min = raceMinMax.getA();
Date max = raceMinMax.getB();
// never reduce max if it was already set
if (min != null && max != null && (getToTime() == null || getToTime().before(max))) {
setMinMax(min, max, /* fireEvent */ false); // no event because we guarantee time to be between min and max
}
}
@Override
public void setMinMax(Date min, Date max, boolean fireEvent) {
super.setMinMax(min, max, fireEvent);
if (redrawAllMarkersPendingForMinMaxBeingInitialized && timeSlider.isMinMaxInitialized()) {
redrawAllMarkers(lastRaceTimesInfo);
redrawAllMarkersPendingForMinMaxBeingInitialized = false;
}
}
/**
* When in {@link PlayModes#Replay} mode, tries to put the {@link #timer} to the time point when the last leg was
* finished first. If this time point is not (yet?) known, tries to put the {@link #timer} to the
* {@link RaceTimesInfoDTO#endOfRace end of the race}. If that happens to be undefined (<code>null</code>), the
* {@link RaceTimesInfoDTO#startOfRace start of the race} is used instead. If that isn't available either, the timer
* remains unchanged.
* <p>
*
* When in {@link PlayModes#Live} mode, tries to advance the timer to the time point of the
* {@link RaceTimesInfoDTO#timePointOfNewestEvent timePointOfNewestEvent} received from the tracking infrastructure
* so far and puts the timer into {@link PlayStates#Playing play mode}.
*/
private void initTimerPosition(RaceTimesInfoDTO newRaceTimesInfo) {
// initialize timer position
switch (timer.getPlayMode()) {
case Live:
if (newRaceTimesInfo.newestTrackingEvent != null) {
timer.setTime(newRaceTimesInfo.newestTrackingEvent.getTime());
}
timer.play();
break;
case Replay:
// set time to start of race
if (newRaceTimesInfo.startOfRace != null) {
timer.setTime(newRaceTimesInfo.startOfRace.getTime());
}
break;
}
}
/**
* Expected to be called before {@link #lastRaceTimesInfo} has been updated to <code>newRaceTimesInfo</code>
*/
private void updateLegMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
boolean requiresMarkerUpdate = true;
// updating the sliderbar markers requires a lot of time, therefore we need to do this only if required
if (lastRaceTimesInfo != null && lastRaceTimesInfo.markPassingTimes.size() == newRaceTimesInfo.markPassingTimes.size()) {
requiresMarkerUpdate = false;
int numberOfLegs = newRaceTimesInfo.markPassingTimes.size();
for (int i = 0; i < numberOfLegs; i++) {
if (!Util.equalsWithNull(newRaceTimesInfo.markPassingTimes.get(i).firstPassingDate, lastRaceTimesInfo.markPassingTimes.get(i).firstPassingDate)) {
requiresMarkerUpdate = true;
break;
}
}
if ((lastRaceTimesInfo.startOfRace == null && newRaceTimesInfo.startOfRace != null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace == null)
|| (lastRaceTimesInfo.startOfRace != null && newRaceTimesInfo.startOfRace != null
&& lastRaceTimesInfo.startOfRace.getTime() != newRaceTimesInfo.startOfRace.getTime())) {
requiresMarkerUpdate = true;
}
if ((lastRaceTimesInfo.endOfRace == null && newRaceTimesInfo.endOfRace != null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace == null)
|| (lastRaceTimesInfo.endOfRace != null && newRaceTimesInfo.endOfRace != null
&& lastRaceTimesInfo.endOfRace.getTime() != newRaceTimesInfo.endOfRace.getTime())) {
requiresMarkerUpdate = true;
}
}
if (requiresMarkerUpdate) {
if (timeSlider.isMinMaxInitialized()) { // TODO bug 3122 later, the lastRaceTimesInfo will be updated even if not redrawn because min/max not initialized
redrawAllMarkers(newRaceTimesInfo);
} else {
redrawAllMarkersPendingForMinMaxBeingInitialized = true;
}
}
}
private void redrawAllMarkers(RaceTimesInfoDTO newRaceTimesInfo) {
List<MarkPassingTimesDTO> markPassingTimes = newRaceTimesInfo.getMarkPassingTimes();
timeSlider.clearMarkers();
if (newRaceTimesInfo.startOfRace != null) {
long markerTime = newRaceTimesInfo.startOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("S", new Double(markerTime));
}
}
int markPassingCounter = 1;
for (MarkPassingTimesDTO markPassingTimesDTO: markPassingTimes) {
// ignore the start mark passing
if (markPassingCounter > 1 && markPassingTimesDTO.firstPassingDate != null) {
long markerTime = markPassingTimesDTO.firstPassingDate.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker(markPassingTimesDTO.getName(), new Double(markerTime));
}
}
markPassingCounter++;
}
if (newRaceTimesInfo.endOfRace != null) {
long markerTime = newRaceTimesInfo.endOfRace.getTime();
if (!timeSlider.isZoomed() || (timeSlider.isZoomed() && markerTime > timeSlider.getMinValue() && markerTime < timeSlider.getMaxValue())) {
timeSlider.addMarker("E", new Double(markerTime));
}
}
timeSlider.redraw();
}
@Override
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos, long clientTimeWhenRequestWasSent, Date serverTimeDuringRequest, long clientTimeWhenResponseWasReceived) {
timer.adjustClientServerOffset(clientTimeWhenRequestWasSent, serverTimeDuringRequest, clientTimeWhenResponseWasReceived);
updateTimeInfo(raceTimesInfos.get(selectedRace));
}
}
@@ -17,8 +17,6 @@ import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.sap.sailing.domain.common.security.Permission;
import com.sap.sailing.domain.common.security.SailingPermissionsForRoleProvider;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
import com.sap.sailing.gwt.ui.client.LogoAndTitlePanel;
import com.sap.sailing.gwt.ui.client.MediaService;
@@ -87,14 +85,11 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
boolean showViewStreamletColors = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_STREAMLET_COLORS, false /* default*/);
boolean showViewSimulation = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_SIMULATION, true /* default*/);
String activeCompetitorsFilterSetName = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_VIEW_COMPETITOR_FILTER, null /* default*/);
// TODO Remove CAN_REPLAY_DURING_LIVE_RACES url parameter handling (which is used as fallback) after successful adaption of user permissions
final boolean canReplayWhileLiveIsPossible = getUserService().getCurrentUser().hasPermission(Permission.CAN_REPLAY_DURING_LIVE_RACES.getStringPermission(),
SailingPermissionsForRoleProvider.INSTANCE) || GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, false);
final boolean autoSelectMedia = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_AUTOSELECT_MEDIA, true);
final String defaultMedia = GwtHttpRequestUtils.getStringParameter(RaceBoardViewConfiguration.PARAM_DEFAULT_MEDIA, null /* default*/);
final boolean showMapControls = GwtHttpRequestUtils.getBooleanParameter(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, true /* default*/);
raceboardViewConfig = new RaceBoardViewConfiguration(activeCompetitorsFilterSetName, showLeaderboard,
showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, canReplayWhileLiveIsPossible, autoSelectMedia, defaultMedia);
showWindChart, showCompetitorsChart, showViewStreamlets, showViewStreamletColors, showViewSimulation, autoSelectMedia, defaultMedia);
sailingService.getRaceboardData(regattaName, raceName, leaderboardName, leaderboardGroupName, eventId, new AsyncCallback<RaceboardDataDTO>() {
@Override
public void onSuccess(RaceboardDataDTO result) {
@@ -102,8 +97,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
// This decision is made once based on the initial screen height. Resizing the window afterwards will have
// no impact on the chart support, i.e. they are available/unavailable based on the initial decision.
boolean isScreenLargeEnoughToOfferChartSupport = Document.get().getClientHeight() >= 600;
checkUrlParameters(result, canReplayWhileLiveIsPossible, showMapControls,
isScreenLargeEnoughToOfferChartSupport);
checkUrlParameters(result, showMapControls, isScreenLargeEnoughToOfferChartSupport);
}
@Override
@@ -122,7 +116,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint {
vp.add(new Label(message));
}
private void checkUrlParameters(RaceboardDataDTO raceboardData, boolean canReplayWhileLiveIsPossible, boolean showMapControls,
private void checkUrlParameters(RaceboardDataDTO raceboardData, boolean showMapControls,
boolean isScreenLargeEnoughToOfferChartSupport) {
if (!raceboardData.isValidLeaderboard()) {
createErrorPage(getStringMessages().noSuchLeaderboard());
@@ -238,8 +238,8 @@ public class RaceBoardPanel extends SimplePanel implements LeaderboardUpdateList
}
}
}
timePanel = new RaceTimePanel(timer, timeRangeWithZoomModel, stringMessages, raceTimesInfoProvider,
raceboardViewConfiguration.isCanReplayDuringLiveRaces(), isScreenLargeEnoughToOfferChartSupport, selectedRaceIdentifier);
timePanel = new RaceTimePanel(userService, timer, timeRangeWithZoomModel, stringMessages, raceTimesInfoProvider,
false, isScreenLargeEnoughToOfferChartSupport, selectedRaceIdentifier);
timeRangeWithZoomModel.addTimeZoomChangeListener(timePanel);
raceTimesInfoProvider.addRaceTimesInfoProviderListener(timePanel);
}
@@ -10,7 +10,6 @@ public class RaceBoardViewConfiguration {
private final boolean showWindChart;
private final boolean showCompetitorsChart;
private final String activeCompetitorsFilterSetName;
private final boolean canReplayDuringLiveRaces;
private final boolean autoSelectMedia;
private final String defaultMedia;
private final boolean showViewStreamlets;
@@ -34,11 +33,11 @@ public class RaceBoardViewConfiguration {
public RaceBoardViewConfiguration() {
this(/* activeCompetitorsFilterSetName */ null, /* showLeaderboard */ true,
/* showWindChart */ false, /* showCompetitorsChart */ false, /* showViewStreamlets */ false, /* showViewStreamletColors */ false, /* showViewSimulation */ false,
/* canReplayDuringLiveRaces */false, /* autoSelectMedia */false, null);
/* autoSelectMedia */false, null);
}
public RaceBoardViewConfiguration(String activeCompetitorsFilterSetName, boolean showLeaderboard,
boolean showWindChart, boolean showCompetitorsChart, boolean showViewStreamlets, boolean showViewStreamletColors, boolean showViewSimulation, boolean canReplayDuringLiveRaces,
boolean showWindChart, boolean showCompetitorsChart, boolean showViewStreamlets, boolean showViewStreamletColors, boolean showViewSimulation,
boolean autoSelectMedia, String defaultMedia) {
this.activeCompetitorsFilterSetName = activeCompetitorsFilterSetName;
this.showLeaderboard = showLeaderboard;
@@ -47,7 +46,6 @@ public class RaceBoardViewConfiguration {
this.showViewStreamlets = showViewStreamlets;
this.showViewStreamletColors = showViewStreamletColors;
this.showViewSimulation = showViewSimulation;
this.canReplayDuringLiveRaces = canReplayDuringLiveRaces;
this.autoSelectMedia = autoSelectMedia;
this.defaultMedia = defaultMedia;
}
@@ -80,10 +78,6 @@ public class RaceBoardViewConfiguration {
return activeCompetitorsFilterSetName;
}
public boolean isCanReplayDuringLiveRaces() {
return canReplayDuringLiveRaces;
}
public boolean isAutoSelectMedia() {
return autoSelectMedia;
}