mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-17 01:31:01 +00:00
new RaceLogTracking tab in AdminConsole
This commit is contained in:
1 parent
ba0587d979
commit
ef1f72b72b
28 files changed
+1014
-491
No files matched your search
+2
-1
@@ -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;
|
||||
|
||||
|
||||
+2
-2
@@ -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() {}
|
||||
|
||||
|
||||
+2
-2
@@ -116,7 +116,7 @@ public class CreateAndTrackWithRaceLogTest {
|
||||
RaceLog raceLog = column.getRaceLog(fleet);
|
||||
|
||||
//before denoting, it is not listed as loadable
|
||||
Map<RaceColumn, Collection<Fleet>> loadable = adapter.listRacesThatCanBeAdded(service, leaderboard);
|
||||
Map<RaceColumn, Collection<Fleet>> 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());
|
||||
|
||||
|
||||
+46
-33
@@ -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<RaceColumn, Collection<Fleet>> listRacesThatCanBeAdded(RacingEventService service,
|
||||
Leaderboard leaderboard);
|
||||
/**
|
||||
* Lists all races for this leaderboards according to the rules in
|
||||
* {@link #canRaceBeAdded(RacingEventService, Leaderboard, RaceColumn, Fleet)}.
|
||||
*/
|
||||
Map<RaceColumn, Collection<Fleet>> 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;
|
||||
}
|
||||
+15
-16
@@ -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<T extends GPSFix> implements GPSFixJsonHandler {
|
||||
private final JsonDeserializer<T> deserializer;
|
||||
private final JsonSerializer<T> serializer;
|
||||
private final JsonDeserializer<T> deserializer;
|
||||
private final JsonSerializer<T> serializer;
|
||||
|
||||
public GPSFixJsonHandlerImpl(JsonDeserializer<T> deserializer,
|
||||
JsonSerializer<T> serializer) {
|
||||
this.deserializer = deserializer;
|
||||
this.serializer = serializer;
|
||||
}
|
||||
public GPSFixJsonHandlerImpl(JsonDeserializer<T> deserializer, JsonSerializer<T> 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);
|
||||
}
|
||||
}
|
||||
+29
-28
@@ -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;
|
||||
}
|
||||
}
|
||||
+196
-193
@@ -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<Competitor, List<DeviceMapping<Competitor>>> competitorMappings = new HashMap<>();
|
||||
private Map<Mark, List<DeviceMapping<Mark>>> markMappings = new HashMap<>();
|
||||
|
||||
|
||||
private Map<DeviceIdentifier, List<DeviceMapping<Mark>>> markMappingsByDevices = new HashMap<>();
|
||||
private Map<DeviceIdentifier, List<DeviceMapping<Competitor>>> 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<Competitor, List<DeviceMapping<Competitor>>> getNewCompetitorMappings() {
|
||||
return new DeviceCompetitorMappingFinder(params.getRaceLog()).analyze();
|
||||
return new DeviceCompetitorMappingFinder(params.getRaceLog()).analyze();
|
||||
}
|
||||
|
||||
|
||||
private Map<Mark, List<DeviceMapping<Mark>>> 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<? extends DeviceMapping<?>> list : competitorMappings.values()) {
|
||||
for (DeviceMapping<?> mapping : list) {
|
||||
if (mapping.getTimeRange().from().before(earliestMapping)) {
|
||||
earliestMapping = mapping.getTimeRange().from();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(markMappings) {
|
||||
for (List<? extends DeviceMapping<?>> 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<? extends DeviceMapping<?>> list : competitorMappings.values()) {
|
||||
for (DeviceMapping<?> mapping : list) {
|
||||
if (mapping.getTimeRange().from().before(earliestMapping)) {
|
||||
earliestMapping = mapping.getTimeRange().from();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (markMappings) {
|
||||
for (List<? extends DeviceMapping<?>> list : markMappings.values()) {
|
||||
for (DeviceMapping<?> mapping : list) {
|
||||
if (mapping.getTimeRange().from().before(earliestMapping)) {
|
||||
earliestMapping = mapping.getTimeRange().from();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trackedRace.setStartOfTrackingReceived(earliestMapping);
|
||||
}
|
||||
|
||||
|
||||
private <ItemT extends WithID, FixT extends GPSFix> boolean hasMappingAlreadyBeenLoaded(
|
||||
DeviceMapping<ItemT> newMapping, List<DeviceMapping<ItemT>> oldMappings) {
|
||||
for (DeviceMapping<ItemT> oldMapping : oldMappings) {
|
||||
if (newMapping.getDevice() == oldMapping.getDevice() &&
|
||||
newMapping.getTimeRange().liesWithin(oldMapping.getTimeRange())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
DeviceMapping<ItemT> newMapping, List<DeviceMapping<ItemT>> oldMappings) {
|
||||
for (DeviceMapping<ItemT> oldMapping : oldMappings) {
|
||||
if (newMapping.getDevice() == oldMapping.getDevice()
|
||||
&& newMapping.getTimeRange().liesWithin(oldMapping.getTimeRange())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private <ItemT extends WithID, FixT extends GPSFix>
|
||||
Map<DeviceIdentifier, List<DeviceMapping<ItemT>>>
|
||||
transformToMappingsByDevice(Map<ItemT, List<DeviceMapping<ItemT>>> mappings) {
|
||||
|
||||
Map<DeviceIdentifier, List<DeviceMapping<ItemT>>> result = new HashMap<>();
|
||||
for (ItemT item : mappings.keySet()) {
|
||||
for (DeviceMapping<ItemT> mapping : mappings.get(item)) {
|
||||
List<DeviceMapping<ItemT>> list = result.get(mapping.getDevice());
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
result.put(mapping.getDevice(), list);
|
||||
}
|
||||
list.add(mapping);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
private <ItemT extends WithID, FixT extends GPSFix> Map<DeviceIdentifier, List<DeviceMapping<ItemT>>> transformToMappingsByDevice(
|
||||
Map<ItemT, List<DeviceMapping<ItemT>>> mappings) {
|
||||
|
||||
Map<DeviceIdentifier, List<DeviceMapping<ItemT>>> result = new HashMap<>();
|
||||
for (ItemT item : mappings.keySet()) {
|
||||
for (DeviceMapping<ItemT> mapping : mappings.get(item)) {
|
||||
List<DeviceMapping<ItemT>> 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<Mark, List<DeviceMapping<Mark>>> newMappings = getNewMarkMappings();
|
||||
|
||||
if (loadIfNotCovered) {
|
||||
for (Mark mark : newMappings.keySet()) {
|
||||
DynamicGPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
|
||||
List<DeviceMapping<Mark>> oldMappings = markMappings.get(mark);
|
||||
|
||||
for (DeviceMapping<Mark> 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<Mark, List<DeviceMapping<Mark>>> newMappings = getNewMarkMappings();
|
||||
|
||||
if (loadIfNotCovered) {
|
||||
for (Mark mark : newMappings.keySet()) {
|
||||
DynamicGPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
|
||||
List<DeviceMapping<Mark>> oldMappings = markMappings.get(mark);
|
||||
|
||||
for (DeviceMapping<Mark> 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<Competitor, List<DeviceMapping<Competitor>>> newMappings = getNewCompetitorMappings();
|
||||
|
||||
if (loadIfNotCovered) {
|
||||
for (Competitor competitor : newMappings.keySet()) {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = trackedRace.getTrack(competitor);
|
||||
List<DeviceMapping<Competitor>> oldMappings = competitorMappings.get(competitor);
|
||||
|
||||
for (DeviceMapping<Competitor> 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<Competitor, List<DeviceMapping<Competitor>>> newMappings = getNewCompetitorMappings();
|
||||
|
||||
if (loadIfNotCovered) {
|
||||
for (Competitor competitor : newMappings.keySet()) {
|
||||
DynamicGPSFixTrack<Competitor, GPSFixMoving> track = trackedRace.getTrack(competitor);
|
||||
List<DeviceMapping<Competitor>> oldMappings = competitorMappings.get(competitor);
|
||||
|
||||
for (DeviceMapping<Competitor> 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<String, BoatClass> 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<Competitor> competitors = new RegisteredCompetitorsAnalyzer(raceLog).analyze();
|
||||
final RaceDefinition raceDef = new RaceDefinitionImpl(raceInfo.getA(), course, boatClass, competitors);
|
||||
|
||||
Iterable<Sideline> sidelines = Collections.<Sideline>emptyList();
|
||||
|
||||
//set race definition, so race is linked to leaderboard automatically
|
||||
|
||||
Iterable<Sideline> sidelines = Collections.<Sideline> 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<Mark> mapping : markMappingsByDevices.get(device)) {
|
||||
Mark mark = mapping.getMappedTo();
|
||||
if (mapping.getTimeRange().includes(timePoint)) {
|
||||
trackedRace.recordFix(mark, fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (competitorMappingsByDevices.get(device) != null) {
|
||||
for (DeviceMapping<Competitor> 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<Mark> mapping : markMappingsByDevices.get(device)) {
|
||||
Mark mark = mapping.getMappedTo();
|
||||
if (mapping.getTimeRange().includes(timePoint)) {
|
||||
trackedRace.recordFix(mark, fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (competitorMappingsByDevices.get(device) != null) {
|
||||
for (DeviceMapping<Competitor> 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+150
-70
@@ -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<RaceColumn, Collection<Fleet>> findInLeaderboard(Leaderboard leaderboard,
|
||||
Function<Pair<RaceColumn, Fleet>, Boolean> includeInResult) {
|
||||
Function<Pair<RaceColumn, Fleet>, Boolean> includeInResult) {
|
||||
Map<RaceColumn, Collection<Fleet>> result = new HashMap<>();
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
if (includeInResult.perform(new Pair<>(raceColumn, fleet))) {
|
||||
Collection<Fleet> coll = result.get(raceColumn);
|
||||
if (includeInResult.perform(new Pair<>(raceColumn, fleet))) {
|
||||
Collection<Fleet> coll = result.get(raceColumn);
|
||||
if (coll == null) {
|
||||
coll = new ArrayList<>();
|
||||
result.put(raceColumn, coll);
|
||||
}
|
||||
coll.add(fleet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<RaceColumn, Collection<Fleet>> listRacesThatCanBeAdded(final RacingEventService service,
|
||||
Leaderboard leaderboard) {
|
||||
return findInLeaderboard(leaderboard, new Function<Util.Pair<RaceColumn,Fleet>, Boolean>() {
|
||||
@Override
|
||||
public Boolean perform(Pair<RaceColumn, Fleet> in) {
|
||||
return canRaceBeAdded(service, in.getA(), in.getB());
|
||||
}
|
||||
});
|
||||
public Map<RaceColumn, Collection<Fleet>> listRaceLogTrackersThatCanBeAdded(final RacingEventService service,
|
||||
Leaderboard leaderboard) {
|
||||
return findInLeaderboard(leaderboard, new Function<Util.Pair<RaceColumn, Fleet>, Boolean>() {
|
||||
@Override
|
||||
public Boolean perform(Pair<RaceColumn, Fleet> 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();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+14
-13
@@ -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<Triple<DeviceIdentifier, Serializable, List<GPSFix>>, Void> {
|
||||
public class RecordFixesPostServlet extends
|
||||
AbstractJsonPostServlet<Triple<DeviceIdentifier, Serializable, List<GPSFix>>, Void> {
|
||||
private static final long serialVersionUID = 2778739335260621119L;
|
||||
private DeviceAndSessionIdentifierWithGPSFixesDeserializer deserializer;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
TypeBasedServiceFinder<GPSFixJsonHandler> fixServiceFinder =
|
||||
getServiceFinderFactory().createServiceFinder(GPSFixJsonHandler.class);
|
||||
TypeBasedServiceFinder<DeviceIdentifierJsonHandler> deviceServiceFinder =
|
||||
getServiceFinderFactory().createServiceFinder(DeviceIdentifierJsonHandler.class);
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
TypeBasedServiceFinder<GPSFixJsonHandler> fixServiceFinder = getServiceFinderFactory().createServiceFinder(
|
||||
GPSFixJsonHandler.class);
|
||||
TypeBasedServiceFinder<DeviceIdentifierJsonHandler> deviceServiceFinder = getServiceFinderFactory()
|
||||
.createServiceFinder(DeviceIdentifierJsonHandler.class);
|
||||
deserializer = new DeviceAndSessionIdentifierWithGPSFixesDeserializer(fixServiceFinder, deviceServiceFinder);
|
||||
}
|
||||
|
||||
@@ -47,14 +48,14 @@ public class RecordFixesPostServlet extends AbstractJsonPostServlet<Triple<Devic
|
||||
public Void process(Map<String, String> parameterValues,
|
||||
Triple<DeviceIdentifier, Serializable, List<GPSFix>> 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<GPSFix> fixes = domainObject.getC();
|
||||
|
||||
|
||||
for (GPSFix fix : fixes) {
|
||||
getService().getGPSFixStore().storeFix(device, fix);
|
||||
getService().getGPSFixStore().storeFix(device, fix);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
-1
@@ -19,7 +19,6 @@ public class RaceLogTrackingStateAnalyzer extends RaceLogAnalyzer<RaceLogTrackin
|
||||
if (event instanceof StartTrackingEvent) {
|
||||
return RaceLogTrackingState.TRACKING;
|
||||
} else if (event instanceof DenoteForTrackingEvent) {
|
||||
System.out.println(RaceLogTrackingState.AWAITING_RACE_DEFINITION);
|
||||
return RaceLogTrackingState.AWAITING_RACE_DEFINITION;
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -97,6 +97,12 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
|
||||
createSwissTimingRacePanel.setSize("90%", "90%");
|
||||
addScrollableTab(tabPanel, createSwissTimingRacePanel, stringMessages.createSwissTimingRace());
|
||||
|
||||
final RaceLogTrackingEventManagementPanel raceLogTrackingEventManagementPanel = new RaceLogTrackingEventManagementPanel(
|
||||
sailingService, this, this, stringMessages);
|
||||
raceLogTrackingEventManagementPanel.setSize("90%", "90%");
|
||||
addScrollableTab(tabPanel, raceLogTrackingEventManagementPanel, stringMessages.raceLogTracking());
|
||||
regattaDisplayers.add(raceLogTrackingEventManagementPanel);
|
||||
|
||||
IgtimiAccountsPanel igtimiAccountsPanel = new IgtimiAccountsPanel(sailingService, this, stringMessages);
|
||||
igtimiAccountsPanel.ensureDebugId("IgtimiAccounts");
|
||||
igtimiAccountsPanel.setSize("90%", "90%");
|
||||
@@ -178,6 +184,9 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt
|
||||
if (competitorPanel.isVisible()) {
|
||||
competitorPanel.refreshCompetitorList();
|
||||
}
|
||||
if (raceLogTrackingEventManagementPanel.isVisible()) {
|
||||
raceLogTrackingEventManagementPanel.loadLeaderboards();
|
||||
}
|
||||
}
|
||||
});
|
||||
fillRegattas();
|
||||
|
||||
+9
-9
@@ -1,6 +1,6 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.text.shared.SafeHtmlRenderer;
|
||||
@@ -14,7 +14,6 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
|
||||
public static final String ACTION_EDIT = "ACTION_EDIT";
|
||||
public static final String ACTION_CONFIGURE_URL = "ACTION_CONFIGURE_URL";
|
||||
public static final String ACTION_EXPORT_XML = "ACTION_EXPORT_XML";
|
||||
public static final String ACTION_ADD_RACELOG_TRACKER = "ACTION_ADD_RACELOG_TRACKER";
|
||||
private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
@@ -30,12 +29,13 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
|
||||
|
||||
@Override
|
||||
protected Iterable<ImageSpec> 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<ImageSpec> result = new ArrayList<ImageSpec>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
+16
-95
@@ -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<RaceColumnDTO, FleetDTO> {
|
||||
public static class RaceColumnDTOAndFleetDTOWithNameBasedEquality extends Pair<RaceColumnDTO, FleetDTO> {
|
||||
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<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceLogTrackerExistsColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@Override
|
||||
public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) {
|
||||
boolean trackerExists = raceColumnAndFleetName.getB().raceLogTrackerForRaceExists;
|
||||
return trackerExists ? "X" : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceLogTrackingStateColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@Override
|
||||
public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnAndFleetName) {
|
||||
RaceLogTrackingState state = raceColumnAndFleetName.getB().raceLogTrackingState;
|
||||
return state.isForTracking() ? state.name() : "";
|
||||
}
|
||||
};
|
||||
|
||||
ImagesBarColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality, LeaderboardRaceConfigImagesBarCell> raceActionColumn =
|
||||
new ImagesBarColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality, LeaderboardRaceConfigImagesBarCell>(
|
||||
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<RaceLogDTO>() {
|
||||
@Override
|
||||
@@ -927,12 +902,12 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
|
||||
+ selectedRaceColumnName + " in leaderboard " + selectedLeaderboardName + ": "
|
||||
+ t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onSuccess(Map<String, RegattaAndRaceIdentifier> 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<RaceColumnDTO> 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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
-4
@@ -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;
|
||||
}
|
||||
}
|
||||
+41
@@ -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<String> renderer, StringMessages stringConstants) {
|
||||
super();
|
||||
this.stringMessages = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<ImageSpec> getImageSpecs() {
|
||||
ArrayList<ImageSpec> result = new ArrayList<ImageSpec>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+401
@@ -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<StrippedLeaderboardDTO> leaderboardList;
|
||||
private final ListDataProvider<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceColumnAndFleetList;
|
||||
private final CellTable<StrippedLeaderboardDTO> leaderboardTable;
|
||||
private final CellTable<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceColumnTable;
|
||||
private final CaptionPanel selectedLeaderBoardPanel;
|
||||
private final CaptionPanel trackedRacesCaptionPanel;
|
||||
private LabeledAbstractFilterablePanel<StrippedLeaderboardDTO> filterLeaderboardPanel;
|
||||
final SingleSelectionModel<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceColumnTableSelectionModel;
|
||||
private List<StrippedLeaderboardDTO> availableLeaderboardList;
|
||||
private final MultiSelectionModel<StrippedLeaderboardDTO> leaderboardSelectionModel;
|
||||
|
||||
public RaceLogTrackingEventManagementPanel(SailingServiceAsync sailingService, RegattaRefresher regattaRefresher,
|
||||
ErrorReporter errorReporter, StringMessages stringMessages) {
|
||||
super(sailingService, regattaRefresher, errorReporter, new RaceSelectionModel(), stringMessages);
|
||||
leaderboardList = new ListDataProvider<StrippedLeaderboardDTO>();
|
||||
raceColumnAndFleetList = new ListDataProvider<RaceColumnDTOAndFleetDTOWithNameBasedEquality>();
|
||||
this.errorReporter = errorReporter;
|
||||
this.availableLeaderboardList = new ArrayList<StrippedLeaderboardDTO>();
|
||||
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<StrippedLeaderboardDTO>(/* pageSize */10000, tableRes);
|
||||
filterLeaderboardPanel = new LabeledAbstractFilterablePanel<StrippedLeaderboardDTO>(lblFilterEvents, availableLeaderboardList, leaderboardTable, leaderboardList) {
|
||||
@Override
|
||||
public List<String> getSearchableStrings(StrippedLeaderboardDTO t) {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
strings.add(t.name);
|
||||
strings.add(t.displayName);
|
||||
return strings;
|
||||
}
|
||||
};
|
||||
leaderboardConfigControlsPanel.add(filterLeaderboardPanel);
|
||||
leaderboardsPanel.add(leaderboardConfigControlsPanel);
|
||||
ListHandler<StrippedLeaderboardDTO> leaderboardColumnListHandler = new ListHandler<StrippedLeaderboardDTO>(
|
||||
leaderboardList.getList());
|
||||
|
||||
TextColumn<StrippedLeaderboardDTO> leaderboardNameColumn = new TextColumn<StrippedLeaderboardDTO>() {
|
||||
@Override
|
||||
public String getValue(StrippedLeaderboardDTO leaderboard) {
|
||||
return leaderboard.name;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<StrippedLeaderboardDTO> leaderboardDisplayNameColumn = new TextColumn<StrippedLeaderboardDTO>() {
|
||||
@Override
|
||||
public String getValue(StrippedLeaderboardDTO leaderboard) {
|
||||
return leaderboard.getDisplayName() != null ? leaderboard.getDisplayName() : "";
|
||||
}
|
||||
};
|
||||
|
||||
ImagesBarColumn<StrippedLeaderboardDTO, RaceLogTrackingEventManagementImagesBarCell> leaderboardActionColumn =
|
||||
new ImagesBarColumn<StrippedLeaderboardDTO, RaceLogTrackingEventManagementImagesBarCell>(
|
||||
new RaceLogTrackingEventManagementImagesBarCell(stringMessages));
|
||||
leaderboardActionColumn.setFieldUpdater(new FieldUpdater<StrippedLeaderboardDTO, String>() {
|
||||
@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<StrippedLeaderboardDTO>();
|
||||
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<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceNameColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@Override
|
||||
public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) {
|
||||
return object.getA().getName();
|
||||
}
|
||||
};
|
||||
TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality> fleetNameColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@Override
|
||||
public String getValue(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) {
|
||||
return object.getB().getName();
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality> raceLogTrackingStateColumn = new TextColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality>() {
|
||||
@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<RaceColumnDTOAndFleetDTOWithNameBasedEquality, RaceLogTrackingEventManagementRaceImagesBarCell> raceActionColumn =
|
||||
new ImagesBarColumn<RaceColumnDTOAndFleetDTOWithNameBasedEquality, RaceLogTrackingEventManagementRaceImagesBarCell>(
|
||||
new RaceLogTrackingEventManagementRaceImagesBarCell(stringMessages));
|
||||
raceActionColumn.setFieldUpdater(new FieldUpdater<RaceColumnDTOAndFleetDTOWithNameBasedEquality, String>() {
|
||||
@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<RaceColumnDTOAndFleetDTOWithNameBasedEquality>(/* 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<RaceColumnDTOAndFleetDTOWithNameBasedEquality>();
|
||||
raceColumnTable.setSelectionModel(raceColumnTableSelectionModel);
|
||||
vPanel.add(raceColumnTable);
|
||||
|
||||
HorizontalPanel selectedLeaderboardRaceButtonPanel = new HorizontalPanel();
|
||||
selectedLeaderboardRaceButtonPanel.setSpacing(5);
|
||||
vPanel.add(selectedLeaderboardRaceButtonPanel);
|
||||
|
||||
loadLeaderboards();
|
||||
}
|
||||
|
||||
public void loadLeaderboards() {
|
||||
sailingService.getLeaderboards(new AsyncCallback<List<StrippedLeaderboardDTO>>() {
|
||||
@Override
|
||||
public void onSuccess(List<StrippedLeaderboardDTO> 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 <code>null</code>, 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<StrippedLeaderboardDTO>() {
|
||||
@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<StrippedLeaderboardDTO> 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<RaceColumnDTOAndFleetDTOWithNameBasedEquality> 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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@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<Void>() {
|
||||
@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");
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -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<ImageSpec> getImageSpecs() {
|
||||
List<ImageSpec> result = new ArrayList<ImageSpec>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
+2
@@ -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;
|
||||
}
|
||||
+2
@@ -523,5 +523,7 @@ public interface SailingServiceAsync {
|
||||
void denoteForRaceLogTracking(String leaderboardName,
|
||||
String raceColumnName, String fleetName,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void denoteForRaceLogTracking(String leaderboardName, AsyncCallback<Void> callback);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
+2
-2
@@ -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
|
||||
raceLogTracking=RaceLog Tracking
|
||||
+3
-3
@@ -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
|
||||
addRaceLogTrackers=RaceLog Tracker hinzufügen
|
||||
denoteForRaceLogTracking=Für RaceLog Tracking markieren
|
||||
raceLogTracking=RaceLog Tracking
|
||||
+8
@@ -31,6 +31,8 @@ public abstract class ImagesBarCell extends AbstractSafeHtmlCell<String> {
|
||||
*/
|
||||
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<String> {
|
||||
}
|
||||
|
||||
protected abstract Iterable<ImageSpec> 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
|
||||
|
||||
+17
-6
@@ -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<RaceColumn, Collection<Fleet>> canBeLoaded = adapter.listRacesThatCanBeAdded(getService(), leaderboard);
|
||||
Map<RaceColumn, Collection<Fleet>> 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);
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 499 B After Width: | Height: | Size: 428 B |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 417 B |
Reference in new issue
Block a user