mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-06 02:52:22 +00:00
Merge branch 'bug5029'
This commit is contained in:
commit
b1f5d43513
7 files changed
+147
-160
No files matched your search
+53
@@ -0,0 +1,53 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sse.common.Util;
|
||||
|
||||
public class RaceTimesCalculationUtil {
|
||||
public static final long MIN_TIME_BEFORE_RACE_START = 3 * 60 * 1000; // 3 minutes
|
||||
public static final long MIN_TIME_AFTER_RACE_START = 5 * 60 * 1000; // 5 minutes
|
||||
public static final long TIME_AFTER_LIVE = 5 * 60 * 1000; // 5 minutes
|
||||
public static final long MAX_TIME_AFTER_RACE_END = 3 * 60 * 1000; // 3 minutes
|
||||
|
||||
public static Util.Pair<Date, Date> calculateRaceMinMax(Date liveTimePoint, Date startOfTracking, Date startOfRace,
|
||||
Date raceFinishingTime, Date raceFinishedTime, Date endOfRace, Date endOfTracking) {
|
||||
if (liveTimePoint == null) {
|
||||
return new Util.Pair<Date, Date>(null, null);
|
||||
}
|
||||
Date min = null;
|
||||
Date max = null;
|
||||
|
||||
// Range start / min
|
||||
if (startOfRace != null) {
|
||||
// We have a start time
|
||||
min = new Date(startOfRace.getTime() - MIN_TIME_BEFORE_RACE_START);
|
||||
} else if (startOfTracking != null) {
|
||||
// We at least have a start of tracking time
|
||||
min = startOfTracking;
|
||||
}
|
||||
if (min == null || liveTimePoint.before(min)){
|
||||
// There is no start time or the start time is in the future
|
||||
min = new Date(liveTimePoint.getTime());
|
||||
}
|
||||
|
||||
// Range end / max
|
||||
if (raceFinishedTime != null) {
|
||||
// We have a blue flag down event
|
||||
max = new Date(raceFinishedTime.getTime() + MAX_TIME_AFTER_RACE_END);
|
||||
} else if (endOfRace != null && raceFinishingTime == null) {
|
||||
// We have NO blue flag up event and we have an end of race time
|
||||
max = new Date(endOfRace.getTime() + MAX_TIME_AFTER_RACE_END);
|
||||
} else {
|
||||
// We have no end time and are not expecting any end events
|
||||
if (endOfTracking != null && raceFinishingTime == null) {
|
||||
max = endOfTracking;
|
||||
} else {
|
||||
// No end in sight; Keep on playing
|
||||
max = new Date(liveTimePoint.getTime() + TIME_AFTER_LIVE);
|
||||
}
|
||||
}
|
||||
|
||||
return new Util.Pair<Date, Date>(min, max);
|
||||
}
|
||||
}
|
||||
+29
-35
@@ -2,8 +2,10 @@ package com.sap.sailing.domain.common.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.common.RaceTimesCalculationUtil;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.TimingConstants;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.security.shared.dto.NamedDTO;
|
||||
|
||||
/**
|
||||
@@ -19,6 +21,7 @@ public class BasicRaceDTO extends NamedDTO {
|
||||
|
||||
public Date startOfRace;
|
||||
public Date endOfRace;
|
||||
public Date raceFinishingTime;
|
||||
public Date raceFinishedTime;
|
||||
public TrackedRaceDTO trackedRace;
|
||||
|
||||
@@ -37,44 +40,35 @@ public class BasicRaceDTO extends NamedDTO {
|
||||
* point of the "live" interval as defined above.
|
||||
*/
|
||||
public boolean isLive(long serverTimePointAsMillis) {
|
||||
final Date startOfLivePeriod;
|
||||
final Date endOfLivePeriod;
|
||||
if (trackedRace == null || !trackedRace.hasGPSData || !trackedRace.hasWindData) {
|
||||
startOfLivePeriod = null;
|
||||
endOfLivePeriod = null;
|
||||
} else {
|
||||
if (startOfRace == null) {
|
||||
startOfLivePeriod = trackedRace.startOfTracking;
|
||||
} else {
|
||||
startOfLivePeriod = new Date(startOfRace.getTime() - TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS);
|
||||
}
|
||||
if (endOfRace == null) {
|
||||
if (trackedRace.timePointOfNewestEvent != null) {
|
||||
endOfLivePeriod = new Date(trackedRace.timePointOfNewestEvent.getTime()
|
||||
+ TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS);
|
||||
} else {
|
||||
endOfLivePeriod = null;
|
||||
}
|
||||
} else {
|
||||
endOfLivePeriod = new Date(endOfRace.getTime() + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS);
|
||||
Date timePoint = null;
|
||||
if (serverTimePointAsMillis != 0) {
|
||||
timePoint = new Date(serverTimePointAsMillis);
|
||||
} else if (trackedRace != null && trackedRace.startOfTracking != null) {
|
||||
timePoint = trackedRace.startOfTracking;
|
||||
} else if (startOfRace != null) {
|
||||
timePoint = new Date(startOfRace.getTime() - TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS + 1);
|
||||
}
|
||||
|
||||
if (trackedRace != null && trackedRace.hasGPSData && trackedRace.hasWindData) {
|
||||
Util.Pair<Date, Date> minMax = RaceTimesCalculationUtil.calculateRaceMinMax(timePoint,
|
||||
trackedRace.startOfTracking, startOfRace, raceFinishingTime, raceFinishedTime, endOfRace,
|
||||
trackedRace.endOfTracking);
|
||||
Date min = minMax.getA() != null
|
||||
? new Date(minMax.getA().getTime() - TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS)
|
||||
: null;
|
||||
Date max = minMax.getB() != null
|
||||
? new Date(minMax.getB().getTime() + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS
|
||||
+ trackedRace.delayToLiveInMs)
|
||||
: null;
|
||||
|
||||
// We are live if at is in between min and max
|
||||
if (timePoint != null && min != null && max != null) {
|
||||
return !min.after(timePoint) && !timePoint.after(max);
|
||||
}
|
||||
}
|
||||
|
||||
// if an empty timepoint is given then take the start of the race
|
||||
if (serverTimePointAsMillis == 0) {
|
||||
serverTimePointAsMillis = startOfLivePeriod.getTime()+1;
|
||||
}
|
||||
|
||||
// whenLastTrackedRaceWasLive is null if there is no tracked race for fleet, or the tracked race hasn't started yet at the server time
|
||||
// when this DTO was assembled, or there were no GPS or wind data
|
||||
final boolean result =
|
||||
startOfLivePeriod != null &&
|
||||
endOfLivePeriod != null &&
|
||||
startOfLivePeriod.getTime() <= serverTimePointAsMillis &&
|
||||
serverTimePointAsMillis <= endOfLivePeriod.getTime();
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
||||
+1
@@ -208,6 +208,7 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl<RaceLogAndTracked
|
||||
assert trackedRace != null;
|
||||
raceDTO.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate();
|
||||
raceDTO.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate();
|
||||
raceDTO.raceFinishingTime = trackedRace.getFinishingTime() == null ? null : trackedRace.getFinishingTime().asDate();
|
||||
raceDTO.raceFinishedTime = trackedRace.getFinishedTime() == null ? null : trackedRace.getFinishedTime().asDate();
|
||||
raceDTO.status = new RaceStatusDTO();
|
||||
raceDTO.status.status = trackedRace.getStatus() == null ? null : trackedRace.getStatus().getStatus();
|
||||
|
||||
+31
-33
@@ -75,6 +75,7 @@ import com.sap.sailing.domain.common.ManeuverType;
|
||||
import com.sap.sailing.domain.common.NauticalSide;
|
||||
import com.sap.sailing.domain.common.NoWindException;
|
||||
import com.sap.sailing.domain.common.Position;
|
||||
import com.sap.sailing.domain.common.RaceTimesCalculationUtil;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.SpeedWithBearing;
|
||||
@@ -1182,45 +1183,42 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
public boolean hasStarted(TimePoint at) {
|
||||
return getStartOfRace() != null && getStartOfRace().compareTo(at) <= 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isLive(TimePoint at) {
|
||||
final TimePoint startOfLivePeriod;
|
||||
final TimePoint endOfLivePeriod;
|
||||
if (!hasGPSData() || !hasWindData()) {
|
||||
startOfLivePeriod = null;
|
||||
endOfLivePeriod = null;
|
||||
Date timePoint = null;
|
||||
if (at != null) {
|
||||
timePoint = at.asDate();
|
||||
} else {
|
||||
if (getStartOfRace() == null) {
|
||||
startOfLivePeriod = getStartOfTracking();
|
||||
} else {
|
||||
startOfLivePeriod = getStartOfRace().minus(TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS);
|
||||
}
|
||||
if (getEndOfRace() == null) {
|
||||
if (getTimePointOfNewestEvent() != null) {
|
||||
endOfLivePeriod = getTimePointOfNewestEvent().plus(
|
||||
TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS).plus(getDelayToLiveInMillis());
|
||||
} else {
|
||||
endOfLivePeriod = null;
|
||||
}
|
||||
} else {
|
||||
endOfLivePeriod = getEndOfRace().plus(TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS);
|
||||
if (startOfTracking != null) {
|
||||
timePoint = startOfTracking.asDate();
|
||||
} else if (startTime != null) {
|
||||
timePoint = startTime.minus(TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS).plus(1).asDate();
|
||||
}
|
||||
}
|
||||
|
||||
// if an empty timepoint is given then take the start of the race
|
||||
if (at == null) {
|
||||
at = startOfLivePeriod.plus(1);
|
||||
|
||||
if (hasGPSData() && hasWindData()) {
|
||||
Util.Pair<Date, Date> minMax = RaceTimesCalculationUtil.calculateRaceMinMax(timePoint,
|
||||
startOfTracking != null ? startOfTracking.asDate() : null,
|
||||
startTime != null ? startTime.asDate() : null,
|
||||
finishingTime != null ? finishingTime.asDate() : null,
|
||||
finishedTime != null ? finishedTime.asDate() : null,
|
||||
endTime != null ? endTime.asDate() : null,
|
||||
endOfTracking != null ? endOfTracking.asDate() : null);
|
||||
Date min = minMax.getA() != null
|
||||
? new Date(minMax.getA().getTime() - TimingConstants.PRE_START_PHASE_DURATION_IN_MILLIS)
|
||||
: null;
|
||||
Date max = minMax.getB() != null
|
||||
? new Date(minMax.getB().getTime() + TimingConstants.IS_LIVE_GRACE_PERIOD_IN_MILLIS
|
||||
+ getDelayToLiveInMillis())
|
||||
: null;
|
||||
|
||||
// We are live if at is in between min and max
|
||||
if (min != null && max != null) {
|
||||
return !min.after(at.asDate()) && !at.asDate().after(max);
|
||||
}
|
||||
}
|
||||
|
||||
// whenLastTrackedRaceWasLive is null if there is no tracked race for fleet, or the tracked race hasn't started yet at the server time
|
||||
// when this DTO was assembled, or there were no GPS or wind data
|
||||
final boolean result =
|
||||
startOfLivePeriod != null &&
|
||||
endOfLivePeriod != null &&
|
||||
!startOfLivePeriod.after(at) &&
|
||||
!at.after(endOfLivePeriod);
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class LiveRacesList extends Composite {
|
||||
private final SortableRaceListColumn<LiveRaceDTO, ?> raceViewStateColumn = RaceListColumnFactory.getRaceViewStateColumn();
|
||||
|
||||
public RaceListLiveRaces(EventView.Presenter presenter, boolean showRegattaDetails) {
|
||||
super(presenter, new RaceListColumnSet(1, 1), false);
|
||||
super(presenter, new RaceListColumnSet(1, 1), false); // See: https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3819
|
||||
this.regattaNameColumn.setShowDetails(showRegattaDetails);
|
||||
}
|
||||
|
||||
|
||||
+32
-37
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.RaceTimesCalculationUtil;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.security.SecuredDomainType.TrackedRaceActions;
|
||||
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
|
||||
@@ -14,6 +15,7 @@ import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsAndBoatsDTO;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
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;
|
||||
@@ -233,43 +235,34 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
*/
|
||||
@Override
|
||||
protected boolean isLiveModeToBeMadePossible() {
|
||||
long liveTimePointInMillis = timer.getLiveTimePointInMillis();
|
||||
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null ? raceTimesInfoProvider.getRaceTimesInfo(selectedRace) : null;
|
||||
final boolean isLiveModeToBeMadePossible;
|
||||
if (lastRaceTimesInfo != null &&
|
||||
// check that we're after startOfTracking or startOfRace minus some leeway:
|
||||
((lastRaceTimesInfo.startOfTracking != null && liveTimePointInMillis > lastRaceTimesInfo.startOfTracking.getTime()) ||
|
||||
(lastRaceTimesInfo.startOfRace != null && liveTimePointInMillis > lastRaceTimesInfo.startOfRace.getTime() - RaceTimesCalculationUtil.MIN_TIME_BEFORE_RACE_START))) {
|
||||
// now check that we cannot know about an end time or are reasonably before it;
|
||||
// we don't know about the end time if startOfTracking is valid but endOfTracking is not;
|
||||
// neither do we know about the end time if both, startOfTracking and endOfTracking are null
|
||||
// and we have neither a valid newestTrackingEvent nor an endOfRace value; if we do, we would
|
||||
// have to be before the later one plus some leeway.
|
||||
Date endTimeOfLivePeriod;
|
||||
if (lastRaceTimesInfo.startOfTracking == null && lastRaceTimesInfo.endOfTracking == null) {
|
||||
Date latestOfNewestTrackingEventAndEndOfRace = lastRaceTimesInfo.newestTrackingEvent;
|
||||
if (latestOfNewestTrackingEventAndEndOfRace == null || (lastRaceTimesInfo.endOfRace != null && lastRaceTimesInfo.endOfRace.after(latestOfNewestTrackingEventAndEndOfRace))) {
|
||||
latestOfNewestTrackingEventAndEndOfRace = lastRaceTimesInfo.endOfRace;
|
||||
}
|
||||
endTimeOfLivePeriod = latestOfNewestTrackingEventAndEndOfRace == null ? null :
|
||||
new Date(latestOfNewestTrackingEventAndEndOfRace.getTime() + RaceTimesCalculationUtil.TIME_AFTER_LIVE);
|
||||
} else {
|
||||
endTimeOfLivePeriod = lastRaceTimesInfo.endOfTracking;
|
||||
if (lastRaceTimesInfo.endOfRace != null) {
|
||||
// this is a failsafe, if the tracking was never finished, the race was always assumed to be live.
|
||||
Date latestAllowedTime = new Date(
|
||||
lastRaceTimesInfo.endOfRace.getTime() + RaceTimesCalculationUtil.MAX_TIME_AFTER_RACE_END);
|
||||
if (endTimeOfLivePeriod == null || endTimeOfLivePeriod.after(latestAllowedTime)) {
|
||||
endTimeOfLivePeriod = latestAllowedTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
isLiveModeToBeMadePossible = endTimeOfLivePeriod == null /* meaning we don't know an end time */ ||
|
||||
endTimeOfLivePeriod.getTime() >= liveTimePointInMillis;
|
||||
} else {
|
||||
isLiveModeToBeMadePossible = false;
|
||||
RaceTimesInfoDTO lastRaceTimesInfo = raceTimesInfoProvider != null
|
||||
? raceTimesInfoProvider.getRaceTimesInfo(selectedRace)
|
||||
: null;
|
||||
if (lastRaceTimesInfo == null) return false;
|
||||
|
||||
Date timePoint = timer.getLiveTimePointAsDate();
|
||||
Pair<Date, Date> minMax = RaceTimesCalculationUtil.calculateRaceMinMax(timer.getLiveTimePointAsDate(),
|
||||
lastRaceTimesInfo.startOfTracking, lastRaceTimesInfo.startOfRace, lastRaceTimesInfo.raceFinishingTime,
|
||||
lastRaceTimesInfo.raceFinishedTime, lastRaceTimesInfo.endOfRace, lastRaceTimesInfo.endOfTracking);
|
||||
Date min = minMax.getA();
|
||||
Date max = minMax.getB();
|
||||
|
||||
// Bug 3482: try to determine a value for max if max is null
|
||||
if (max == null && lastRaceTimesInfo.newestTrackingEvent != null) {
|
||||
max = new Date(lastRaceTimesInfo.newestTrackingEvent.getTime() + RaceTimesCalculationUtil.TIME_AFTER_LIVE);
|
||||
}
|
||||
return isLiveModeToBeMadePossible;
|
||||
|
||||
// Assume we are live (no end known as of now)
|
||||
boolean beforeEnd = true;
|
||||
if (max != null) {
|
||||
beforeEnd = !timePoint.after(max);
|
||||
}
|
||||
|
||||
if (min != null) {
|
||||
// min < timePoint < max; max might be unknown as of now
|
||||
return !timePoint.before(min) && beforeEnd;
|
||||
}
|
||||
return beforeEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -291,7 +284,9 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
* was <code>null</code> before, or extended to a later point in time.
|
||||
*/
|
||||
private void updateMinMax(RaceTimesInfoDTO newRaceTimesInfo) {
|
||||
Util.Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.calculateRaceMinMax(timer, newRaceTimesInfo);
|
||||
Util.Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.calculateRaceMinMax(timer.getLiveTimePointAsDate(),
|
||||
newRaceTimesInfo.startOfTracking, newRaceTimesInfo.startOfRace, newRaceTimesInfo.raceFinishingTime,
|
||||
newRaceTimesInfo.raceFinishedTime, newRaceTimesInfo.endOfRace, newRaceTimesInfo.endOfTracking);
|
||||
|
||||
Date min = raceMinMax.getA();
|
||||
Date max = raceMinMax.getB();
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.gwt.client.player.Timer;
|
||||
|
||||
public class RaceTimesCalculationUtil {
|
||||
public static final long MIN_TIME_BEFORE_RACE_START = 3 * 60 * 1000; // 3 minutes
|
||||
public static final long MIN_TIME_AFTER_RACE_START = 5 * 60 * 1000; // 5 minutes
|
||||
public static final long TIME_AFTER_LIVE = 5 * 60 * 1000; // 5 minutes
|
||||
public static final long MAX_TIME_AFTER_RACE_END = 1 * 60 * 1000; // 1 minutes
|
||||
|
||||
public static Util.Pair<Date, Date> calculateRaceMinMax(Timer timer, RaceTimesInfoDTO raceTimesInfo) {
|
||||
Date min = null;
|
||||
Date max = null;
|
||||
|
||||
Date liveTimePoint = timer.getLiveTimePointAsDate();
|
||||
|
||||
// Range start / min
|
||||
if (raceTimesInfo.startOfRace != null) {
|
||||
// We have a start time
|
||||
min = new Date(raceTimesInfo.startOfRace.getTime() - MIN_TIME_BEFORE_RACE_START);
|
||||
} else if (raceTimesInfo.startOfTracking != null) {
|
||||
// We at least have a start of tracking time
|
||||
min = raceTimesInfo.startOfTracking;
|
||||
}
|
||||
if (min == null || liveTimePoint.before(min)){
|
||||
// There is no start time or the start time is in the future
|
||||
min = new Date(liveTimePoint.getTime());
|
||||
}
|
||||
|
||||
// Range end / max
|
||||
if (raceTimesInfo.raceFinishedTime != null) {
|
||||
// We have a blue flag down event
|
||||
max = new Date(raceTimesInfo.raceFinishedTime.getTime() + MAX_TIME_AFTER_RACE_END);
|
||||
} else if (raceTimesInfo.endOfRace != null && raceTimesInfo.raceFinishingTime == null) {
|
||||
// We have NO blue flag up event and we have an end of race time
|
||||
max = new Date(raceTimesInfo.endOfRace.getTime() + MAX_TIME_AFTER_RACE_END);
|
||||
} else {
|
||||
// We have no end time so just keep playing until they are created
|
||||
max = new Date(liveTimePoint.getTime() + TIME_AFTER_LIVE);
|
||||
}
|
||||
// If there are no end events or the additional offset exceeds end of tracking
|
||||
if (raceTimesInfo.endOfTracking != null) {
|
||||
if (max == null || max.after(raceTimesInfo.endOfTracking)) {
|
||||
max = raceTimesInfo.endOfTracking;
|
||||
}
|
||||
}
|
||||
|
||||
return new Util.Pair<Date, Date>(min, max);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user