diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java index 720b3978532..998b30ef79a 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/AbstractLeaderboardDTO.java @@ -31,7 +31,8 @@ public abstract class AbstractLeaderboardDTO implements Serializable { public String defaultCourseAreaName; public ScoringSchemeType scoringScheme; public LeaderboardType type; - public boolean raceLogTrackedRacesCouldBeAdded = false; + public boolean isDenotedForRaceLogTracking = false; + public boolean raceLogTrackersCanBeAdded = false; private Long delayToLiveInMillisForLatestRace; diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/FleetDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/FleetDTO.java index 7c447735a4b..b6beb6758e9 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/FleetDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/FleetDTO.java @@ -8,9 +8,9 @@ public class FleetDTO extends NamedDTO { private Color color; private int orderNo; - public boolean raceLogTrackedRaceCouldBeAdded; + public boolean raceLogTrackerCanBeAdded; public RaceLogTrackingState raceLogTrackingState; - public boolean raceLogTrackerForRaceExists; + public boolean raceLogTrackerExists; public FleetDTO() {} diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelog/tracking/test/impl/CreateAndTrackWithRaceLogTest.java b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelog/tracking/test/impl/CreateAndTrackWithRaceLogTest.java index 1ba7c4de9e6..6f7efd5b79d 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelog/tracking/test/impl/CreateAndTrackWithRaceLogTest.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter.test/src/com/sap/sailing/domain/racelog/tracking/test/impl/CreateAndTrackWithRaceLogTest.java @@ -116,7 +116,7 @@ public class CreateAndTrackWithRaceLogTest { RaceLog raceLog = column.getRaceLog(fleet); //before denoting, it is not listed as loadable - Map> loadable = adapter.listRacesThatCanBeAdded(service, leaderboard); + Map> loadable = adapter.listRaceLogTrackersThatCanBeAdded(service, leaderboard); assertEquals(0, loadable.size()); //can denote racelog for tracking @@ -132,7 +132,7 @@ public class CreateAndTrackWithRaceLogTest { gpsFixStore.storeFix(dev1, new GPSFixMovingImpl(new DegreePosition(0, 0), new MillisecondsTimePoint(15), new KnotSpeedWithBearingImpl(10, new DegreeBearingImpl(5)))); //then listed as loadable - loadable = adapter.listRacesThatCanBeAdded(service, leaderboard); + loadable = adapter.listRaceLogTrackersThatCanBeAdded(service, leaderboard); assertEquals(1, loadable.size()); assertEquals(1, loadable.get(column).size()); diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/RaceLogTrackingAdapter.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/RaceLogTrackingAdapter.java index be2f0a6a0e4..8398c4be9fd 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/RaceLogTrackingAdapter.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/RaceLogTrackingAdapter.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForTrackingException; import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.tracking.impl.RaceLogRaceTracker; import com.sap.sailing.domain.tracking.RacesHandle; @@ -19,40 +20,52 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.RacingEventService; public interface RaceLogTrackingAdapter { - /** - * Can be called either to track a new race, or optionally to load a race - * that is already in the {@link RaceLogTrackingState#TRACKING} state, but - * was closed. - */ - RacesHandle addRace(RacingEventService service, - RegattaIdentifier regattaToAddTo, Leaderboard leaderboard, - RaceColumn raceColumn, Fleet fleet, long timeoutInMilliseconds) - throws MalformedURLException, FileNotFoundException, - URISyntaxException, Exception; + /** + * Can be called either to track a new race, or optionally to load a race that is already in the + * {@link RaceLogTrackingState#TRACKING} state, but was closed. + */ + RacesHandle addRace(RacingEventService service, RegattaIdentifier regattaToAddTo, Leaderboard leaderboard, + RaceColumn raceColumn, Fleet fleet, long timeoutInMilliseconds) throws MalformedURLException, + FileNotFoundException, URISyntaxException, Exception; - /** - * Lists all races for this leaderboards according to the rules in - * {@link #canRaceBeAdded(RacingEventService, Leaderboard, RaceColumn, Fleet)}. - */ - Map> listRacesThatCanBeAdded(RacingEventService service, - Leaderboard leaderboard); + /** + * Lists all races for this leaderboards according to the rules in + * {@link #canRaceBeAdded(RacingEventService, Leaderboard, RaceColumn, Fleet)}. + */ + Map> listRaceLogTrackersThatCanBeAdded(RacingEventService service, Leaderboard leaderboard); - /** - * Returns {@code true}, if a {@link DenoteForTrackingEvent} exists within the {@link RaceLog}, - * and if it does not not already have an attached {@link TrackedRace}, - * and if there is no {@link RaceLogRaceTracker} registered for it already. - */ - boolean canRaceBeAdded(RacingEventService service, RaceColumn raceColumn, Fleet fleet); + /** + * Returns {@code true}, if a {@link DenoteForTrackingEvent} exists within the {@link RaceLog}, and if it does not + * not already have an attached {@link TrackedRace}, and if there is no {@link RaceLogRaceTracker} registered for it + * already. + */ + boolean isDenotedForRaceLogTracking(RacingEventService service, RaceColumn raceColumn, Fleet fleet); - /** - * Denotes the {@link RaceLog} for racelog-tracking, by inserting a - * {@link DenoteForTrackingEvent}. - * - * @throws NotDenotableForTrackingException - * Fails, if no {@link RaceLog}, or a non-empty {@link RaceLog}, or one with attached - * {@link TrackedRace} is found already in place. - */ - void denoteForRaceLogTracking(RacingEventService service, Leaderboard leaderboard, - RaceColumn raceColumn, Fleet fleet, String raceName) - throws NotDenotableForTrackingException; + /** + * Returns {@code true}, if a {@link DenoteForTrackingEvent} exists within the {@link RaceLog}, and if it does not + * not already have an attached {@link TrackedRace}, and if there is no {@link RaceLogRaceTracker} registered for it + * already. + */ + boolean canRaceLogTrackerBeAdded(RacingEventService service, RaceColumn raceColumn, Fleet fleet); + + /** + * Denotes the {@link RaceLog} for racelog-tracking, by inserting a {@link DenoteForTrackingEvent}. + * + * @throws NotDenotableForTrackingException + * Fails, if no {@link RaceLog}, or a non-empty {@link RaceLog}, or one with attached + * {@link TrackedRace} is found already in place. + * Also fails, if the {@code leaderboard} is not a {@link RegattaLeaderboard}. + */ + void denoteForRaceLogTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, + Fleet fleet, String raceName) throws NotDenotableForTrackingException; + + /** + * Denotes the entire {@link Leaderboard} for racelog-tracking, by calling the + * {@link #denoteForRaceLogTracking(RacingEventService, Leaderboard, RaceColumn, Fleet, String)} method for each + * {@link RaceLog}. + * + * Also, a listener is registered, that denotes every {@link RaceLog} that is added at a later time as well. + */ + void denoteForRaceLogTracking(RacingEventService service, Leaderboard leaderboard) + throws NotDenotableForTrackingException; } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/GPSFixJsonHandlerImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/GPSFixJsonHandlerImpl.java index fcb25e70281..5c5b0dd5be7 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/GPSFixJsonHandlerImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/GPSFixJsonHandlerImpl.java @@ -9,23 +9,22 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler; public class GPSFixJsonHandlerImpl implements GPSFixJsonHandler { - private final JsonDeserializer deserializer; - private final JsonSerializer serializer; + private final JsonDeserializer deserializer; + private final JsonSerializer serializer; - public GPSFixJsonHandlerImpl(JsonDeserializer deserializer, - JsonSerializer serializer) { - this.deserializer = deserializer; - this.serializer = serializer; - } + public GPSFixJsonHandlerImpl(JsonDeserializer deserializer, JsonSerializer serializer) { + this.deserializer = deserializer; + this.serializer = serializer; + } - @SuppressWarnings("unchecked") - @Override - public JSONObject transformForth(GPSFix fix) throws IllegalArgumentException { - return serializer.serialize((T) fix); - } + @SuppressWarnings("unchecked") + @Override + public JSONObject transformForth(GPSFix fix) throws IllegalArgumentException { + return serializer.serialize((T) fix); + } - @Override - public GPSFix transformBack(JSONObject json) throws JsonDeserializationException { - return deserializer.deserialize(json); - } + @Override + public GPSFix transformBack(JSONObject json) throws JsonDeserializationException { + return deserializer.deserialize(json); + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogConnectivityParams.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogConnectivityParams.java index 067cca58944..70de214da09 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogConnectivityParams.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogConnectivityParams.java @@ -20,46 +20,47 @@ import com.sap.sailing.domain.tracking.WindStore; import com.sap.sailing.server.RacingEventService; public class RaceLogConnectivityParams implements RaceTrackingConnectivityParameters { - private final RacingEventService service; + private final RacingEventService service; private final RaceColumn raceColumn; private final Fleet fleet; private final Leaderboard leaderboard; private final long delayToLiveInMillis; private final Regatta regatta; - public RaceLogConnectivityParams(RacingEventService service, Regatta regatta, RaceColumn raceColumn, Fleet fleet, Leaderboard leaderboard, long delayToLiveInMillis) - throws RaceNotCreatedException { - this.service = service; - this.regatta = regatta; + public RaceLogConnectivityParams(RacingEventService service, Regatta regatta, RaceColumn raceColumn, Fleet fleet, + Leaderboard leaderboard, long delayToLiveInMillis) throws RaceNotCreatedException { + this.service = service; + this.regatta = regatta; this.raceColumn = raceColumn; this.fleet = fleet; this.leaderboard = leaderboard; this.delayToLiveInMillis = delayToLiveInMillis; - - if (! new RaceLogTrackingStateAnalyzer(getRaceLog()).analyze().isForTracking()) { - throw new RaceNotCreatedException(String.format("Racelog (%s) is not denoted for tracking", getRaceLog())); + + if (!new RaceLogTrackingStateAnalyzer(getRaceLog()).analyze().isForTracking()) { + throw new RaceNotCreatedException(String.format("Racelog (%s) is not denoted for tracking", getRaceLog())); } } - @Override - public RaceTracker createRaceTracker( - TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore) { - return createRaceTracker(regatta, trackedRegattaRegistry, windStore, gpsFixStore); - } + @Override + public RaceTracker createRaceTracker(TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, + GPSFixStore gpsFixStore) { + return createRaceTracker(regatta, trackedRegattaRegistry, windStore, gpsFixStore); + } - @Override - public RaceTracker createRaceTracker(Regatta regatta, - TrackedRegattaRegistry trackedRegattaRegistry, WindStore windStore, GPSFixStore gpsFixStore) { - if (regatta == null) { - BoatClass boatClass = new RaceInformationFinder(getRaceLog()).analyze().getB(); - regatta = service.getOrCreateDefaultRegatta("RaceLog-tracking default Regatta", boatClass.getName(), UUID.randomUUID()); - } - if (regatta == null) { - throw new RaceNotCreatedException("No regatta for race-log tracked race"); - } - DynamicTrackedRegatta trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(regatta); - return new RaceLogRaceTracker(trackedRegatta, this, windStore, gpsFixStore); - } + @Override + public RaceTracker createRaceTracker(Regatta regatta, TrackedRegattaRegistry trackedRegattaRegistry, + WindStore windStore, GPSFixStore gpsFixStore) { + if (regatta == null) { + BoatClass boatClass = new RaceInformationFinder(getRaceLog()).analyze().getB(); + regatta = service.getOrCreateDefaultRegatta("RaceLog-tracking default Regatta", boatClass.getName(), + UUID.randomUUID()); + } + if (regatta == null) { + throw new RaceNotCreatedException("No regatta for race-log tracked race"); + } + DynamicTrackedRegatta trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(regatta); + return new RaceLogRaceTracker(trackedRegatta, this, windStore, gpsFixStore); + } @Override public Object getTrackerID() { @@ -86,8 +87,8 @@ public class RaceLogConnectivityParams implements RaceTrackingConnectivityParame public Leaderboard getLeaderboard() { return leaderboard; } - + public RacingEventService getService() { - return service; + return service; } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogRaceTracker.java index 96c096ce1dd..3e87583aa71 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogRaceTracker.java @@ -57,23 +57,24 @@ import com.sap.sailing.domain.tracking.WindTrack; import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl; /** - * Track a race using the data defined in the {@link RaceLog}. If the events suggest that the race is already - * in the {@link RaceLogTrackingState#TRACKING} state, tracking commences immediately and - * existing fixes are loaded immediately from the database. + * Track a race using the data defined in the {@link RaceLog}. If the events suggest that the race is already in the + * {@link RaceLogTrackingState#TRACKING} state, tracking commences immediately and existing fixes are loaded immediately + * from the database. * * Otherwise, the tracker waits until a {@link StartTrackingEvent} is received to perform these tasks. + * * @author Fredrik Teschke - * + * */ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceTracker, GPSFixReceivedListener { private final RaceLogConnectivityParams params; private final WindStore windStore; private final GPSFixStore gpsFixStore; private final DynamicTrackedRegatta regatta; - + private Map>> competitorMappings = new HashMap<>(); private Map>> markMappings = new HashMap<>(); - + private Map>> markMappingsByDevices = new HashMap<>(); private Map>> competitorMappingsByDevices = new HashMap<>(); @@ -81,20 +82,20 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT private static final Logger logger = Logger.getLogger(RaceLogRaceTracker.class.getName()); - public RaceLogRaceTracker(DynamicTrackedRegatta regatta, RaceLogConnectivityParams params, - WindStore windStore, GPSFixStore gpsFixStore) { + public RaceLogRaceTracker(DynamicTrackedRegatta regatta, RaceLogConnectivityParams params, WindStore windStore, + GPSFixStore gpsFixStore) { this.params = params; this.windStore = windStore; this.gpsFixStore = gpsFixStore; this.regatta = regatta; - - //add a listener on the racelog, to be informed about relevant events + + // add a listener on the racelog, to be informed about relevant events params.getRaceLog().addListener(this); - - logger.info(String.format("Created race-log tracker for: %s %s %s", - params.getLeaderboard(), params.getRaceColumn(), params.getFleet())); - - //load race for which tracking already started + + logger.info(String.format("Created race-log tracker for: %s %s %s", params.getLeaderboard(), + params.getRaceColumn(), params.getFleet())); + + // load race for which tracking already started if (new RaceLogTrackingStateAnalyzer(params.getRaceLog()).analyze() == RaceLogTrackingState.TRACKING) { startTracking(null); } @@ -102,16 +103,16 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT @Override public void stop() { - trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.FINISHED, 100)); - - //remove listener on racelog - params.getRaceLog().removeListener(this); - - //remove listener for fixes - gpsFixStore.removeListener(this); + trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.FINISHED, 100)); - logger.info(String.format("Stopped tracking race-log race %s %s %s", params.getLeaderboard(), params.getRaceColumn(), - params.getFleet())); + // remove listener on racelog + params.getRaceLog().removeListener(this); + + // remove listener for fixes + gpsFixStore.removeListener(this); + + logger.info(String.format("Stopped tracking race-log race %s %s %s", params.getLeaderboard(), + params.getRaceColumn(), params.getFleet())); } @Override @@ -153,192 +154,194 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT public Object getID() { return params.getRaceLog().getId(); } - + private Map>> getNewCompetitorMappings() { - return new DeviceCompetitorMappingFinder(params.getRaceLog()).analyze(); + return new DeviceCompetitorMappingFinder(params.getRaceLog()).analyze(); } - + private Map>> getNewMarkMappings() { - return new DeviceMarkMappingFinder(params.getRaceLog()).analyze(); + return new DeviceMarkMappingFinder(params.getRaceLog()).analyze(); } - + /** * Find the earliest device mapping, set this as start of tracking timepoint */ private void updateStartOfTracking() { - TimePoint earliestMapping = new MillisecondsTimePoint(Long.MAX_VALUE); - - synchronized(competitorMappings) { - for (List> list : competitorMappings.values()) { - for (DeviceMapping mapping : list) { - if (mapping.getTimeRange().from().before(earliestMapping)) { - earliestMapping = mapping.getTimeRange().from(); - } - } - } - } - - synchronized(markMappings) { - for (List> list : markMappings.values()) { - for (DeviceMapping mapping : list) { - if (mapping.getTimeRange().from().before(earliestMapping)) { - earliestMapping = mapping.getTimeRange().from(); - } - } - } - } - - trackedRace.setStartOfTrackingReceived(earliestMapping); + TimePoint earliestMapping = new MillisecondsTimePoint(Long.MAX_VALUE); + + synchronized (competitorMappings) { + for (List> list : competitorMappings.values()) { + for (DeviceMapping mapping : list) { + if (mapping.getTimeRange().from().before(earliestMapping)) { + earliestMapping = mapping.getTimeRange().from(); + } + } + } + } + + synchronized (markMappings) { + for (List> list : markMappings.values()) { + for (DeviceMapping mapping : list) { + if (mapping.getTimeRange().from().before(earliestMapping)) { + earliestMapping = mapping.getTimeRange().from(); + } + } + } + } + + trackedRace.setStartOfTrackingReceived(earliestMapping); } - + private boolean hasMappingAlreadyBeenLoaded( - DeviceMapping newMapping, List> oldMappings) { - for (DeviceMapping oldMapping : oldMappings) { - if (newMapping.getDevice() == oldMapping.getDevice() && - newMapping.getTimeRange().liesWithin(oldMapping.getTimeRange())) { - return true; - } - } - return false; + DeviceMapping newMapping, List> oldMappings) { + for (DeviceMapping oldMapping : oldMappings) { + if (newMapping.getDevice() == oldMapping.getDevice() + && newMapping.getTimeRange().liesWithin(oldMapping.getTimeRange())) { + return true; + } + } + return false; } - - private - Map>> - transformToMappingsByDevice(Map>> mappings) { - - Map>> result = new HashMap<>(); - for (ItemT item : mappings.keySet()) { - for (DeviceMapping mapping : mappings.get(item)) { - List> list = result.get(mapping.getDevice()); - if (list == null) { - list = new ArrayList<>(); - result.put(mapping.getDevice(), list); - } - list.add(mapping); - } - } - - return result; + + private Map>> transformToMappingsByDevice( + Map>> mappings) { + + Map>> result = new HashMap<>(); + for (ItemT item : mappings.keySet()) { + for (DeviceMapping mapping : mappings.get(item)) { + List> list = result.get(mapping.getDevice()); + if (list == null) { + list = new ArrayList<>(); + result.put(mapping.getDevice(), list); + } + list.add(mapping); + } + } + + return result; } - + private void updateMarkMappings(boolean loadIfNotCovered) { - //TODO remove fixes, if mappings have been removed - - synchronized(markMappings) { - //check if there are new time ranges not covered so far - Map>> newMappings = getNewMarkMappings(); - - if (loadIfNotCovered) { - for (Mark mark : newMappings.keySet()) { - DynamicGPSFixTrack track = trackedRace.getOrCreateTrack(mark); - List> oldMappings = markMappings.get(mark); - - for (DeviceMapping newMapping : newMappings.get(mark)) { - if (! hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) { - gpsFixStore.loadMarkTrack(track, newMapping); - } - } - } - } - - markMappings.clear(); - markMappings.putAll(newMappings); - - markMappingsByDevices.clear(); - markMappingsByDevices.putAll(transformToMappingsByDevice(markMappings)); - } - - updateStartOfTracking(); + // TODO remove fixes, if mappings have been removed + + synchronized (markMappings) { + // check if there are new time ranges not covered so far + Map>> newMappings = getNewMarkMappings(); + + if (loadIfNotCovered) { + for (Mark mark : newMappings.keySet()) { + DynamicGPSFixTrack track = trackedRace.getOrCreateTrack(mark); + List> oldMappings = markMappings.get(mark); + + for (DeviceMapping newMapping : newMappings.get(mark)) { + if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) { + gpsFixStore.loadMarkTrack(track, newMapping); + } + } + } + } + + markMappings.clear(); + markMappings.putAll(newMappings); + + markMappingsByDevices.clear(); + markMappingsByDevices.putAll(transformToMappingsByDevice(markMappings)); + } + + updateStartOfTracking(); } - + @Override public void visit(DeviceMarkMappingEvent event) { - if (trackedRace != null) updateMarkMappings(true); + if (trackedRace != null) + updateMarkMappings(true); } - - private void updateCompetitorMappings(boolean loadIfNotCovered) { - //TODO remove fixes, if mappings have been removed - - synchronized(competitorMappings) { - //check if there are new time ranges not covered so far - Map>> newMappings = getNewCompetitorMappings(); - - if (loadIfNotCovered) { - for (Competitor competitor : newMappings.keySet()) { - DynamicGPSFixTrack track = trackedRace.getTrack(competitor); - List> oldMappings = competitorMappings.get(competitor); - - for (DeviceMapping newMapping : newMappings.get(competitor)) { - if (! hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) { - gpsFixStore.loadCompetitorTrack(track, newMapping); - } - } - } - } - - competitorMappings.clear(); - competitorMappings.putAll(newMappings); - - competitorMappingsByDevices.clear(); - competitorMappingsByDevices.putAll(transformToMappingsByDevice(competitorMappings)); - } - updateStartOfTracking(); + private void updateCompetitorMappings(boolean loadIfNotCovered) { + // TODO remove fixes, if mappings have been removed + + synchronized (competitorMappings) { + // check if there are new time ranges not covered so far + Map>> newMappings = getNewCompetitorMappings(); + + if (loadIfNotCovered) { + for (Competitor competitor : newMappings.keySet()) { + DynamicGPSFixTrack track = trackedRace.getTrack(competitor); + List> oldMappings = competitorMappings.get(competitor); + + for (DeviceMapping newMapping : newMappings.get(competitor)) { + if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) { + gpsFixStore.loadCompetitorTrack(track, newMapping); + } + } + } + } + + competitorMappings.clear(); + competitorMappings.putAll(newMappings); + + competitorMappingsByDevices.clear(); + competitorMappingsByDevices.putAll(transformToMappingsByDevice(competitorMappings)); + } + + updateStartOfTracking(); } - + @Override public void visit(DeviceCompetitorMappingEvent event) { - if (trackedRace != null) updateCompetitorMappings(true); + if (trackedRace != null) + updateCompetitorMappings(true); } - + @Override public void visit(StartTrackingEvent event) { - if (trackedRace == null) startTracking(event); + if (trackedRace == null) + startTracking(event); } - + private void startTracking(StartTrackingEvent event) { RaceLog raceLog = params.getRaceLog(); RaceColumn raceColumn = params.getRaceColumn(); Fleet fleet = params.getFleet(); - + Pair raceInfo = new RaceInformationFinder(raceLog).analyze(); BoatClass boatClass = raceInfo.getB(); CourseBase courseBase = new LastPublishedCourseDesignFinder(raceLog).analyze(); if (courseBase == null) { - if (event != null) { - raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(MillisecondsTimePoint.now(), - params.getService().getServerAuthor(), raceLog.getCurrentPassId(), event.getId())); - } + if (event != null) { + raceLog.add(RaceLogEventFactory.INSTANCE.createRevokeEvent(MillisecondsTimePoint.now(), params + .getService().getServerAuthor(), raceLog.getCurrentPassId(), event.getId())); + } throw new RaceNotCreatedException(String.format("Course definition for racelog (%s) missing", raceLog)); } - + Course course = new CourseImpl(raceInfo.getA() + " course", courseBase.getWaypoints()); - + if (raceColumn.getTrackedRace(fleet) != null) { throw new RaceNotCreatedException(String.format("Race for racelog (%s) has already been created", raceLog)); } - + Iterable competitors = new RegisteredCompetitorsAnalyzer(raceLog).analyze(); final RaceDefinition raceDef = new RaceDefinitionImpl(raceInfo.getA(), course, boatClass, competitors); - - Iterable sidelines = Collections.emptyList(); - - //set race definition, so race is linked to leaderboard automatically + + Iterable sidelines = Collections. emptyList(); + + // set race definition, so race is linked to leaderboard automatically regatta.getRegatta().addRace(raceDef); raceColumn.setRaceIdentifier(fleet, regatta.getRegatta().getRaceIdentifier(raceDef)); - - trackedRace = regatta.createTrackedRace(raceDef, sidelines, windStore, gpsFixStore, params.getDelayToLiveInMillis(), - WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, boatClass.getApproximateManeuverDurationInMilliseconds(), - null); - - trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 0)); - updateStartOfTracking(); - - //update the device mappings (without loading the fixes, as the TrackedRace does this itself on startup) - updateCompetitorMappings(false); - updateMarkMappings(false); - //add a listener, so new fixes will also be forwarded to the race + trackedRace = regatta.createTrackedRace(raceDef, sidelines, windStore, gpsFixStore, + params.getDelayToLiveInMillis(), WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, + boatClass.getApproximateManeuverDurationInMilliseconds(), null); + + trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 0)); + updateStartOfTracking(); + + // update the device mappings (without loading the fixes, as the TrackedRace does this itself on startup) + updateCompetitorMappings(false); + updateMarkMappings(false); + + // add a listener, so new fixes will also be forwarded to the race gpsFixStore.addListener(this); logger.info(String.format("Started tracking race-log race (%s)", raceLog)); @@ -351,32 +354,32 @@ public class RaceLogRaceTracker extends BaseRaceLogEventVisitor implements RaceT public RaceLogConnectivityParams getParams() { return params; } - - @Override - public void fixReceived(DeviceIdentifier device, GPSFix fix) { - TimePoint timePoint = fix.getTimePoint(); - if (markMappingsByDevices.get(device) != null) { - for (DeviceMapping mapping : markMappingsByDevices.get(device)) { - Mark mark = mapping.getMappedTo(); - if (mapping.getTimeRange().includes(timePoint)) { - trackedRace.recordFix(mark, fix); - } - } - } - if (competitorMappingsByDevices.get(device) != null) { - for (DeviceMapping mapping : competitorMappingsByDevices.get(device)) { - Competitor comp = mapping.getMappedTo(); - if (mapping.getTimeRange().includes(timePoint)) { - if (fix instanceof GPSFixMoving) { - trackedRace.recordFix(comp, (GPSFixMoving) fix); - } else { - logger.log(Level.WARNING, - String.format("Could not add fix for competitor (%s) in race (%s), as it is no GPSFixMoving", - comp, params.getRaceLog())); - } - } - } - } - } + @Override + public void fixReceived(DeviceIdentifier device, GPSFix fix) { + TimePoint timePoint = fix.getTimePoint(); + if (markMappingsByDevices.get(device) != null) { + for (DeviceMapping mapping : markMappingsByDevices.get(device)) { + Mark mark = mapping.getMappedTo(); + if (mapping.getTimeRange().includes(timePoint)) { + trackedRace.recordFix(mark, fix); + } + } + } + + if (competitorMappingsByDevices.get(device) != null) { + for (DeviceMapping mapping : competitorMappingsByDevices.get(device)) { + Competitor comp = mapping.getMappedTo(); + if (mapping.getTimeRange().includes(timePoint)) { + if (fix instanceof GPSFixMoving) { + trackedRace.recordFix(comp, (GPSFixMoving) fix); + } else { + logger.log(Level.WARNING, String.format( + "Could not add fix for competitor (%s) in race (%s), as it is no GPSFixMoving", comp, + params.getRaceLog())); + } + } + } + } + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterFactoryImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterFactoryImpl.java index 3f82de49f08..f1712eb4007 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterFactoryImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterFactoryImpl.java @@ -5,15 +5,15 @@ import com.sap.sailing.domain.racelog.tracking.RaceLogTrackingAdapter; import com.sap.sailing.domain.racelog.tracking.RaceLogTrackingAdapterFactory; public enum RaceLogTrackingAdapterFactoryImpl implements RaceLogTrackingAdapterFactory { - INSTANCE; - private RaceLogTrackingAdapter adapter; + INSTANCE; + private RaceLogTrackingAdapter adapter; - @Override - public RaceLogTrackingAdapter getAdapter(DomainFactory baseDomainFactory) { - if (adapter == null) { - adapter = new RaceLogTrackingAdapterImpl(baseDomainFactory); - } - return adapter; - } + @Override + public RaceLogTrackingAdapter getAdapter(DomainFactory baseDomainFactory) { + if (adapter == null) { + adapter = new RaceLogTrackingAdapterImpl(baseDomainFactory); + } + return adapter; + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterImpl.java index d8d54d6f04a..aaf7fb1bd98 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/RaceLogTrackingAdapterImpl.java @@ -11,9 +11,11 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.DomainFactory; import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.impl.Function; @@ -23,12 +25,13 @@ import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForTrackingException; import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState; import com.sap.sailing.domain.common.racelog.tracking.RaceNotCreatedException; -import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogEventFactory; +import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.tracking.RaceLogTrackingAdapter; import com.sap.sailing.domain.racelog.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; import com.sap.sailing.domain.tracking.RacesHandle; @@ -36,92 +39,169 @@ import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.server.RacingEventService; public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter { - private static final Logger logger = Logger.getLogger(RaceLogTrackingAdapterImpl.class.getName()); - - private final DomainFactory domainFactory; - private final long delayToLiveInMillis; + private static final Logger logger = Logger.getLogger(RaceLogTrackingAdapterImpl.class.getName()); - public RaceLogTrackingAdapterImpl(DomainFactory domainFactory) { - this.domainFactory = domainFactory; - this.delayToLiveInMillis = TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS; - } +// private final DomainFactory domainFactory; + private final long delayToLiveInMillis; + + public RaceLogTrackingAdapterImpl(DomainFactory domainFactory) { +// this.domainFactory = domainFactory; + this.delayToLiveInMillis = TrackedRace.DEFAULT_LIVE_DELAY_IN_MILLISECONDS; + } + + @Override + public RacesHandle addRace(RacingEventService service, RegattaIdentifier regattaToAddTo, Leaderboard leaderboard, + RaceColumn raceColumn, Fleet fleet, long timeoutInMilliseconds) throws MalformedURLException, + FileNotFoundException, URISyntaxException, RaceNotCreatedException, Exception, RaceNotCreatedException { + Regatta regatta = regattaToAddTo == null ? null : service.getRegatta(regattaToAddTo); + RaceLogConnectivityParams params = new RaceLogConnectivityParams(service, regatta, raceColumn, fleet, + leaderboard, delayToLiveInMillis); + return service.addRace(regattaToAddTo, params, timeoutInMilliseconds); + } - @Override - public RacesHandle addRace(RacingEventService service, RegattaIdentifier regattaToAddTo, Leaderboard leaderboard, - RaceColumn raceColumn, Fleet fleet, long timeoutInMilliseconds) - throws MalformedURLException, FileNotFoundException, URISyntaxException, RaceNotCreatedException, Exception, - RaceNotCreatedException { - Regatta regatta = regattaToAddTo == null ? null : service.getRegatta(regattaToAddTo); - RaceLogConnectivityParams params = new RaceLogConnectivityParams(service, regatta, - raceColumn, fleet, leaderboard, delayToLiveInMillis); - return service.addRace(regattaToAddTo, params, timeoutInMilliseconds); - } - private Map> findInLeaderboard(Leaderboard leaderboard, - Function, Boolean> includeInResult) { + Function, Boolean> includeInResult) { Map> result = new HashMap<>(); for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { for (Fleet fleet : raceColumn.getFleets()) { - if (includeInResult.perform(new Pair<>(raceColumn, fleet))) { - Collection coll = result.get(raceColumn); + if (includeInResult.perform(new Pair<>(raceColumn, fleet))) { + Collection coll = result.get(raceColumn); if (coll == null) { coll = new ArrayList<>(); result.put(raceColumn, coll); } coll.add(fleet); - } + } } } return result; } - + @Override - public Map> listRacesThatCanBeAdded(final RacingEventService service, - Leaderboard leaderboard) { - return findInLeaderboard(leaderboard, new Function, Boolean>() { - @Override - public Boolean perform(Pair in) { - return canRaceBeAdded(service, in.getA(), in.getB()); - } - }); + public Map> listRaceLogTrackersThatCanBeAdded(final RacingEventService service, + Leaderboard leaderboard) { + return findInLeaderboard(leaderboard, new Function, Boolean>() { + @Override + public Boolean perform(Pair in) { + return canRaceLogTrackerBeAdded(service, in.getA(), in.getB()); + } + }); } - @Override - public void denoteForRaceLogTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, - String raceName) - throws NotDenotableForTrackingException { - - BoatClass boatClass = null; - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard rLeaderboard = (RegattaLeaderboard) leaderboard; - boatClass = rLeaderboard.getRegatta().getBoatClass(); - } else if (leaderboard instanceof FlexibleLeaderboard) { - logger.log(Level.INFO, "Choosing 49er as default boat class for racelog-tracked race in FlexibleLeaderboard"); - boatClass = domainFactory.getOrCreateBoatClass("49er"); - } - - if (raceName == null) { - raceName = leaderboard.getName() + " " + raceColumn.getName() + " " + fleet.getName(); - } - - RaceLog raceLog = raceColumn.getRaceLog(fleet); - assert raceLog != null : new NotDenotableForTrackingException("No RaceLog found in place"); - assert raceLog.isEmpty() : new NotDenotableForTrackingException("RaceLog is not empty"); - - RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDenoteForTrackingEvent( - MillisecondsTimePoint.now(), service.getServerAuthor(), raceLog.getCurrentPassId(), raceName, boatClass); - raceLog.add(event); - } + @Override + public void denoteForRaceLogTracking(RacingEventService service, Leaderboard leaderboard, RaceColumn raceColumn, + Fleet fleet, String raceName) throws NotDenotableForTrackingException { - @Override - public boolean canRaceBeAdded(RacingEventService service, RaceColumn raceColumn, Fleet fleet) { - if (raceColumn.getTrackedRace(fleet) == null) { - RaceLog raceLog = raceColumn.getRaceLog(fleet); - if (service.getRaceTrackerById(raceLog.getId()) == null) { - RaceLogTrackingState state = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); - return state.isForTracking(); - } - } - return false; - } + BoatClass boatClass = null; + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard rLeaderboard = (RegattaLeaderboard) leaderboard; + boatClass = rLeaderboard.getRegatta().getBoatClass(); + } else { + throw new NotDenotableForTrackingException("Can only denote RegattaLeaderboards for RaceLog-tracking"); + } + + if (raceName == null) { + raceName = leaderboard.getName() + " " + raceColumn.getName() + " " + fleet.getName(); + } + + RaceLog raceLog = raceColumn.getRaceLog(fleet); + assert raceLog != null : new NotDenotableForTrackingException("No RaceLog found in place"); + assert raceLog.isEmpty() : new NotDenotableForTrackingException("RaceLog is not empty"); + + RaceLogEvent event = RaceLogEventFactory.INSTANCE.createDenoteForTrackingEvent(MillisecondsTimePoint.now(), + service.getServerAuthor(), raceLog.getCurrentPassId(), raceName, boatClass); + raceLog.add(event); + } + + @Override + public void denoteForRaceLogTracking(final RacingEventService service, final Leaderboard leaderboard) + throws NotDenotableForTrackingException { + for (RaceColumn column : leaderboard.getRaceColumns()) { + for (Fleet fleet : column.getFleets()) { + denoteForRaceLogTracking(service, leaderboard, column, fleet, null); + } + } + + // add listener, that also denotes all newly added RaceLogs for tracking + leaderboard.addRaceColumnListener(new RaceColumnListener() { + private static final long serialVersionUID = 3229728745966607941L; + + @Override + public void trackedRaceUnlinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {} + + @Override + public void trackedRaceLinked(RaceColumn raceColumn, Fleet fleet, TrackedRace trackedRace) {} + + @Override + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, + ResultDiscardingRule newDiscardingRule) {} + + @Override + public void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event) {} + + @Override + public void raceColumnRemovedFromContainer(RaceColumn raceColumn) {} + + @Override + public void raceColumnMoved(RaceColumn raceColumn, int newIndex) {} + + @Override + public void raceColumnAddedToContainer(RaceColumn raceColumn) { + for (Fleet fleet : raceColumn.getFleets()) { + try { + denoteForRaceLogTracking(service, leaderboard, raceColumn, fleet, null); + } catch (NotDenotableForTrackingException e) { + logger.log(Level.WARNING, "Listener could not denote newly added RaceLog for racelog-tracking"); + e.printStackTrace(); + } + } + } + + @Override + public boolean isTransient() { + return true; + } + + @Override + public void isStartsWithZeroScoreChanged(RaceColumn raceColumn, boolean newIsStartsWithZeroScore) { } + + @Override + public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) {} + + @Override + public void isFirstColumnIsNonDiscardableCarryForwardChanged(RaceColumn raceColumn, + boolean firstColumnIsNonDiscardableCarryForward) {} + + @Override + public void hasSplitFleetContiguousScoringChanged(RaceColumn raceColumn, boolean hasSplitFleetContiguousScoring) {} + + @Override + public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) {} + + @Override + public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {} + + @Override + public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) { + return true; + } + }); + } + + @Override + public boolean canRaceLogTrackerBeAdded(RacingEventService service, RaceColumn raceColumn, Fleet fleet) { + if (raceColumn.getTrackedRace(fleet) == null) { + RaceLog raceLog = raceColumn.getRaceLog(fleet); + if (service.getRaceTrackerById(raceLog.getId()) == null) { + RaceLogTrackingState state = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); + return state.isForTracking(); + } + } + return false; + } + + @Override + public boolean isDenotedForRaceLogTracking(RacingEventService service, RaceColumn raceColumn, Fleet fleet) { + return new RaceLogTrackingStateAnalyzer(raceColumn.getRaceLog(fleet)).analyze().isForTracking(); + } } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/SmartphoneImeiMongoHandlerImpl.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/SmartphoneImeiMongoHandlerImpl.java index 38482871747..a2c696ab3b4 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/SmartphoneImeiMongoHandlerImpl.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/impl/SmartphoneImeiMongoHandlerImpl.java @@ -7,8 +7,8 @@ import com.sap.sailing.domain.racelog.tracking.SmartphoneImeiIdentifier; public class SmartphoneImeiMongoHandlerImpl implements DeviceIdentifierMongoHandler { private SmartphoneImeiIdentifier castIdentifier(DeviceIdentifier identifier) throws TransformationException { - if (! (identifier instanceof SmartphoneImeiIdentifier)) - throw new TransformationException("Expected a SmartphoneImeiIdentifier, got instead: " + identifier); + if (!(identifier instanceof SmartphoneImeiIdentifier)) + throw new TransformationException("Expected a SmartphoneImeiIdentifier, got instead: " + identifier); return (SmartphoneImeiIdentifier) identifier; } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/servlet/RecordFixesPostServlet.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/servlet/RecordFixesPostServlet.java index e055bd2e551..0b7d8fcb3cf 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/servlet/RecordFixesPostServlet.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelog/tracking/servlet/RecordFixesPostServlet.java @@ -19,17 +19,18 @@ import com.sap.sailing.server.gateway.serialization.JsonSerializer; import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler; import com.sap.sailing.server.gateway.serialization.racelog.tracking.GPSFixJsonHandler; -public class RecordFixesPostServlet extends AbstractJsonPostServlet>, Void> { +public class RecordFixesPostServlet extends + AbstractJsonPostServlet>, Void> { private static final long serialVersionUID = 2778739335260621119L; private DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer; @Override - public void init(ServletConfig config) throws ServletException { - super.init(config); - TypeBasedServiceFinder fixServiceFinder = - getServiceFinderFactory().createServiceFinder(GPSFixJsonHandler.class); - TypeBasedServiceFinder deviceServiceFinder = - getServiceFinderFactory().createServiceFinder(DeviceIdentifierJsonHandler.class); + public void init(ServletConfig config) throws ServletException { + super.init(config); + TypeBasedServiceFinder fixServiceFinder = getServiceFinderFactory().createServiceFinder( + GPSFixJsonHandler.class); + TypeBasedServiceFinder deviceServiceFinder = getServiceFinderFactory() + .createServiceFinder(DeviceIdentifierJsonHandler.class); deserializer = new DeviceAndSessionIdentifierWithGPSFixesDeserializer(fixServiceFinder, deviceServiceFinder); } @@ -47,14 +48,14 @@ public class RecordFixesPostServlet extends AbstractJsonPostServlet parameterValues, Triple> domainObject) throws HttpExceptionWithMessage { DeviceIdentifier device = domainObject.getA(); - //might use the session id in the future -// Serializable sessionId = domainObject.getB(); + // might use the session id in the future + // Serializable sessionId = domainObject.getB(); List fixes = domainObject.getC(); - + for (GPSFix fix : fixes) { - getService().getGPSFixStore().storeFix(device, fix); + getService().getGPSFixStore().storeFix(device, fix); } - - return null; + + return null; } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/analyzing/impl/RaceLogTrackingStateAnalyzer.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/analyzing/impl/RaceLogTrackingStateAnalyzer.java index 05dc04b848e..712cde0e9a4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/analyzing/impl/RaceLogTrackingStateAnalyzer.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/racelog/tracking/analyzing/impl/RaceLogTrackingStateAnalyzer.java @@ -19,7 +19,6 @@ public class RaceLogTrackingStateAnalyzer extends RaceLogAnalyzer getImageSpecs() { - return Arrays.asList(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon())), - new ImageSpec(ACTION_EDIT_SCORES, stringMessages.actionEditScores(), makeImagePrototype(resources.scoresIcon())), - new ImageSpec(ACTION_EDIT_COMPETITORS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon())), - new ImageSpec(ACTION_CONFIGURE_URL, stringMessages.actionConfigureUrl(), makeImagePrototype(resources.settingsActionIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon())), - new ImageSpec(ACTION_EXPORT_XML, stringMessages.actionExportXML(), makeImagePrototype(resources.exportXMLIcon())), - new ImageSpec(ACTION_ADD_RACELOG_TRACKER, stringMessages.addRaceLogTracker(), makeImagePrototype(resources.addRaceLogTracker()))); + ArrayList result = new ArrayList(); + result.add(new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(resources.editIcon()))); + result.add(new ImageSpec(ACTION_EDIT_SCORES, stringMessages.actionEditScores(), makeImagePrototype(resources.scoresIcon()))); + result.add(new ImageSpec(ACTION_EDIT_COMPETITORS, stringMessages.actionEditCompetitors(), makeImagePrototype(resources.competitorsIcon()))); + result.add(new ImageSpec(ACTION_CONFIGURE_URL, stringMessages.actionConfigureUrl(), makeImagePrototype(resources.settingsActionIcon()))); + result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(resources.removeIcon()))); + result.add(new ImageSpec(ACTION_EXPORT_XML, stringMessages.actionExportXML(), makeImagePrototype(resources.exportXMLIcon()))); + return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index beccd284741..fa8c9bfb297 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -50,7 +50,6 @@ import com.sap.sailing.domain.common.dto.NamedDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.impl.Util; import com.sap.sailing.domain.common.impl.Util.Pair; -import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState; import com.sap.sailing.gwt.ui.adminconsole.DisablableCheckboxCell.IsEnabled; import com.sap.sailing.gwt.ui.adminconsole.RaceColumnInLeaderboardDialog.RaceColumnDescriptor; import com.sap.sailing.gwt.ui.client.ErrorReporter; @@ -76,7 +75,7 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.gwt.ui.DataEntryDialog.DialogCallback; public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderboardProvider, RegattaDisplayer, RaceSelectionChangeListener, - TrackedRaceChangedListener { +TrackedRaceChangedListener { private final TrackedRacesListComposite trackedRacesListComposite; @@ -132,7 +131,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb private static AnchorTemplates ANCHORTEMPLATE = GWT.create(AnchorTemplates.class); - private static class RaceColumnDTOAndFleetDTOWithNameBasedEquality extends Pair { + public static class RaceColumnDTOAndFleetDTOWithNameBasedEquality extends Pair { private static final long serialVersionUID = -8742476113296862662L; public RaceColumnDTOAndFleetDTOWithNameBasedEquality(RaceColumnDTO a, FleetDTO b) { @@ -250,7 +249,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb int val = -1; val = (o1 != null && o2 != null && ascending) ? (o1.name.compareTo(o2.name)) : -(o2.name .compareTo(o1.name)); - + return val; } @@ -362,13 +361,11 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } }); editCompetitorsDialog.show(); - + } else if (LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL.equals(value)) { openLeaderboardUrlConfigDialog(leaderboardDTO, stringMessages); } else if (LeaderboardConfigImagesBarCell.ACTION_EXPORT_XML.equals(value)) { Window.open("/export/xml?domain=leaderboard&name=" + leaderboardDTO.name, "", null); - } else if (LeaderboardConfigImagesBarCell.ACTION_ADD_RACELOG_TRACKER.equals(value)) { - addRaceLogTracker(leaderboardDTO); } } }); @@ -497,7 +494,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb @Override public boolean isEnabled() { return getSelectedLeaderboard() != null && !getSelectedLeaderboard().type.isRegattaLeaderboard(); - + } })) { @Override @@ -521,22 +518,6 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } }; - TextColumn raceLogTrackerExistsColumn = new TextColumn() { - @Override - public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) { - boolean trackerExists = raceColumnAndFleetName.getB().raceLogTrackerForRaceExists; - return trackerExists ? "X" : ""; - } - }; - - TextColumn raceLogTrackingStateColumn = new TextColumn() { - @Override - public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) { - RaceLogTrackingState state = raceColumnAndFleetName.getB().raceLogTrackingState; - return state.isForTracking() ? state.name() : ""; - } - }; - ImagesBarColumn raceActionColumn = new ImagesBarColumn( new LeaderboardRaceConfigImagesBarCell(this, stringMessages)); @@ -557,10 +538,6 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb setStartTime(object.getA(), object.getB()); } else if(LeaderboardRaceConfigImagesBarCell.ACTION_SHOW_RACELOG.equals(value)) { showRaceLog(object.getA(), object.getB()); - } else if (LeaderboardRaceConfigImagesBarCell.ACTION_ADD_RACELOG_TRACKER.equals(value)) { - addRaceLogTracker(object.getA(), object.getB()); - } else if (LeaderboardRaceConfigImagesBarCell.ACTION_DENOTE_FOR_RACELOG_TRACKING.equals(value)) { - denoteForRaceLogTracking(object.getA(), object.getB()); } } }); @@ -573,8 +550,6 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb raceColumnTable.addColumn(isMedalRaceCheckboxColumn, stringMessages.medalRace()); raceColumnTable.addColumn(isLinkedRaceColumn, stringMessages.islinked()); raceColumnTable.addColumn(explicitFactorColumn, stringMessages.factor()); - raceColumnTable.addColumn(raceLogTrackerExistsColumn, stringMessages.raceLogTrackerExists()); - raceColumnTable.addColumn(raceLogTrackingStateColumn, stringMessages.raceLogTrackingState()); raceColumnTable.addColumn(raceActionColumn, stringMessages.actions()); raceColumnAndFleetList.addDataDisplay(raceColumnTable); raceColumnTable.setWidth("500px"); @@ -794,7 +769,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb } }); } - + private void openRaceLogDialog(RaceLogDTO raceLogDTO) { RaceLogDialog dialog = new RaceLogDialog(raceLogDTO, stringMessages, new DialogCallback() { @Override @@ -927,12 +902,12 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb + selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": " + t.getMessage()); } - + @Override public void onSuccess(Map regattaAndRaceNamesPerFleet) { if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) { - RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet - .get(selectedFleetName); + RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet + .get(selectedFleetName); if (raceIdentifier != null) { selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName()); } else { @@ -1028,7 +1003,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingIsMedalRace(caught.getMessage())); } - + @Override public void onSuccess(Void result) { getSelectedLeaderboard().setIsMedalRace(raceInLeaderboard.getRaceColumnName(), isMedalRace); @@ -1047,7 +1022,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb @Override public void cancel() { } - + @Override public void ok(final List result) { updateRaceColumnsOfLeaderboard(leaderboardName, existingRaceColumns, result); @@ -1163,7 +1138,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb @Override public void cancel() { } - + @Override public void ok(final LeaderboardDescriptor newLeaderboard) { sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), @@ -1174,7 +1149,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb errorReporter.reportError("Error trying to create the new flexible leaderboard " + newLeaderboard.getName() + ": " + t.getMessage()); } - + @Override public void handleSuccess(StrippedLeaderboardDTO result) { addLeaderboard(result); @@ -1203,7 +1178,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb errorReporter.reportError("Error trying to create the new regatta leaderboard " + newLeaderboard.getName() + ": " + t.getMessage()); } - + @Override public void onSuccess(StrippedLeaderboardDTO result) { addLeaderboard(result); @@ -1229,7 +1204,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb errorReporter.reportError("Error trying to update leaderboard " + oldLeaderboardName + ": " + t.getMessage()); } - + @Override public void onSuccess(StrippedLeaderboardDTO updatedLeaderboard) { int indexOfLeaderboard = 0; @@ -1257,7 +1232,7 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove the leaderboards:" + caught.getMessage()); - + } @@ -1335,58 +1310,4 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb public StrippedLeaderboardDTO getSelectedLeaderboard() { return leaderboardSelectionModel.getSelectedSet().isEmpty() ? null : leaderboardSelectionModel.getSelectedSet().iterator().next(); } - - private void addRaceLogTracker(final StrippedLeaderboardDTO leaderboard) { - final RaceColumnDTOAndFleetDTOWithNameBasedEquality selectedRCFleet = getSelectedRaceColumnWithFleet(); - if (leaderboard.raceLogTrackedRacesCouldBeAdded) { - sailingService.addRaceLogTrackers(leaderboard.name, new AsyncCallback() { - @Override - public void onSuccess(Void result) { - loadAndRefreshLeaderboard(leaderboard.name, selectedRCFleet.getA().getName()); - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Failed to add RaceLog tracker: " + caught.getMessage()); - } - }); - } else { - errorReporter.reportError("No RaceLogTracker can be added for any of the RaceLogs in this leaderboard"); - } - } - - private void addRaceLogTracker(final RaceColumnDTO raceColumn, FleetDTO fleet) { - if (fleet.raceLogTrackedRaceCouldBeAdded) { - final StrippedLeaderboardDTO leaderboard = getSelectedLeaderboard(); - sailingService.addRaceLogTracker(leaderboard.name, raceColumn.getName(), fleet.getName(), new AsyncCallback() { - @Override - public void onSuccess(Void result) { - loadAndRefreshLeaderboard(leaderboard.name, raceColumn.getName()); - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Failed to add RaceLog trackers: " + caught.getMessage()); - } - }); - } else { - errorReporter.reportError("No RaceLogTracker can be added for the RaceLog of this fleet"); - } - } - - private void denoteForRaceLogTracking(final RaceColumnDTO raceColumn, final FleetDTO fleet) { - final StrippedLeaderboardDTO leaderboard = getSelectedLeaderboard(); - sailingService.denoteForRaceLogTracking(leaderboard.name, raceColumn.getName(), fleet.getName(), new AsyncCallback() { - @Override - public void onSuccess(Void result) { - loadAndRefreshLeaderboard(leaderboard.name, raceColumn.getName()); - refreshRaceLog(raceColumn, fleet, true); - } - - @Override - public void onFailure(Throwable caught) { - errorReporter.reportError("Could not denote for RaceLog tracking: " + caught.getMessage()); - } - }); - } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java index 21773d41926..3a938222b06 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardRaceConfigImagesBarCell.java @@ -16,8 +16,6 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { public final static String ACTION_REFRESH_RACELOG = "ACTION_REFRESH_RACE_LOG"; public final static String ACTION_SET_STARTTIME = "ACTION_SET_STARTTIME"; public final static String ACTION_SHOW_RACELOG = "ACTION_SHOW_RACELOG"; - public final static String ACTION_ADD_RACELOG_TRACKER = "ACTION_ADD_RACELOG_TRACKER"; - public final static String ACTION_DENOTE_FOR_RACELOG_TRACKING = "ACTION_DENOTE_FOR_RACELOG_TRACKING"; private final StringMessages stringMessages; private final SelectedLeaderboardProvider selectedLeaderboardProvider; @@ -42,8 +40,6 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell { result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon()))); result.add(new ImageSpec(ACTION_SET_STARTTIME, stringMessages.setStartTime(), makeImagePrototype(resources.clockIcon()))); result.add(new ImageSpec(ACTION_SHOW_RACELOG, stringMessages.raceLog(), makeImagePrototype(resources.flagIcon()))); - result.add(new ImageSpec(ACTION_ADD_RACELOG_TRACKER, stringMessages.addRaceLogTracker(), makeImagePrototype(resources.addRaceLogTracker()))); - result.add(new ImageSpec(ACTION_DENOTE_FOR_RACELOG_TRACKING, stringMessages.denoteForRaceLogTracking(), makeImagePrototype(resources.denoteForRaceLogTracking()))); return result; } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementImagesBarCell.java new file mode 100644 index 00000000000..7821d029b79 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementImagesBarCell.java @@ -0,0 +1,41 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.text.shared.SafeHtmlRenderer; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; + +public class RaceLogTrackingEventManagementImagesBarCell extends ImagesBarCell { + public static final String ACTION_DENOTE_FOR_RACELOG_TRACKING = "ACTION_DENOTE_FOR_RACELOG_TRACKING"; + public static final String ACTION_ADD_RACELOG_TRACKERS = "ACTION_ADD_RACELOG_TRACKERS"; + private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); + private final StringMessages stringMessages; + + public RaceLogTrackingEventManagementImagesBarCell(StringMessages stringMessages) { + super(); + this.stringMessages = stringMessages; + } + + public RaceLogTrackingEventManagementImagesBarCell(SafeHtmlRenderer renderer, StringMessages stringConstants) { + super(); + this.stringMessages = stringConstants; + } + + @Override + protected Iterable getImageSpecs() { + ArrayList result = new ArrayList(); + + StrippedLeaderboardDTO leaderboard = (StrippedLeaderboardDTO) getContext().getKey(); + if (! leaderboard.isDenotedForRaceLogTracking) { + result.add(new ImageSpec(ACTION_DENOTE_FOR_RACELOG_TRACKING, stringMessages.denoteForRaceLogTracking(), makeImagePrototype(resources.denoteForRaceLogTracking()))); + } + if (leaderboard.raceLogTrackersCanBeAdded) { + result.add(new ImageSpec(ACTION_ADD_RACELOG_TRACKERS, stringMessages.addRaceLogTrackers(), makeImagePrototype(resources.addRaceLogTracker()))); + } + + return result; + } +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementPanel.java new file mode 100644 index 00000000000..a11b655106c --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementPanel.java @@ -0,0 +1,401 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.cell.client.FieldUpdater; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.cellview.client.CellTable; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.CaptionPanel; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.google.gwt.view.client.SingleSelectionModel; +import com.sap.sailing.domain.common.LeaderboardType; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState; +import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; +import com.sap.sailing.gwt.ui.client.ErrorReporter; +import com.sap.sailing.gwt.ui.client.RaceSelectionModel; +import com.sap.sailing.gwt.ui.client.RegattaRefresher; +import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.shared.panels.LabeledAbstractFilterablePanel; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; + +/** + * Allows the user to start and stop tracking of races using the RaceLog-tracking connector. + */ +public class RaceLogTrackingEventManagementPanel extends AbstractEventManagementPanel { + private final ListDataProvider leaderboardList; + private final ListDataProvider raceColumnAndFleetList; + private final CellTable leaderboardTable; + private final CellTable raceColumnTable; + private final CaptionPanel selectedLeaderBoardPanel; + private final CaptionPanel trackedRacesCaptionPanel; + private LabeledAbstractFilterablePanel filterLeaderboardPanel; + final SingleSelectionModel raceColumnTableSelectionModel; + private List availableLeaderboardList; + private final MultiSelectionModel leaderboardSelectionModel; + + public RaceLogTrackingEventManagementPanel(SailingServiceAsync sailingService, RegattaRefresher regattaRefresher, + ErrorReporter errorReporter, StringMessages stringMessages) { + super(sailingService, regattaRefresher, errorReporter, new RaceSelectionModel(), stringMessages); + leaderboardList = new ListDataProvider(); + raceColumnAndFleetList = new ListDataProvider(); + this.errorReporter = errorReporter; + this.availableLeaderboardList = new ArrayList(); + VerticalPanel mainPanel = new VerticalPanel(); + mainPanel.setWidth("100%"); + this.setWidget(mainPanel); + + //Create leaderboards list and functionality + CaptionPanel leaderboardsCaptionPanel = new CaptionPanel(stringMessages.leaderboards()); + leaderboardsCaptionPanel.setStyleName("bold"); + leaderboardsCaptionPanel.setWidth("75%"); + mainPanel.add(leaderboardsCaptionPanel); + + VerticalPanel leaderboardsPanel = new VerticalPanel(); + leaderboardsCaptionPanel.add(leaderboardsPanel); + + HorizontalPanel leaderboardConfigControlsPanel = new HorizontalPanel(); + Label lblFilterEvents = new Label(stringMessages.filterLeaderboardsByName() + ": "); + leaderboardConfigControlsPanel.setSpacing(5); + + AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); + leaderboardTable = new CellTable(/* pageSize */10000, tableRes); + filterLeaderboardPanel = new LabeledAbstractFilterablePanel(lblFilterEvents, availableLeaderboardList, leaderboardTable, leaderboardList) { + @Override + public List getSearchableStrings(StrippedLeaderboardDTO t) { + List strings = new ArrayList(); + strings.add(t.name); + strings.add(t.displayName); + return strings; + } + }; + leaderboardConfigControlsPanel.add(filterLeaderboardPanel); + leaderboardsPanel.add(leaderboardConfigControlsPanel); + ListHandler leaderboardColumnListHandler = new ListHandler( + leaderboardList.getList()); + + TextColumn leaderboardNameColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + return leaderboard.name; + } + }; + + TextColumn leaderboardDisplayNameColumn = new TextColumn() { + @Override + public String getValue(StrippedLeaderboardDTO leaderboard) { + return leaderboard.getDisplayName() != null ? leaderboard.getDisplayName() : ""; + } + }; + + ImagesBarColumn leaderboardActionColumn = + new ImagesBarColumn( + new RaceLogTrackingEventManagementImagesBarCell(stringMessages)); + leaderboardActionColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, StrippedLeaderboardDTO leaderboardDTO, String value) { + if (RaceLogTrackingEventManagementImagesBarCell.ACTION_ADD_RACELOG_TRACKERS.equals(value)) { + addRaceLogTrackers(leaderboardDTO); + } else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_DENOTE_FOR_RACELOG_TRACKING.equals(value)) { + denoteForRaceLogTracking(leaderboardDTO); + } + } + }); + + leaderboardTable.addColumn(leaderboardNameColumn, stringMessages.name()); + leaderboardTable.addColumn(leaderboardDisplayNameColumn, stringMessages.displayName()); + leaderboardTable.addColumn(leaderboardActionColumn, stringMessages.actions()); + leaderboardTable.addColumnSortHandler(leaderboardColumnListHandler); + leaderboardTable.setWidth("100%"); + leaderboardSelectionModel = new MultiSelectionModel(); + leaderboardTable.setSelectionModel(leaderboardSelectionModel); + leaderboardSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { + public void onSelectionChange(SelectionChangeEvent event) { + leaderboardSelectionChanged(); + } + }); + leaderboardList.addDataDisplay(leaderboardTable); + leaderboardsPanel.add(leaderboardTable); + HorizontalPanel leaderboardButtonPanel = new HorizontalPanel(); + leaderboardButtonPanel.setSpacing(5); + leaderboardsPanel.add(leaderboardButtonPanel); + + mainPanel.add(new Grid(1, 1)); + + // caption panels for the selected leaderboard and tracked races + HorizontalPanel splitPanel = new HorizontalPanel(); + mainPanel.add(splitPanel); + + selectedLeaderBoardPanel = new CaptionPanel(stringMessages.leaderboard()); + selectedLeaderBoardPanel.setWidth("50%"); + splitPanel.add(selectedLeaderBoardPanel); + + VerticalPanel vPanel = new VerticalPanel(); + vPanel.setWidth("100%"); + selectedLeaderBoardPanel.setContentWidget(vPanel); + + trackedRacesCaptionPanel = new CaptionPanel(stringMessages.trackedRaces()); + trackedRacesCaptionPanel.setWidth("50%"); + splitPanel.add(trackedRacesCaptionPanel); + + VerticalPanel trackedRacesPanel = new VerticalPanel(); + trackedRacesPanel.setWidth("100%"); + trackedRacesCaptionPanel.setContentWidget(trackedRacesPanel); + trackedRacesCaptionPanel.setStyleName("bold"); + + + // ------------ races of the selected leaderboard ---------------- + TextColumn raceNameColumn = new TextColumn() { + @Override + public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) { + return object.getA().getName(); + } + }; + TextColumn fleetNameColumn = new TextColumn() { + @Override + public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) { + return object.getB().getName(); + } + }; + + TextColumn raceLogTrackingStateColumn = new TextColumn() { + @Override + public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) { + RaceLogTrackingState state = raceColumnAndFleetName.getB().raceLogTrackingState; + if (raceColumnAndFleetName.getB().raceLogTrackerExists) { + if (state == RaceLogTrackingState.TRACKING) { + return "Tracking"; + } else { + return "Tracker is listening"; + } + } else if (raceColumnAndFleetName.getB().raceLogTrackingState.isForTracking()) { + return "Denoted"; + } else { + return "Not denoted"; + } + } + }; + + ImagesBarColumn raceActionColumn = + new ImagesBarColumn( + new RaceLogTrackingEventManagementRaceImagesBarCell(stringMessages)); + raceActionColumn.setFieldUpdater(new FieldUpdater() { + @Override + public void update(int index, RaceColumnDTOAndFleetDTOWithNameBasedEquality object, String value) { + if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_ADD_RACELOG_TRACKER.equals(value)) { + addRaceLogTracker(object.getA(), object.getB()); + } else if (RaceLogTrackingEventManagementRaceImagesBarCell.ACTION_DENOTE_FOR_RACELOG_TRACKING.equals(value)) { + denoteForRaceLogTracking(object.getA(), object.getB()); + } + } + }); + + Label lblRaceNamesIn = new Label(stringMessages.races()); + vPanel.add(lblRaceNamesIn); + raceColumnTable = new CellTable(/* pageSize */200, tableRes); + raceColumnTable.ensureDebugId("RaceColumnTable"); + raceColumnTable.addColumn(raceNameColumn, stringMessages.race()); + raceColumnTable.addColumn(fleetNameColumn, stringMessages.fleet()); + raceColumnTable.addColumn(raceLogTrackingStateColumn, stringMessages.status()); + raceColumnTable.addColumn(raceActionColumn, stringMessages.actions()); + raceColumnAndFleetList.addDataDisplay(raceColumnTable); + raceColumnTable.setWidth("500px"); + raceColumnTableSelectionModel = new SingleSelectionModel(); + raceColumnTable.setSelectionModel(raceColumnTableSelectionModel); + vPanel.add(raceColumnTable); + + HorizontalPanel selectedLeaderboardRaceButtonPanel = new HorizontalPanel(); + selectedLeaderboardRaceButtonPanel.setSpacing(5); + vPanel.add(selectedLeaderboardRaceButtonPanel); + + loadLeaderboards(); + } + + public void loadLeaderboards() { + sailingService.getLeaderboards(new AsyncCallback>() { + @Override + public void onSuccess(List leaderboards) { + leaderboardList.getList().clear(); + availableLeaderboardList.clear(); + for (StrippedLeaderboardDTO leaderboard : leaderboards) { + if (leaderboard.type == LeaderboardType.RegattaLeaderboard) { + leaderboardList.getList().add(leaderboard); + availableLeaderboardList.add(leaderboard); + } + } + filterLeaderboardPanel.updateAll(availableLeaderboardList); + leaderboardSelectionChanged(); + } + + @Override + public void onFailure(Throwable t) { + RaceLogTrackingEventManagementPanel.this.errorReporter.reportError("Error trying to obtain list of leaderboards: " + + t.getMessage()); + } + }); + } + + /** + * @param nameOfRaceColumnToSelect + * if not null, selects the first race column name with this name found in the leaderboard + * after the refresh has successfully completed. See {@link #selectRaceColumn(String)}. + */ + public void loadAndRefreshLeaderboard(final String leaderboardName, final String nameOfRaceColumnToSelect) { + sailingService.getLeaderboard(leaderboardName, new AsyncCallback() { + @Override + public void onSuccess(StrippedLeaderboardDTO leaderboard) { + for (StrippedLeaderboardDTO leaderboardDTO : leaderboardSelectionModel.getSelectedSet()) { + if (leaderboardDTO.name.equals(leaderboardName)) { + leaderboardSelectionModel.setSelected(leaderboardDTO, false); + break; + } + } + + replaceLeaderboardInList(leaderboardList.getList(), leaderboardName, leaderboard); + replaceLeaderboardInList(availableLeaderboardList, leaderboardName, leaderboard); + leaderboardSelectionModel.setSelected(leaderboard, true); + if (nameOfRaceColumnToSelect != null) { + selectRaceColumn(nameOfRaceColumnToSelect); + } + leaderboardSelectionChanged(); + } + + @Override + public void onFailure(Throwable t) { + RaceLogTrackingEventManagementPanel.this.errorReporter.reportError("Error trying to update leaderboard with name " + leaderboardName + " : " + + t.getMessage()); + } + }); + } + + private void replaceLeaderboardInList(List leaderboardList, String leaderboardToReplace, StrippedLeaderboardDTO newLeaderboard) { + int index = -1; + for (StrippedLeaderboardDTO existingLeaderboard : leaderboardList) { + index++; + if (existingLeaderboard.name.equals(leaderboardToReplace)) { + break; + } + } + if (index >= 0) { + leaderboardList.set(index, newLeaderboard); + } + } + + private void selectRaceColumn(String raceCoumnName) { + List list = raceColumnAndFleetList.getList(); + for (RaceColumnDTOAndFleetDTOWithNameBasedEquality pair : list) { + if (pair.getA().getName().equals(raceCoumnName)) { + raceColumnTableSelectionModel.setSelected(pair, true); + break; + } + } + } + + private RaceColumnDTOAndFleetDTOWithNameBasedEquality getSelectedRaceColumnWithFleet() { + RaceColumnDTOAndFleetDTOWithNameBasedEquality raceInLeaderboardAndFleetName = raceColumnTableSelectionModel.getSelectedObject(); + return raceInLeaderboardAndFleetName; + } + + private void leaderboardSelectionChanged() { + StrippedLeaderboardDTO selectedLeaderboard = getSelectedLeaderboard(); + if (leaderboardSelectionModel.getSelectedSet().size() == 1 && selectedLeaderboard != null) { + raceColumnAndFleetList.getList().clear(); + for (RaceColumnDTO raceColumn : selectedLeaderboard.getRaceList()) { + for (FleetDTO fleet : raceColumn.getFleets()) { + raceColumnAndFleetList.getList().add(new RaceColumnDTOAndFleetDTOWithNameBasedEquality(raceColumn, fleet)); + } + } + selectedLeaderBoardPanel.setVisible(true); + selectedLeaderBoardPanel.setCaptionText("Details of leaderboard '" + selectedLeaderboard.name + "'"); + if (!selectedLeaderboard.type.isMetaLeaderboard()) { + trackedRacesCaptionPanel.setVisible(true); + } + } else { + selectedLeaderBoardPanel.setVisible(false); + trackedRacesCaptionPanel.setVisible(false); + } + } + + private StrippedLeaderboardDTO getSelectedLeaderboard() { + return leaderboardSelectionModel.getSelectedSet().isEmpty() ? null : leaderboardSelectionModel.getSelectedSet().iterator().next(); + } + + private void denoteForRaceLogTracking(final StrippedLeaderboardDTO leaderboard) { + sailingService.denoteForRaceLogTracking(leaderboard.name, new AsyncCallback() { + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(leaderboard.name, null); + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Could not denote for RaceLog tracking: " + caught.getMessage()); + } + }); + } + + private void denoteForRaceLogTracking(final RaceColumnDTO raceColumn, final FleetDTO fleet) { + final StrippedLeaderboardDTO leaderboard = getSelectedLeaderboard(); + sailingService.denoteForRaceLogTracking(leaderboard.name, raceColumn.getName(), fleet.getName(), new AsyncCallback() { + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(leaderboard.name, raceColumn.getName()); + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Could not denote for RaceLog tracking: " + caught.getMessage()); + } + }); + } + + private void addRaceLogTrackers(final StrippedLeaderboardDTO leaderboard) { + final RaceColumnDTOAndFleetDTOWithNameBasedEquality selectedRCFleet = getSelectedRaceColumnWithFleet(); + if (leaderboard.raceLogTrackersCanBeAdded) { + sailingService.addRaceLogTrackers(leaderboard.name, new AsyncCallback() { + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(leaderboard.name, selectedRCFleet.getA().getName()); + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Failed to add RaceLog tracker: " + caught.getMessage()); + } + }); + } else { + errorReporter.reportError("No RaceLogTracker can be added for any of the RaceLogs in this leaderboard"); + } + } + + private void addRaceLogTracker(final RaceColumnDTO raceColumn, FleetDTO fleet) { + if (fleet.raceLogTrackerCanBeAdded) { + final StrippedLeaderboardDTO leaderboard = getSelectedLeaderboard(); + sailingService.addRaceLogTracker(leaderboard.name, raceColumn.getName(), fleet.getName(), new AsyncCallback() { + @Override + public void onSuccess(Void result) { + loadAndRefreshLeaderboard(leaderboard.name, raceColumn.getName()); + } + + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Failed to add RaceLog trackers: " + caught.getMessage()); + } + }); + } else { + errorReporter.reportError("No RaceLogTracker can be added for the RaceLog of this fleet"); + } + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java new file mode 100644 index 00000000000..886f33253cb --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingEventManagementRaceImagesBarCell.java @@ -0,0 +1,35 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.core.client.GWT; +import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; +import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.gwt.ui.client.shared.components.ImagesBarCell; + +public class RaceLogTrackingEventManagementRaceImagesBarCell extends ImagesBarCell { + public final static String ACTION_ADD_RACELOG_TRACKER = "ACTION_ADD_RACELOG_TRACKER"; + public final static String ACTION_DENOTE_FOR_RACELOG_TRACKING = "ACTION_DENOTE_FOR_RACELOG_TRACKING"; + + private final StringMessages stringMessages; + private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class); + + public RaceLogTrackingEventManagementRaceImagesBarCell(StringMessages stringConstants) { + super(); + this.stringMessages = stringConstants; + } + + @Override + protected Iterable getImageSpecs() { + List result = new ArrayList(); + RaceColumnDTOAndFleetDTOWithNameBasedEquality object = (RaceColumnDTOAndFleetDTOWithNameBasedEquality) getContext().getKey(); + if (object.getB().raceLogTrackerCanBeAdded) { + result.add(new ImageSpec(ACTION_ADD_RACELOG_TRACKER, stringMessages.addRaceLogTracker(), makeImagePrototype(resources.addRaceLogTracker()))); + } + if (! object.getB().raceLogTrackingState.isForTracking()) { + result.add(new ImageSpec(ACTION_DENOTE_FOR_RACELOG_TRACKING, stringMessages.denoteForRaceLogTracking(), makeImagePrototype(resources.denoteForRaceLogTracking()))); + } + return result; + } +} \ No newline at end of file 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 b0ba0bc9de7..888f9c8237f 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 @@ -383,4 +383,6 @@ public interface SailingService extends RemoteService { void addRaceLogTracker(String leaderboardName, String raceColumnName, String fleetName) throws Exception, RaceNotCreatedException; void denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) throws Exception; + + void denoteForRaceLogTracking(String leaderboardName) throws Exception; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index fcd2345e02c..806761affca 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -523,5 +523,7 @@ public interface SailingServiceAsync { void denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback callback); + + void denoteForRaceLogTracking(String leaderboardName, AsyncCallback callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 8da87228d32..53a8b41f02e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -960,7 +960,7 @@ public interface StringMessages extends Messages { String hasSplitFleetContiguousScoring(); String eventOverview(); String addRaceLogTracker(); + String addRaceLogTrackers(); String denoteForRaceLogTracking(); - String raceLogTrackerExists(); - String raceLogTrackingState(); + String raceLogTracking(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index a61222ced79..96407b7e325 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -949,6 +949,6 @@ releaseNotes=News and Release History hasSplitFleetContiguousScoring=Split fleets scored contiguously eventOverview=Event Overview addRaceLogTracker=Add RaceLog Tracker +addRaceLogTrackers=Add RaceLog Trackers denoteForRaceLogTracking=Denote for RaceLog tracking -raceLogTrackerExists=RL-Tracker exists -raceLogTrackingState=RL tracking state \ No newline at end of file +raceLogTracking=RaceLog Tracking \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index a4275db2240..232ccb3ead1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -945,6 +945,6 @@ releaseNotes=Neuigkeiten und Änderungshistorie hasSplitFleetContiguousScoring=Gruppen durchgängig bepunkten eventOverview=Event Übersicht addRaceLogTracker=RaceLog Tracker hinzufügen -denoteForRaceLogTracking=Kennzeichnen für RaceLog-Tracking -raceLogTrackerExists=RL-Tracker vorhanden -raceLogTrackingState=RL Tracking Status \ No newline at end of file +addRaceLogTrackers=RaceLog Tracker hinzufügen +denoteForRaceLogTracking=Für RaceLog Tracking markieren +raceLogTracking=RaceLog Tracking \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/components/ImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/components/ImagesBarCell.java index 1485b968509..86f6d744521 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/components/ImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/components/ImagesBarCell.java @@ -31,6 +31,8 @@ public abstract class ImagesBarCell extends AbstractSafeHtmlCell { */ private final static ImagesBarTemplates imageTemplate = GWT.create(ImagesBarTemplates.class); + private Context context; + protected class ImageSpec { private final AbstractImagePrototype imagePrototype; private final String actionName; @@ -138,9 +140,15 @@ public abstract class ImagesBarCell extends AbstractSafeHtmlCell { } protected abstract Iterable getImageSpecs(); + + protected Context getContext() { + return context; + } @Override protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb) { + this.context = context; + /* * Always do a null check on the value. Cell widgets can pass null to * cells if the underlying data contains a null, or if the data arrives 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 fd4687977f2..b1b6909844d 100755 --- 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 @@ -1973,7 +1973,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S } else { leaderboardDTO.discardThresholds = null; } - leaderboardDTO.raceLogTrackedRacesCouldBeAdded = false; + leaderboardDTO.isDenotedForRaceLogTracking = false; + leaderboardDTO.raceLogTrackersCanBeAdded = false; for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { for (Fleet fleet : raceColumn.getFleets()) { RaceDTO raceDTO = null; @@ -1992,11 +1993,15 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S RaceLog raceLog = raceColumn.getRaceLog(fleet); fleetDTO.raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); - fleetDTO.raceLogTrackerForRaceExists = getService().getRaceTrackerById(raceLog.getId()) != null; + fleetDTO.raceLogTrackerExists = getService().getRaceTrackerById(raceLog.getId()) != null; - if (getRaceLogTrackingAdapter().canRaceBeAdded(getService(), raceColumn, fleet)) { - leaderboardDTO.raceLogTrackedRacesCouldBeAdded = true; - fleetDTO.raceLogTrackedRaceCouldBeAdded = true; + if (getRaceLogTrackingAdapter().isDenotedForRaceLogTracking(getService(), raceColumn, fleet)) { + leaderboardDTO.isDenotedForRaceLogTracking = true; + } + + if (getRaceLogTrackingAdapter().canRaceLogTrackerBeAdded(getService(), raceColumn, fleet)) { + leaderboardDTO.raceLogTrackersCanBeAdded = true; + fleetDTO.raceLogTrackerCanBeAdded = true; } } } @@ -3840,7 +3845,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); RaceLogTrackingAdapter adapter = getRaceLogTrackingAdapter(); - Map> canBeLoaded = adapter.listRacesThatCanBeAdded(getService(), leaderboard); + Map> canBeLoaded = adapter.listRaceLogTrackersThatCanBeAdded(getService(), leaderboard); for (RaceColumn raceColumn : canBeLoaded.keySet()) { if (canBeLoaded.get(raceColumn) != null) { for (Fleet fleet : canBeLoaded.get(raceColumn)) { @@ -3859,4 +3864,10 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S getRaceLogTrackingAdapter().denoteForRaceLogTracking(getService(), leaderboard, raceColumn, fleet, null); } + + @Override + public void denoteForRaceLogTracking(String leaderboardName) throws Exception { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getRaceLogTrackingAdapter().denoteForRaceLogTracking(getService(), leaderboard); + } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/add_racelog_tracker.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/add_racelog_tracker.png index 704b98b021b..fc34656a556 100644 Binary files a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/add_racelog_tracker.png and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/add_racelog_tracker.png differ diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/denote_for_racelog_tracking.png b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/denote_for_racelog_tracking.png index a70e4f91303..7fcfe5674d2 100644 Binary files a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/denote_for_racelog_tracking.png and b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/client/images/denote_for_racelog_tracking.png differ