diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceCompetitorMappingFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceCompetitorMappingFinder.java index a8eb5d6ee8c..80b225f94a0 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceCompetitorMappingFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceCompetitorMappingFinder.java @@ -1,9 +1,16 @@ package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; +import java.util.UUID; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceCompetitorMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaLogDeviceCompetitorMappingFinder extends RegattaLogDeviceMappingFinder { @@ -15,4 +22,11 @@ public class RegattaLogDeviceCompetitorMappingFinder extends RegattaLogDeviceMap protected boolean isValidMapping(RegattaLogDeviceMappingEvent mapping) { return mapping instanceof RegattaLogDeviceCompetitorMappingEvent; } + + @Override + protected RegattaLogDeviceCompetitorMappingEvent createDeviceMappingEvent(Competitor item, AbstractLogEventAuthor author, + TimePoint from, TimePoint to, DeviceIdentifier deviceId) { + final TimePoint now = MillisecondsTimePoint.now(); + return new RegattaLogDeviceCompetitorMappingEventImpl(now, now, author, UUID.randomUUID(), item, deviceId, from, to); + } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMappingFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMappingFinder.java index 635e7212c7d..a86f6e835f9 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMappingFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMappingFinder.java @@ -8,17 +8,21 @@ import java.util.List; import java.util.Map; import java.util.logging.Logger; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; +import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; import com.sap.sailing.domain.racelogtracking.DeviceMapping; import com.sap.sailing.domain.racelogtracking.impl.DeviceMappingImpl; import com.sap.sse.common.TimePoint; import com.sap.sse.common.TimeRange; +import com.sap.sse.common.Util; import com.sap.sse.common.WithID; +import com.sap.sse.common.impl.MillisecondsDurationImpl; import com.sap.sse.common.impl.TimeRangeImpl; /** @@ -34,7 +38,7 @@ import com.sap.sse.common.impl.TimeRangeImpl; * {@code DeviceMapping}, the only changes being introduced by closing open time ranges in cases where an * according {@code CloseOpenEndedDeviceMappingEvent} exists. */ -public class RegattaLogDeviceMappingFinder extends RegattaLogAnalyzer>>> { +public abstract class RegattaLogDeviceMappingFinder extends RegattaLogAnalyzer>>> { private static Logger logger = Logger.getLogger(RegattaLogDeviceMappingFinder.class.getName()); public RegattaLogDeviceMappingFinder(RegattaLog log) { @@ -51,41 +55,46 @@ public class RegattaLogDeviceMappingFinder extends Regatta Collections.singletonList(originalEventId)); } - private List getItemSet(Map> map, T item) { - List list = map.get(item); + private List> getMappingEventsForItem(Map>> map, ItemT item) { + List> list = map.get(item); if (list == null) { - list = new ArrayList(); + list = new ArrayList>(); map.put(item, list); } return list; } + @Override protected Map>> performAnalysis() { Map>> events = new HashMap>>(); - Map>> mappings = new HashMap>>(); Map closingEvents = new HashMap(); + findUnrevokedMappingAndClosingEvents(events, closingEvents); + Map>> mappings = new HashMap>>(); + for (ItemT item : events.keySet()) { + mappings.put(item, closeOpenRanges(events.get(item), item, closingEvents)); + } + return mappings; + } + private void findUnrevokedMappingAndClosingEvents(Map>> events, + Map closingEvents) { for (RegattaLogEvent e : getLog().getUnrevokedEvents()) { if (e instanceof RegattaLogDeviceMappingEvent && isValidMapping(((RegattaLogDeviceMappingEvent) e))) { @SuppressWarnings("unchecked") RegattaLogDeviceMappingEvent mappingEvent = (RegattaLogDeviceMappingEvent) e; - getItemSet(events, mappingEvent.getMappedTo()).add(mappingEvent); + getMappingEventsForItem(events, mappingEvent.getMappedTo()).add(mappingEvent); } else if (e instanceof RegattaLogCloseOpenEndedDeviceMappingEvent) { //a higher priority closing events for the same mapping event overwrites the lower priority one RegattaLogCloseOpenEndedDeviceMappingEvent closingEvent = (RegattaLogCloseOpenEndedDeviceMappingEvent) e; closingEvents.put(closingEvent.getDeviceMappingEventId(), closingEvent); } } - for (ItemT item : events.keySet()) { - mappings.put(item, closeOpenRanges(events.get(item), item, closingEvents)); - } - return mappings; } private List> closeOpenRanges(List> events, ItemT item, Map closingEvents) { List> result = new ArrayList>(); - for (RegattaLogDeviceMappingEvent event : events) { + for (final RegattaLogDeviceMappingEvent event : events) { TimePoint from = event.getFrom(); TimePoint to = event.getTo(); TimePoint closingTimePoint = closingEvents.containsKey(event.getId()) ? closingEvents.get(event.getId()) @@ -100,4 +109,31 @@ public class RegattaLogDeviceMappingFinder extends Regatta } return result; } + + /** + * By revoking existing mappings for {@code item} and replacing them by mappings that exclude {@code fixTimePoint}, any + * fix at {@code fixTimePoint} will no longer be linked to {@code item}. If a mapping is limited to the exact fix time point, + * the mapping is only revoked and not replaced. If one boundary is exactly the fix time point, the interval is revoked and + * replaced by a single interval with that border adjusted so it excludes the fix. + */ + public void removeTimePointFromMapping(ItemT item, TimePoint fixTimePoint) throws NotRevokableException { + Map>> events = new HashMap>>(); + Map closingEvents = new HashMap(); + findUnrevokedMappingAndClosingEvents(events, closingEvents); + for (final RegattaLogDeviceMappingEvent event : events.get(item)) { + final TimePoint from = event.getFrom(); + final RegattaLogCloseOpenEndedDeviceMappingEvent closingEvent = closingEvents.get(event.getId()); + final TimePoint to = closingEvent!= null ? closingEvent.getClosingTimePoint() : event.getTo(); + final TimeRange mappingTimeRange = new TimeRangeImpl(from, to); + if (mappingTimeRange.includes(fixTimePoint)) { + if (Util.equalsWithNull(from, fixTimePoint)) { + // revoke original mapping event and replace by one that starts one millisecond after the fix time point + log.revokeEvent(event.getAuthor(), event); + log.add(createDeviceMappingEvent(item, event.getAuthor(), from.plus(new MillisecondsDurationImpl(1)), to, event.getDevice())); + } + } + } + } + + protected abstract RegattaLogDeviceMappingEvent createDeviceMappingEvent(ItemT item, AbstractLogEventAuthor author, TimePoint plus, TimePoint to, DeviceIdentifier deviceId); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMarkMappingFinder.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMarkMappingFinder.java index c692f4d22ba..f78a02598cf 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMarkMappingFinder.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/tracking/analyzing/impl/RegattaLogDeviceMarkMappingFinder.java @@ -1,9 +1,16 @@ package com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl; +import java.util.UUID; + +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMarkMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.racelogtracking.DeviceIdentifier; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.impl.MillisecondsTimePoint; public class RegattaLogDeviceMarkMappingFinder extends RegattaLogDeviceMappingFinder { @@ -15,4 +22,11 @@ public class RegattaLogDeviceMarkMappingFinder extends RegattaLogDeviceMappingFi protected boolean isValidMapping(RegattaLogDeviceMappingEvent mapping) { return mapping instanceof RegattaLogDeviceMarkMappingEvent; } + + @Override + protected RegattaLogDeviceMarkMappingEvent createDeviceMappingEvent(Mark item, AbstractLogEventAuthor author, + TimePoint from, TimePoint to, DeviceIdentifier deviceId) { + final TimePoint now = MillisecondsTimePoint.now(); + return new RegattaLogDeviceMarkMappingEventImpl(now, now, author, UUID.randomUUID(), item, deviceId, from, to); + } } diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch index 263825f093c..2bd988c6083 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT sdm.launch @@ -1,78 +1,78 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index b14028404ea..6adb642328e 100644 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -1,75 +1,75 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 9c506f53723..a45d718feb0 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -633,7 +633,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS */ boolean canRemoveMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix); - void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix); + void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) throws NotRevokableException; void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO newFix); 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 49ba6fc6c7b..d7ea3121c22 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 @@ -91,7 +91,9 @@ import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMa import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogRevokeEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDefinedMarkAnalyzer; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceCompetitorMappingFinder; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogOpenEndedDeviceMappingCloser; import com.sap.sailing.domain.base.Boat; @@ -6111,7 +6113,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S if (raceColumn != null) { final Fleet fleet = raceColumn.getFleetByName(fleetName); if (fleet != null) { - for (final Mark mark : raceColumn.getMarks(fleet)) { + for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { final MarkDTO markDTO = convertToMarkDTO(mark, /* position */ null); final TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); final GPSFixTrack markTrack; @@ -6186,23 +6188,22 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } @Override - public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) { + public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) throws NotRevokableException { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); if (raceColumn != null) { - final Fleet fleet = raceColumn.getFleetByName(fleetName); - if (fleet != null) { - final TrackedRace trackedRace = raceColumn.getTrackedRace(fleet); - } else { - result = false; + final TimePoint fixTimePoint = new MillisecondsTimePoint(fix.timepoint); + final RegattaLog regattaLog = raceColumn.getRegattaLog(); + final Collection marks = new RegattaLogDefinedMarkAnalyzer(regattaLog).analyze(); + final RegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder(regattaLog); + for (final Mark mark : marks) { + if (mark.getId().toString().equals(markIdAsString)) { + mappingFinder.removeTimePointFromMapping(mark, fixTimePoint); + } } - } else { - result = false; } } - // TODO need to find all mappings that span fix's time point; revoke all those mappings and instead create two replacements that end before/start after fix's time point to skip it; - // TODO if an existing mapping starts at or ends with the fix's time point, only one or no replacement mapping may be required ("ping" case). } @Override diff --git a/java/com.sap.sse.security.ui/Security UI sdm.launch b/java/com.sap.sse.security.ui/Security UI sdm.launch index fdc04ec8bf3..63fc7dc7116 100644 --- a/java/com.sap.sse.security.ui/Security UI sdm.launch +++ b/java/com.sap.sse.security.ui/Security UI sdm.launch @@ -1,48 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - +