mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-28 14:57:12 +00:00
compileable but untested refactored version of RaceMap.timeChanged, working towards a solution for bug3378
Change-Id: Idc67121b9c1931e66453def87da8243250b9c9d2
This commit is contained in:
1 parent
68a1c76529
commit
61d1c2da2e
9 files changed
+251
-132
No files matched your search
+47
@@ -0,0 +1,47 @@
|
||||
package com.sap.sailing.gwt.ui.actions;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sse.gwt.client.async.AsyncAction;
|
||||
|
||||
public abstract class AbstractGetMapRelatedDataAction<T> implements AsyncAction<T> {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final RegattaAndRaceIdentifier raceIdentifier;
|
||||
private final Map<CompetitorDTO, Date> from;
|
||||
private final Map<CompetitorDTO, Date> to;
|
||||
private final boolean extrapolate;
|
||||
|
||||
public AbstractGetMapRelatedDataAction(SailingServiceAsync sailingService,
|
||||
RegattaAndRaceIdentifier raceIdentifier, Map<CompetitorDTO, Date> from,
|
||||
Map<CompetitorDTO, Date> to, boolean extrapolate) {
|
||||
this.sailingService = sailingService;
|
||||
this.raceIdentifier = raceIdentifier;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.extrapolate = extrapolate;
|
||||
}
|
||||
|
||||
protected SailingServiceAsync getSailingService() {
|
||||
return sailingService;
|
||||
}
|
||||
|
||||
protected RegattaAndRaceIdentifier getRaceIdentifier() {
|
||||
return raceIdentifier;
|
||||
}
|
||||
|
||||
protected Map<CompetitorDTO, Date> getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
protected Map<CompetitorDTO, Date> getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
protected boolean isExtrapolate() {
|
||||
return extrapolate;
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.sap.sailing.gwt.ui.actions;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO;
|
||||
|
||||
public class GetBoatPositionsAction extends AbstractGetMapRelatedDataAction<CompactBoatPositionsDTO> {
|
||||
public GetBoatPositionsAction(SailingServiceAsync sailingService,
|
||||
RegattaAndRaceIdentifier raceIdentifier, Map<CompetitorDTO, Date> from,
|
||||
Map<CompetitorDTO, Date> to, boolean extrapolate) {
|
||||
super(sailingService, raceIdentifier, from, to, extrapolate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final AsyncCallback<CompactBoatPositionsDTO> callback) {
|
||||
Map<String, Date> fromByCompetitorIdAsString = new HashMap<String, Date>();
|
||||
for (Map.Entry<CompetitorDTO, Date> fromEntry : getFrom().entrySet()) {
|
||||
fromByCompetitorIdAsString.put(fromEntry.getKey().getIdAsString(), fromEntry.getValue());
|
||||
}
|
||||
Map<String, Date> toByCompetitorIdAsString = new HashMap<String, Date>();
|
||||
for (Map.Entry<CompetitorDTO, Date> toEntry : getTo().entrySet()) {
|
||||
toByCompetitorIdAsString.put(toEntry.getKey().getIdAsString(), toEntry.getValue());
|
||||
}
|
||||
getSailingService().getBoatPositions(getRaceIdentifier(), fromByCompetitorIdAsString, toByCompetitorIdAsString,
|
||||
isExtrapolate(), new AsyncCallback<CompactBoatPositionsDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
callback.onFailure(caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompactBoatPositionsDTO result) {
|
||||
callback.onSuccess(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+10
-20
@@ -11,43 +11,33 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
|
||||
import com.sap.sse.gwt.client.async.AsyncAction;
|
||||
|
||||
public class GetRaceMapDataAction implements AsyncAction<RaceMapDataDTO> {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final Iterable<CompetitorDTO> allCompetitors;
|
||||
private final RegattaAndRaceIdentifier raceIdentifier;
|
||||
private final Map<CompetitorDTO, Date> from;
|
||||
private final Map<CompetitorDTO, Date> to;
|
||||
private final boolean extrapolate;
|
||||
public class GetRaceMapDataAction extends AbstractGetMapRelatedDataAction<RaceMapDataDTO> {
|
||||
private final Map<String, CompetitorDTO> competitorsByIdAsString;
|
||||
private final Date date;
|
||||
private final LegIdentifier simulationLegIdentifier;
|
||||
|
||||
public GetRaceMapDataAction(SailingServiceAsync sailingService, Iterable<CompetitorDTO> allCompetitors,
|
||||
public GetRaceMapDataAction(SailingServiceAsync sailingService, Map<String, CompetitorDTO> competitorsByIdAsString,
|
||||
RegattaAndRaceIdentifier raceIdentifier, Date date, Map<CompetitorDTO, Date> from,
|
||||
Map<CompetitorDTO, Date> to, boolean extrapolate, LegIdentifier simulationLegIdentifier) {
|
||||
this.allCompetitors = allCompetitors;
|
||||
this.sailingService = sailingService;
|
||||
this.raceIdentifier = raceIdentifier;
|
||||
super(sailingService, raceIdentifier, from, to, extrapolate);
|
||||
this.competitorsByIdAsString = competitorsByIdAsString;
|
||||
this.date = date;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.extrapolate = extrapolate;
|
||||
this.simulationLegIdentifier = simulationLegIdentifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final AsyncCallback<RaceMapDataDTO> callback) {
|
||||
Map<String, Date> fromByCompetitorIdAsString = new HashMap<String, Date>();
|
||||
for (Map.Entry<CompetitorDTO, Date> fromEntry : from.entrySet()) {
|
||||
for (Map.Entry<CompetitorDTO, Date> fromEntry : getFrom().entrySet()) {
|
||||
fromByCompetitorIdAsString.put(fromEntry.getKey().getIdAsString(), fromEntry.getValue());
|
||||
}
|
||||
Map<String, Date> toByCompetitorIdAsString = new HashMap<String, Date>();
|
||||
for (Map.Entry<CompetitorDTO, Date> toEntry : to.entrySet()) {
|
||||
for (Map.Entry<CompetitorDTO, Date> toEntry : getTo().entrySet()) {
|
||||
toByCompetitorIdAsString.put(toEntry.getKey().getIdAsString(), toEntry.getValue());
|
||||
}
|
||||
sailingService.getRaceMapData(raceIdentifier, date, fromByCompetitorIdAsString, toByCompetitorIdAsString,
|
||||
extrapolate, simulationLegIdentifier, new AsyncCallback<CompactRaceMapDataDTO>() {
|
||||
getSailingService().getRaceMapData(getRaceIdentifier(), date, fromByCompetitorIdAsString, toByCompetitorIdAsString,
|
||||
isExtrapolate(), simulationLegIdentifier, new AsyncCallback<CompactRaceMapDataDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
callback.onFailure(caught);
|
||||
@@ -55,7 +45,7 @@ public class GetRaceMapDataAction implements AsyncAction<RaceMapDataDTO> {
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompactRaceMapDataDTO result) {
|
||||
callback.onSuccess(result.getRaceMapDataDTO(allCompetitors));
|
||||
callback.onSuccess(result.getRaceMapDataDTO(competitorsByIdAsString));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+6
@@ -45,6 +45,7 @@ import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
|
||||
@@ -158,6 +159,10 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
CompactRaceMapDataDTO getRaceMapData(RegattaAndRaceIdentifier raceIdentifier, Date date, Map<String, Date> fromPerCompetitorIdAsString,
|
||||
Map<String, Date> toPerCompetitorIdAsString, boolean extrapolate, LegIdentifier simulationLegIdentifier) throws NoWindException;
|
||||
|
||||
CompactBoatPositionsDTO getBoatPositions(RegattaAndRaceIdentifier raceIdentifier,
|
||||
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
|
||||
boolean extrapolate) throws NoWindException;
|
||||
|
||||
RaceTimesInfoDTO getRaceTimesInfo(RegattaAndRaceIdentifier raceIdentifier);
|
||||
|
||||
List<RaceTimesInfoDTO> getRaceTimesInfos(Collection<RegattaAndRaceIdentifier> raceIdentifiers);
|
||||
@@ -612,4 +617,5 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
|
||||
*/
|
||||
Collection<CompetitorDTO> getCompetitorRegistrationsOnRaceLog(String leaderboardName, String raceColumnName,
|
||||
String fleetName);
|
||||
|
||||
}
|
||||
+6
@@ -37,6 +37,7 @@ import com.sap.sailing.domain.common.racelog.RacingProcedureType;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
|
||||
@@ -368,6 +369,10 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
|
||||
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
|
||||
boolean extrapolate, LegIdentifier simulationLegIdentifier, AsyncCallback<CompactRaceMapDataDTO> callback);
|
||||
|
||||
void getBoatPositions(RegattaAndRaceIdentifier raceIdentifier, Map<String, Date> fromPerCompetitorIdAsString,
|
||||
Map<String, Date> toPerCompetitorIdAsString, boolean extrapolate,
|
||||
AsyncCallback<CompactBoatPositionsDTO> callback);
|
||||
|
||||
void getReplicaInfo(AsyncCallback<ReplicationStateDTO> callback);
|
||||
|
||||
void startReplicatingFromMaster(String messagingHost, String masterName, String exchangeName, int servletPort,
|
||||
@@ -753,4 +758,5 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
|
||||
|
||||
void copyCourseToOtherRaceLogs(Triple<String, String, String> fromTriple,
|
||||
Set<Triple<String, String, String>> toTriples, AsyncCallback<Void> callback);
|
||||
|
||||
}
|
||||
+93
-92
@@ -83,6 +83,7 @@ import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.scalablevalue.impl.ScalableBearing;
|
||||
import com.sap.sailing.domain.common.scalablevalue.impl.ScalablePosition;
|
||||
import com.sap.sailing.gwt.ui.actions.GetBoatPositionsAction;
|
||||
import com.sap.sailing.gwt.ui.actions.GetPolarAction;
|
||||
import com.sap.sailing.gwt.ui.actions.GetRaceMapDataAction;
|
||||
import com.sap.sailing.gwt.ui.actions.GetWindInfoAction;
|
||||
@@ -100,6 +101,7 @@ import com.sap.sailing.gwt.ui.client.shared.filter.QuickRankProvider;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapHelpLinesSettings.HelpLineTypes;
|
||||
import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapZoomSettings.ZoomTypes;
|
||||
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
|
||||
@@ -776,29 +778,8 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
final long transitionTimeInMillis = calculateTimeForPositionTransitionInMillis(newTime, oldTime);
|
||||
final com.sap.sse.common.Util.Triple<Map<CompetitorDTO, Date>, Map<CompetitorDTO, Date>, Map<CompetitorDTO, Boolean>> fromAndToAndOverlap =
|
||||
fixesAndTails.computeFromAndTo(newTime, competitorsToShow, settings.getEffectiveTailLengthInMilliseconds());
|
||||
int requestID = ++boatPositionRequestIDCounter;
|
||||
// For those competitors for which the tails don't overlap (and therefore will be replaced by the new tail coming from the server)
|
||||
// we expect some potential delay in computing the full tail. Therefore, in those cases we fire two requests: one fetching only the
|
||||
// boat positions at newTime with zero tail length; and another one fetching everything else.
|
||||
// TODO bug3378: two calls that both request simulation and mark data wastes bandwidth and CPU; one of them should only use getBoatPositions to request missing pieces of tails; showBoatsOnMap must not remove canvases / tails if one of the two calls delivers only partial results
|
||||
final GetRaceMapDataAction getRaceMapDataForAllOverlappingAndTipsOfNonOverlapping = getRaceMapDataForAllOverlappingAndTipsOfNonOverlapping(fromAndToAndOverlap, race, newTime);
|
||||
final boolean updateMarksAndLinesExceptAdvantageLineInCallback;
|
||||
if (getRaceMapDataForAllOverlappingAndTipsOfNonOverlapping != null) {
|
||||
asyncActionsExecutor.execute(getRaceMapDataForAllOverlappingAndTipsOfNonOverlapping, GET_RACE_MAP_DATA_CATEGORY,
|
||||
getRaceMapDataCallback(newTime, transitionTimeInMillis, fromAndToAndOverlap.getC(), competitorsToShow, requestID,
|
||||
/* updateMarksAndLinesExceptAdvantageLineInCallback */ true));
|
||||
updateMarksAndLinesExceptAdvantageLineInCallback = false; // don't do this again in the second call that mainly fetches
|
||||
requestID = ++boatPositionRequestIDCounter;
|
||||
} else {
|
||||
updateMarksAndLinesExceptAdvantageLineInCallback = true;
|
||||
}
|
||||
// next, do the full thing; being the later call, if request throttling kicks in, the later call
|
||||
// supersedes the earlier call which may get dropped then
|
||||
GetRaceMapDataAction getRaceMapDataAction = new GetRaceMapDataAction(sailingService, competitorSelection.getAllCompetitors(), race,
|
||||
useNullAsTimePoint() ? null : newTime, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(), /* extrapolate */ true, (settings.isShowSimulationOverlay() ? simulationOverlay.getLegIdentifier() : null));
|
||||
asyncActionsExecutor.execute(getRaceMapDataAction, GET_RACE_MAP_DATA_CATEGORY,
|
||||
getRaceMapDataCallback(newTime, transitionTimeInMillis, fromAndToAndOverlap.getC(), competitorsToShow, requestID,
|
||||
updateMarksAndLinesExceptAdvantageLineInCallback));
|
||||
// Request map data update, possibly in two calls; see method details
|
||||
callGetRaceMapDataForAllOverlappingAndTipsOfNonOverlappingAndGetBoatPositionsForAllOthers(fromAndToAndOverlap, race, newTime, transitionTimeInMillis, competitorsToShow);
|
||||
|
||||
// draw the wind into the map, get the combined wind
|
||||
List<String> windSourceTypeNames = new ArrayList<String>();
|
||||
@@ -851,63 +832,79 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
}
|
||||
|
||||
/**
|
||||
* We assume that overlapping segments usually don't require a lot of loading time as the most typical case will be to update a longer
|
||||
* tail with a few new fixes that were received since the last time tick. Non-overlapping position requests typically occur for the
|
||||
* first request when no fix at all is known for the competitor yet, or when the user has radically moved the time slider to some
|
||||
* other time such that given the current tail length setting the new tail segment does not overlap with the old one, requiring a full
|
||||
* load of the entire tail data for that competitor.<p>
|
||||
* Requests updates for map data and, when received, updates the map structures accordingly.
|
||||
* <p>
|
||||
*
|
||||
* For the non-overlapping requests, this method creates a separate request which only loads boat positions, quick ranks, sidelines and
|
||||
* mark positions for the zero-length interval at <code>newTime</code>, assuming that this will work fairly fast and in particular in
|
||||
* O(1) time regardless of tail length, compared to fetching the entire tail for all competitors.
|
||||
* The update can happen in one or two round trips. We assume that overlapping segments usually don't require a lot
|
||||
* of loading time as the most typical case will be to update a longer tail with a few new fixes that were received
|
||||
* since the last time tick. These supposedly fast requests are handled by a {@link GetRaceMapDataAction} which also
|
||||
* requests updates for mark positions, sidelines and quick ranks. The same request also loads boat positions for
|
||||
* the zero-length interval at <code>newTime</code> for the non-overlapping tails assuming that this will work
|
||||
* fairly fast and in particular in O(1) time regardless of tail length, compared to fetching the entire tail for
|
||||
* all competitors. This will at least provide quick feedback about those competitors' positions even if loading
|
||||
* their entire tail may take a little longer. The {@link GetRaceMapDataAction} therefore is intended to be a rather
|
||||
* quick call.
|
||||
* <p>
|
||||
*
|
||||
* TODO bug 3378: This shall produce two calls: one complete GetRaceMapDataAction and another fetching of missing "long tails" which only needs to be carried out if the first call does not deliver everything requested by fromAndToAndOverlap
|
||||
* The second call of GetRaceMapDataAction is this:
|
||||
*
|
||||
* GetRaceMapDataAction getRaceMapDataAction = new GetRaceMapDataAction(sailingService, competitorSelection.getAllCompetitors(), race,
|
||||
* useNullAsTimePoint() ? null : newTime, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(),
|
||||
* true, // extrapolate
|
||||
* (settings.isShowSimulationOverlay() ? simulationOverlay.getLegIdentifier() : null));
|
||||
* asyncActionsExecutor.execute(getRaceMapDataAction, GET_RACE_MAP_DATA_CATEGORY,
|
||||
* getRaceMapDataCallback(newTime, transitionTimeInMillis, fromAndToAndOverlap.getC(), competitorsToShow, requestID,
|
||||
* updateMarksAndLinesExceptAdvantageLineInCallback));
|
||||
*
|
||||
* Non-overlapping position requests typically occur for the first request when no fix at all is known for the
|
||||
* competitor yet, or when the user has radically moved the time slider to some other time such that given the
|
||||
* current tail length setting the new tail segment does not overlap with the old one, requiring a full load of the
|
||||
* entire tail data for that competitor. For these non-overlapping requests, this method creates a
|
||||
* {@link GetBoatPositionsAction} request loading the entire tail required, but not quick ranks, sidelines and mark
|
||||
* positions. Updating the results of this call is done in {@link #updateBoatPositions(Date, long, Map, Iterable, Map)}.
|
||||
* <p>
|
||||
*/
|
||||
private GetRaceMapDataAction getRaceMapDataForAllOverlappingAndTipsOfNonOverlapping(
|
||||
Triple<Map<CompetitorDTO, Date>, Map<CompetitorDTO, Date>, Map<CompetitorDTO, Boolean>> fromAndToAndOverlap,
|
||||
RegattaAndRaceIdentifier race, Date newTime) {
|
||||
Map<CompetitorDTO, Date> fromTimes = new HashMap<>();
|
||||
Map<CompetitorDTO, Date> toTimes = new HashMap<>();
|
||||
private void callGetRaceMapDataForAllOverlappingAndTipsOfNonOverlappingAndGetBoatPositionsForAllOthers(
|
||||
final Triple<Map<CompetitorDTO, Date>, Map<CompetitorDTO, Date>, Map<CompetitorDTO, Boolean>> fromAndToAndOverlap,
|
||||
RegattaAndRaceIdentifier race, final Date newTime, final long transitionTimeInMillis, final Iterable<CompetitorDTO> competitorsToShow) {
|
||||
final Map<CompetitorDTO, Date> fromTimesForQuickCall = new HashMap<>();
|
||||
final Map<CompetitorDTO, Date> toTimesForQuickCall = new HashMap<>();
|
||||
final Map<CompetitorDTO, Date> fromTimesForNonOverlappingTailsCall = new HashMap<>();
|
||||
final Map<CompetitorDTO, Date> toTimesForNonOverlappingTailsCall = new HashMap<>();
|
||||
for (Map.Entry<CompetitorDTO, Boolean> e : fromAndToAndOverlap.getC().entrySet()) {
|
||||
if (!e.getValue()) {
|
||||
// no overlap; add competitor to request
|
||||
fromTimes.put(e.getKey(), newTime);
|
||||
toTimes.put(e.getKey(), newTime);
|
||||
if (e.getValue()) {
|
||||
// overlap: expect a quick response; add original request interval for the competitor
|
||||
fromTimesForQuickCall.put(e.getKey(), fromAndToAndOverlap.getA().get(e.getKey()));
|
||||
toTimesForQuickCall.put(e.getKey(), fromAndToAndOverlap.getB().get(e.getKey()));
|
||||
} else {
|
||||
// no overlap; add competitor to request with a zero-length interval asking only position at newTime, not the entire tail
|
||||
fromTimesForQuickCall.put(e.getKey(), newTime);
|
||||
toTimesForQuickCall.put(e.getKey(), newTime);
|
||||
fromTimesForNonOverlappingTailsCall.put(e.getKey(), fromAndToAndOverlap.getA().get(e.getKey()));
|
||||
toTimesForNonOverlappingTailsCall.put(e.getKey(), fromAndToAndOverlap.getB().get(e.getKey()));
|
||||
}
|
||||
}
|
||||
final GetRaceMapDataAction result;
|
||||
if (!fromTimes.isEmpty()) {
|
||||
result = new GetRaceMapDataAction(sailingService, competitorSelection.getAllCompetitors(),
|
||||
race, useNullAsTimePoint() ? null : newTime, fromTimes, toTimes, /* extrapolate */true, (settings.isShowSimulationOverlay() ? simulationOverlay.getLegIdentifier() : null));
|
||||
} else {
|
||||
result = null;
|
||||
final Map<String, CompetitorDTO> competitorsByIdAsString = new HashMap<String, CompetitorDTO>();
|
||||
for (CompetitorDTO competitor : competitorSelection.getAllCompetitors()) {
|
||||
competitorsByIdAsString.put(competitor.getIdAsString(), competitor);
|
||||
}
|
||||
return result;
|
||||
|
||||
asyncActionsExecutor.execute(new GetRaceMapDataAction(sailingService, competitorsByIdAsString,
|
||||
race, useNullAsTimePoint() ? null : newTime, fromTimesForQuickCall, toTimesForQuickCall, /* extrapolate */true,
|
||||
(settings.isShowSimulationOverlay() ? simulationOverlay.getLegIdentifier() : null)), GET_RACE_MAP_DATA_CATEGORY,
|
||||
getRaceMapDataCallback(newTime, transitionTimeInMillis, fromAndToAndOverlap.getC(), competitorsToShow, ++boatPositionRequestIDCounter));
|
||||
// next, if necessary, do the full thing; the two calls have different action classes, so throttling should not drop one for the other
|
||||
asyncActionsExecutor.execute(new GetBoatPositionsAction(sailingService, race, fromAndToAndOverlap.getA(), fromAndToAndOverlap.getB(),
|
||||
/* extrapolate */ true), GET_RACE_MAP_DATA_CATEGORY,
|
||||
new MarkedAsyncCallback<>(new AsyncCallback<CompactBoatPositionsDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error obtaining racemap data: " + t.getMessage(), true /*silentMode */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompactBoatPositionsDTO result) {
|
||||
updateBoatPositions(newTime, transitionTimeInMillis, fromAndToAndOverlap.getC(), competitorsToShow, result.getBoatPositionsForCompetitors(competitorsByIdAsString));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param updateMarksAndLinesExceptAdvantageLineInCallback
|
||||
* when <code>true</code>, mark positions, mark-related lines such as start line and course middle lines,
|
||||
* three hull length circles and side lines are drawn; otherwise, only the boats, their info flags and
|
||||
* the advantage line will be updated.
|
||||
*/
|
||||
private AsyncCallback<RaceMapDataDTO> getRaceMapDataCallback(
|
||||
final Date newTime,
|
||||
final long transitionTimeInMillis,
|
||||
final Map<CompetitorDTO, Boolean> hasTailOverlapForCompetitor,
|
||||
final Iterable<CompetitorDTO> competitorsToShow, final int requestID,
|
||||
final boolean updateMarksAndLinesExceptAdvantageLineInCallback) {
|
||||
return new AsyncCallback<RaceMapDataDTO>() {
|
||||
final Iterable<CompetitorDTO> competitorsToShow, final int requestID) {
|
||||
return new MarkedAsyncCallback<>(new AsyncCallback<RaceMapDataDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error obtaining racemap data: " + caught.getMessage(), true /*silentMode */);
|
||||
@@ -916,28 +913,19 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
@Override
|
||||
public void onSuccess(RaceMapDataDTO raceMapDataDTO) {
|
||||
if (map != null && raceMapDataDTO != null) {
|
||||
quickRanks = raceMapDataDTO.quickRanks;
|
||||
competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber =
|
||||
raceMapDataDTO.competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber;
|
||||
if (showViewSimulation && settings.isShowSimulationOverlay()) {
|
||||
lastLegNumber = raceMapDataDTO.coursePositions.currentLegNumber;
|
||||
simulationOverlay.updateLeg(Math.max(lastLegNumber,1), /* clearCanvas */ false, raceMapDataDTO.simulationResultVersion);
|
||||
}
|
||||
// process response only if not received out of order
|
||||
if (startedProcessingRequestID < requestID) {
|
||||
startedProcessingRequestID = requestID;
|
||||
quickRanks = raceMapDataDTO.quickRanks;
|
||||
competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber =
|
||||
raceMapDataDTO.competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber;
|
||||
if (showViewSimulation && settings.isShowSimulationOverlay()) {
|
||||
lastLegNumber = raceMapDataDTO.coursePositions.currentLegNumber;
|
||||
simulationOverlay.updateLeg(Math.max(lastLegNumber, 1), /* clearCanvas */ false, raceMapDataDTO.simulationResultVersion);
|
||||
}
|
||||
// Do boat specific actions
|
||||
Map<CompetitorDTO, List<GPSFixDTO>> boatData = raceMapDataDTO.boatPositions;
|
||||
fixesAndTails.updateFixes(boatData, hasTailOverlapForCompetitor, RaceMap.this, transitionTimeInMillis);
|
||||
Iterable<CompetitorDTO> competitorsForWhichNewFixesWereReveiced =
|
||||
fixesAndTails.updateFixes(boatData, hasTailOverlapForCompetitor, RaceMap.this, transitionTimeInMillis);
|
||||
if (!Util.isEmpty(competitorsForWhichNewFixesWereReveiced)) {
|
||||
showBoatsOnMap(newTime, transitionTimeInMillis, competitorsForWhichNewFixesWereReveiced);
|
||||
showCompetitorInfoOnMap(newTime, transitionTimeInMillis, competitorSelection.getSelectedFilteredCompetitors());
|
||||
// even though the wind data is retrieved by a separate call, re-draw the advantage line because it needs to
|
||||
// adjust to new boat positions
|
||||
showAdvantageLine(competitorsToShow, newTime, transitionTimeInMillis);
|
||||
}
|
||||
updateBoatPositions(newTime, transitionTimeInMillis, hasTailOverlapForCompetitor, competitorsToShow, boatData);
|
||||
if (douglasMarkers != null) {
|
||||
removeAllMarkDouglasPeuckerpoints();
|
||||
}
|
||||
@@ -948,13 +936,11 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
if (requiresCoordinateSystemUpdateWhenCoursePositionAndWindDirectionIsKnown) {
|
||||
updateCoordinateSystemFromSettings();
|
||||
}
|
||||
if (updateMarksAndLinesExceptAdvantageLineInCallback) {
|
||||
// Do mark specific actions
|
||||
showCourseMarksOnMap(raceMapDataDTO.coursePositions);
|
||||
showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines);
|
||||
showStartAndFinishAndCourseMiddleLines(raceMapDataDTO.coursePositions);
|
||||
showStartLineToFirstMarkTriangle(raceMapDataDTO.coursePositions);
|
||||
}
|
||||
// Do mark specific actions
|
||||
showCourseMarksOnMap(raceMapDataDTO.coursePositions);
|
||||
showCourseSidelinesOnMap(raceMapDataDTO.courseSidelines);
|
||||
showStartAndFinishAndCourseMiddleLines(raceMapDataDTO.coursePositions);
|
||||
showStartLineToFirstMarkTriangle(raceMapDataDTO.coursePositions);
|
||||
|
||||
// Rezoom the map
|
||||
LatLngBounds zoomToBounds = null;
|
||||
@@ -982,7 +968,22 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
|
||||
lastTimeChangeBeforeInitialization = newTime;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBoatPositions(final Date newTime, final long transitionTimeInMillis,
|
||||
final Map<CompetitorDTO, Boolean> hasTailOverlapForCompetitor,
|
||||
final Iterable<CompetitorDTO> competitorsToShow, Map<CompetitorDTO, List<GPSFixDTO>> boatData) {
|
||||
fixesAndTails.updateFixes(boatData, hasTailOverlapForCompetitor, RaceMap.this, transitionTimeInMillis);
|
||||
Iterable<CompetitorDTO> competitorsForWhichNewFixesWereReveiced =
|
||||
fixesAndTails.updateFixes(boatData, hasTailOverlapForCompetitor, RaceMap.this, transitionTimeInMillis);
|
||||
if (!Util.isEmpty(competitorsForWhichNewFixesWereReveiced)) {
|
||||
showBoatsOnMap(newTime, transitionTimeInMillis, competitorsForWhichNewFixesWereReveiced);
|
||||
showCompetitorInfoOnMap(newTime, transitionTimeInMillis, competitorSelection.getSelectedFilteredCompetitors());
|
||||
// even though the wind data is retrieved by a separate call, re-draw the advantage line because it needs to
|
||||
// adjust to new boat positions
|
||||
showAdvantageLine(competitorsToShow, newTime, transitionTimeInMillis);
|
||||
}
|
||||
}
|
||||
|
||||
private void showCourseSidelinesOnMap(List<SidelineDTO> sidelinesDTOs) {
|
||||
|
||||
+11
-2
@@ -291,6 +291,7 @@ import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO;
|
||||
import com.sap.sailing.gwt.ui.client.SailingService;
|
||||
import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompetitorRaceDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO;
|
||||
@@ -1640,7 +1641,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
public CompactRaceMapDataDTO getRaceMapData(RegattaAndRaceIdentifier raceIdentifier, Date date,
|
||||
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
|
||||
boolean extrapolate, LegIdentifier simulationLegIdentifier) throws NoWindException {
|
||||
final Map<CompetitorDTO, List<GPSFixDTO>> boatPositions = getBoatPositions(raceIdentifier,
|
||||
final Map<CompetitorDTO, List<GPSFixDTO>> boatPositions = getBoatPositionsInternal(raceIdentifier,
|
||||
fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate);
|
||||
final CoursePositionsDTO coursePositions = getCoursePositions(raceIdentifier, date);
|
||||
final List<SidelineDTO> courseSidelines = getCourseSidelines(raceIdentifier, date);
|
||||
@@ -1670,6 +1671,14 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
return competitorBoats;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompactBoatPositionsDTO getBoatPositions(RegattaAndRaceIdentifier raceIdentifier,
|
||||
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
|
||||
boolean extrapolate) throws NoWindException {
|
||||
return new CompactBoatPositionsDTO(getBoatPositionsInternal(raceIdentifier, fromPerCompetitorIdAsString, toPerCompetitorIdAsString, extrapolate));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link LegType}s are cached within the method with a resolution of one minute. The cache key is a pair of
|
||||
* {@link TrackedLegOfCompetitor} and {@link TimePoint}.
|
||||
@@ -1688,7 +1697,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
|
||||
* @return a map where for each competitor participating in the race the list of GPS fixes in increasing
|
||||
* chronological order is provided. The last one is the last position at or before <code>date</code>.
|
||||
*/
|
||||
private Map<CompetitorDTO, List<GPSFixDTO>> getBoatPositions(RegattaAndRaceIdentifier raceIdentifier,
|
||||
private Map<CompetitorDTO, List<GPSFixDTO>> getBoatPositionsInternal(RegattaAndRaceIdentifier raceIdentifier,
|
||||
Map<String, Date> fromPerCompetitorIdAsString, Map<String, Date> toPerCompetitorIdAsString,
|
||||
boolean extrapolate)
|
||||
throws NoWindException {
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.gwt.user.client.rpc.IsSerializable;
|
||||
import com.sap.sailing.domain.common.dto.CompetitorDTO;
|
||||
|
||||
public class CompactBoatPositionsDTO implements IsSerializable {
|
||||
private Map<String, List<GPSFixDTO>> boatPositions;
|
||||
|
||||
CompactBoatPositionsDTO() {} // for GWT serialization only
|
||||
|
||||
public CompactBoatPositionsDTO(Map<CompetitorDTO, List<GPSFixDTO>> boatPositions) {
|
||||
super();
|
||||
this.boatPositions = new HashMap<>();
|
||||
for (final Entry<CompetitorDTO, List<GPSFixDTO>> e : boatPositions.entrySet()) {
|
||||
this.boatPositions.put(e.getKey().getIdAsString(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<CompetitorDTO, List<GPSFixDTO>> getBoatPositionsForCompetitors(Map<String, CompetitorDTO> competitorsByIdsAsStrings) {
|
||||
final Map<CompetitorDTO, List<GPSFixDTO>> result = new HashMap<>();
|
||||
for (final Entry<String, List<GPSFixDTO>> e : boatPositions.entrySet()) {
|
||||
result.put(competitorsByIdsAsStrings.get(e.getKey()), e.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+4
-18
@@ -23,7 +23,7 @@ import com.sap.sse.common.Util;
|
||||
*
|
||||
*/
|
||||
public class CompactRaceMapDataDTO implements IsSerializable {
|
||||
private Map<String, List<GPSFixDTO>> boatPositionsByCompetitorIdAsString;
|
||||
private CompactBoatPositionsDTO boatPositionsByCompetitorIdAsString;
|
||||
|
||||
private CoursePositionsDTO coursePositions;
|
||||
private List<SidelineDTO> courseSidelines;
|
||||
@@ -35,10 +35,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
|
||||
|
||||
public CompactRaceMapDataDTO(Map<CompetitorDTO, List<GPSFixDTO>> boatPositions, CoursePositionsDTO coursePositions,
|
||||
List<SidelineDTO> courseSidelines, QuickRanksDTO quickRanks, long simulationResultVersion) {
|
||||
this.boatPositionsByCompetitorIdAsString = new HashMap<String, List<GPSFixDTO>>();
|
||||
for (Map.Entry<CompetitorDTO, List<GPSFixDTO>> e : boatPositions.entrySet()) {
|
||||
this.boatPositionsByCompetitorIdAsString.put(e.getKey().getIdAsString(), e.getValue());
|
||||
}
|
||||
this.boatPositionsByCompetitorIdAsString = new CompactBoatPositionsDTO(boatPositions);
|
||||
this.quickRanks = new ArrayList<CompactQuickRankDTO>(quickRanks == null ? 0 : Util.size(quickRanks.getQuickRanks()));
|
||||
this.competitorsInOrderOfWindwardDistanceTraveledFarthestFirstIdAsStringAndOneBasedLegNumber = new LinkedHashMap<>();
|
||||
Map<String, Integer> competitorIdAsStringToOneBasedLegNumber = new HashMap<>();
|
||||
@@ -59,11 +56,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
|
||||
this.simulationResultVersion = simulationResultVersion;
|
||||
}
|
||||
|
||||
public RaceMapDataDTO getRaceMapDataDTO(Iterable<CompetitorDTO> competitors) {
|
||||
Map<String, CompetitorDTO> competitorsByIdAsString = new HashMap<String, CompetitorDTO>();
|
||||
for (CompetitorDTO competitor : competitors) {
|
||||
competitorsByIdAsString.put(competitor.getIdAsString(), competitor);
|
||||
}
|
||||
public RaceMapDataDTO getRaceMapDataDTO(Map<String, CompetitorDTO> competitorsByIdAsString) {
|
||||
RaceMapDataDTO result = new RaceMapDataDTO();
|
||||
result.quickRanks = new LinkedHashMap<CompetitorDTO, QuickRankDTO>(this.quickRanks.size());
|
||||
for (CompactQuickRankDTO compactQuickRank : this.quickRanks) {
|
||||
@@ -74,14 +67,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
|
||||
}
|
||||
result.courseSidelines = courseSidelines;
|
||||
result.coursePositions = coursePositions;
|
||||
result.boatPositions = new HashMap<CompetitorDTO, List<GPSFixDTO>>();
|
||||
for (Map.Entry<String, List<GPSFixDTO>> e : boatPositionsByCompetitorIdAsString.entrySet()) {
|
||||
final CompetitorDTO competitor = competitorsByIdAsString.get(e.getKey());
|
||||
if (competitor != null) {
|
||||
// maybe null in case the competitor was added, e.g., by unsuppressing, while this call was underway
|
||||
result.boatPositions.put(competitor, e.getValue());
|
||||
}
|
||||
}
|
||||
result.boatPositions = boatPositionsByCompetitorIdAsString.getBoatPositionsForCompetitors(competitorsByIdAsString);
|
||||
result.competitorsInOrderOfWindwardDistanceTraveledWithOneBasedLegNumber = new LinkedHashMap<>();
|
||||
for (Entry<String, Integer> i : competitorsInOrderOfWindwardDistanceTraveledFarthestFirstIdAsStringAndOneBasedLegNumber.entrySet()) {
|
||||
CompetitorDTO c = competitorsByIdAsString.get(i.getKey());
|
||||
|
||||
Reference in new issue
Block a user