Merge branch 'master' into bug2729

This commit is contained in:
Axel Uhl committed 2015-03-26 16:36:49 +01:00
commit ce4fabbaf2
28 files changed
+567 -310

No files matched your search

@@ -277,7 +277,8 @@ public class IgtimiConnectionImpl implements IgtimiConnection {
TimePoint endOfWindow = new MillisecondsTimePoint(0);
for (DynamicTrackedRace trackedRace : trackedRaces) {
startOfWindow = Collections.min(Arrays.asList(startOfWindow, IgtimiWindTracker.getReceivingStartTime(trackedRace)));
endOfWindow = Collections.max(Arrays.asList(endOfWindow, IgtimiWindTracker.getReceivingEndTime(trackedRace)));
final TimePoint receivingEndTime = IgtimiWindTracker.getReceivingEndTime(trackedRace);
endOfWindow = Collections.max(Arrays.asList(endOfWindow, receivingEndTime==null?MillisecondsTimePoint.now():receivingEndTime));
}
Iterable<DataAccessWindow> daws = getDataAccessWindows(Permission.read, startOfWindow, endOfWindow, /* find all deviceSerialNumbers for window */ null);
logger.info("Found "+Util.size(daws)+" data access windows. Analyzing which ones contain wind data...");
@@ -28,6 +28,7 @@ import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.WriteResult;
import com.mongodb.util.JSON;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl;
@@ -172,6 +173,7 @@ import com.sap.sse.common.TimeRange;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.RGBColor;
import com.sap.sse.common.impl.TimeRangeImpl;
@@ -1604,7 +1606,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
BasicDBObject query = new BasicDBObject();
query.put(FieldNames.REGATTA_LOG_IDENTIFIER_TYPE.name(), identifier.getIdentifierType());
query.put(FieldNames.REGATTA_LOG_IDENTIFIER_NAME.name(), identifier.getName());
loadRegattaLogEvents(result, query);
loadRegattaLogEvents(result, query, identifier);
} catch (Throwable t) {
// something went wrong during DB access; report, then use empty new regatta log
logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load recorded regatta log data. Check MongoDB settings.");
@@ -1613,11 +1615,11 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return result;
}
private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query) {
private void loadRegattaLogEvents(RegattaLog targetRegattaLog, BasicDBObject query, RegattaLikeIdentifier regattaLogIdentifier) {
DBCollection collection = database.getCollection(CollectionNames.REGATTA_LOGS.name());
for (DBObject o : collection.find(query)) {
try {
RegattaLogEvent event = loadRegattaLogEvent((DBObject) o.get(FieldNames.REGATTA_LOG_EVENT.name()));
RegattaLogEvent event = loadRegattaLogEvent(o, regattaLogIdentifier);
if (event != null) {
targetRegattaLog.load(event);
}
@@ -1627,7 +1629,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
}
public RegattaLogEvent loadRegattaLogEvent(DBObject dbObject) {
private RegattaLogEvent loadRegattaLogEvent(DBObject o, RegattaLikeIdentifier regattaLogIdentifier) {
DBObject dbObject = (DBObject) o.get(FieldNames.REGATTA_LOG_EVENT.name());
TimePoint logicalTimePoint = loadTimePoint(dbObject);
TimePoint createdAt = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_EVENT_CREATED_AT);
Serializable id = (Serializable) dbObject.get(FieldNames.REGATTA_LOG_EVENT_ID.name());
@@ -1638,9 +1641,9 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
//CloseOpenEnded, DeviceCompMapping, DeviceMarkMapping, RegisterComp, Revoke
String eventClass = (String) dbObject.get(FieldNames.REGATTA_LOG_EVENT_CLASS.name());
if (eventClass.equals(RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName())) {
return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject);
return loadRegattaLogDeviceCompetitorMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o);
} else if (eventClass.equals(RegattaLogDeviceMarkMappingEvent.class.getSimpleName())) {
return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject);
return loadRegattaLogDeviceMarkMappingEvent(createdAt, author, logicalTimePoint, id, dbObject, regattaLogIdentifier, o);
} else if (eventClass.equals(RegattaLogCloseOpenEndedDeviceMappingEvent.class.getSimpleName())) {
return loadRegattaLogCloseOpenEndedDeviceMappingEvent(createdAt, author, logicalTimePoint, id, dbObject);
} else if (eventClass.equals(RegattaLogRegisterCompetitorEvent.class.getSimpleName())) {
@@ -1680,7 +1683,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
private RegattaLogDeviceMarkMappingEvent loadRegattaLogDeviceMarkMappingEvent(TimePoint createdAt, AbstractLogEventAuthor author,
TimePoint logicalTimePoint, Serializable id, DBObject dbObject) {
TimePoint logicalTimePoint, Serializable id, DBObject dbObject, RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
@@ -1691,13 +1694,57 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
//have to load complete mark, as no order is guaranteed for loading of racelog events
Mark mappedTo = loadMark((DBObject) dbObject.get(FieldNames.MARK.name()));
TimePoint from = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_TO);
return new RegattaLogDeviceMarkMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to);
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, FieldNames.RACE_LOG_FROM, FieldNames.REGATTA_LOG_TO, FieldNames.RACE_LOG_TO);
final TimePoint from = times.getA();
final TimePoint to = times.getB();
final RegattaLogDeviceMarkMappingEventImpl result = new RegattaLogDeviceMarkMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to);
final boolean needsMigration = times.getC();
if (needsMigration) {
// remove old version of mapping event
WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject);
assert removeResult.getN() == 1;
// and then insert using the fixed storage implementation
new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result);
}
return result;
}
/**
* Loads a from and a to time point from <code>fromField</code> and <code>toField</code> of <code>dbObject</code>.
* If the <code>fromField</code> is not found, the <code>fromFieldDeprecated</code> is attempted. If found, migration
* is deemed necessary, expressed by returning <code>true</code> in the {@link Triple#getC()} component of the result.
* Same for the to-field.
*
* @return the from-time in {@link Triple#getA()}, the to-time in {@link Triple#getB()} and whether or not migration is
* necessary because a value was only found in a deprecated field in {@link Triple#getC()}.
*/
private Triple<TimePoint, TimePoint, Boolean> loadFromToTimePoint(final DBObject dbObject, FieldNames fromField, FieldNames fromFieldDeprecated,
FieldNames toField, FieldNames toFieldDeprecated) {
boolean needsMigration = false;
TimePoint from = loadTimePoint(dbObject, fromField);
if (from == null) {
// see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM
// If such a case is found here, migrate the record.
from = loadTimePoint(dbObject, fromFieldDeprecated);
if (from != null) {
needsMigration = true;
}
}
TimePoint to = loadTimePoint(dbObject, toField);
if (to == null) {
// see bug 2733: erroneously, some records before the fix were written using RACE_LOG_FROM instead of REGATTA_LOG_FROM
// If such a case is found here, migrate the record.
to = loadTimePoint(dbObject, toFieldDeprecated);
if (to != null) {
needsMigration = true;
}
}
return new Triple<>(from, to, needsMigration);
}
private RegattaLogDeviceCompetitorMappingEvent loadRegattaLogDeviceCompetitorMappingEvent(TimePoint createdAt,
AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, DBObject dbObject) {
AbstractLogEventAuthor author, TimePoint logicalTimePoint, Serializable id, final DBObject dbObject,
RegattaLikeIdentifier regattaLogIdentifier, DBObject outerDBObject) {
DeviceIdentifier device = null;
try {
device = loadDeviceId(deviceIdentifierServiceFinder,
@@ -1708,9 +1755,19 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
Competitor mappedTo = baseDomainFactory.getExistingCompetitorById(
(Serializable) dbObject.get(FieldNames.COMPETITOR_ID.name()));
TimePoint from = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM);
TimePoint to = loadTimePoint(dbObject, FieldNames.REGATTA_LOG_TO);
return new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to);
Triple<TimePoint, TimePoint, Boolean> times = loadFromToTimePoint(dbObject, FieldNames.REGATTA_LOG_FROM, FieldNames.RACE_LOG_FROM, FieldNames.REGATTA_LOG_TO, FieldNames.RACE_LOG_TO);
final TimePoint from = times.getA();
final TimePoint to = times.getB();
final boolean needsMigration = times.getC();
final RegattaLogDeviceCompetitorMappingEventImpl result = new RegattaLogDeviceCompetitorMappingEventImpl(createdAt, author, logicalTimePoint, id, mappedTo, device, from, to);
if (needsMigration) {
// remove old version of mapping event
WriteResult removeResult = database.getCollection(CollectionNames.REGATTA_LOGS.name()).remove(outerDBObject);
assert removeResult.getN() == 1;
// and then insert using the fixed storage implementation
new MongoObjectFactoryImpl(database, serviceFinderFactory).storeRegattaLogEvent(regattaLogIdentifier, result);
}
return result;
}
/**
@@ -899,17 +899,17 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
return result;
}
private void storeDeviceMappingEvent(DeviceMappingEvent<?, ?> event, DBObject result) {
private void storeDeviceMappingEvent(DeviceMappingEvent<?, ?> event, DBObject result, FieldNames fromField, FieldNames toField) {
try {
result.put(FieldNames.DEVICE_ID.name(), storeDeviceId(deviceIdentifierServiceFinder, event.getDevice()));
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not store device identifier for mappng event", e);
}
if (event.getFrom() != null) {
storeTimePoint(event.getFrom(), result, FieldNames.RACE_LOG_FROM);
storeTimePoint(event.getFrom(), result, fromField);
}
if (event.getTo() != null) {
storeTimePoint(event.getTo(), result, FieldNames.RACE_LOG_TO);
storeTimePoint(event.getTo(), result, toField);
}
}
@@ -917,7 +917,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBObject result = new BasicDBObject();
storeRaceLogEventProperties(event, result);
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceCompetitorMappingEvent.class.getSimpleName());
storeDeviceMappingEvent(event, result);
storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO);
result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId());
return result;
}
@@ -926,7 +926,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
DBObject result = new BasicDBObject();
storeRaceLogEventProperties(event, result);
result.put(FieldNames.RACE_LOG_EVENT_CLASS.name(), RaceLogDeviceMarkMappingEvent.class.getSimpleName());
storeDeviceMappingEvent(event, result);
storeDeviceMappingEvent(event, result, FieldNames.RACE_LOG_FROM, FieldNames.RACE_LOG_TO);
result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo()));
return result;
}
@@ -1307,7 +1307,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceCompetitorMappingEvent event) {
DBObject result = createBasicRegattaLogEventDBObject(event);
result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceCompetitorMappingEvent.class.getSimpleName());
storeDeviceMappingEvent(event, result);
storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO);
result.put(FieldNames.COMPETITOR_ID.name(), event.getMappedTo().getId());
storeRegattaLogEvent(regattaLikeId, result);
}
@@ -1315,7 +1315,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
public void storeRegattaLogEvent(RegattaLikeIdentifier regattaLikeId, RegattaLogDeviceMarkMappingEvent event) {
DBObject result = createBasicRegattaLogEventDBObject(event);
result.put(FieldNames.REGATTA_LOG_EVENT_CLASS.name(), RegattaLogDeviceMarkMappingEvent.class.getSimpleName());
storeDeviceMappingEvent(event, result);
storeDeviceMappingEvent(event, result, FieldNames.REGATTA_LOG_FROM, FieldNames.REGATTA_LOG_TO);
result.put(FieldNames.MARK.name(), storeMark(event.getMappedTo()));
storeRegattaLogEvent(regattaLikeId, result);
}
@@ -80,14 +80,15 @@ public class MongoGPSFixStoreImpl implements MongoGPSFixStore {
private <FixT extends GPSFix> void loadTrack(DynamicGPSFixTrack<?, FixT> track, DeviceIdentifier device,
TimePoint from, TimePoint to, boolean inclusive) throws NoCorrespondingServiceRegisteredException,
TransformationException {
long fromMillis = from.asMillis() - (inclusive ? 1 : 0);
long toMillis = to.asMillis() + (inclusive ? 1 : 0);
Object dbDeviceId = MongoObjectFactoryImpl.storeDeviceId(deviceServiceFinder, device);
DBObject query = QueryBuilder.start(FieldNames.DEVICE_ID.name()).is(dbDeviceId)
.and(FieldNames.TIME_AS_MILLIS.name()).greaterThan(fromMillis)
.and(FieldNames.TIME_AS_MILLIS.name()).lessThan(toMillis).get();
final QueryBuilder queryBuilder = QueryBuilder.start(FieldNames.DEVICE_ID.name()).is(dbDeviceId)
.and(FieldNames.TIME_AS_MILLIS.name());
if (inclusive) {
queryBuilder.greaterThanEquals(from.asMillis()).and(FieldNames.TIME_AS_MILLIS.name()).lessThanEquals(to.asMillis());
} else {
queryBuilder.greaterThan(from.asMillis()).and(FieldNames.TIME_AS_MILLIS.name()).lessThan(to.asMillis());
}
DBObject query = queryBuilder.get();
DBCursor result = fixesCollection.find(query);
for (DBObject fixObject : result) {
@@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -100,8 +101,8 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
private final DynamicTrackedRegatta regatta;
private final Map<AbstractLog<?, ?>, Object> visitors = new HashMap<AbstractLog<?, ?>, Object>();
private Map<Competitor, List<DeviceMapping<Competitor>>> competitorMappings = new HashMap<>();
private Map<Mark, List<DeviceMapping<Mark>>> markMappings = new HashMap<>();
private ConcurrentHashMap<Competitor, List<DeviceMapping<Competitor>>> competitorMappings = new ConcurrentHashMap<>();
private ConcurrentHashMap<Mark, List<DeviceMapping<Mark>>> markMappings = new ConcurrentHashMap<>();
private Map<DeviceIdentifier, List<DeviceMapping<Mark>>> markMappingsByDevices = new HashMap<>();
private Map<DeviceIdentifier, List<DeviceMapping<Competitor>>> competitorMappingsByDevices = new HashMap<>();
@@ -244,28 +245,24 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
TimePoint earliestMappingStart = new MillisecondsTimePoint(Long.MAX_VALUE);
TimePoint latestMappingEnd = new MillisecondsTimePoint(Long.MIN_VALUE);
synchronized (competitorMappings) {
for (List<? extends DeviceMapping<?>> list : competitorMappings.values()) {
for (DeviceMapping<?> mapping : list) {
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
earliestMappingStart = mapping.getTimeRange().from();
}
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
latestMappingEnd = mapping.getTimeRange().to();
}
for (List<? extends DeviceMapping<?>> list : competitorMappings.values()) {
for (DeviceMapping<?> mapping : list) {
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
earliestMappingStart = mapping.getTimeRange().from();
}
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
latestMappingEnd = mapping.getTimeRange().to();
}
}
}
synchronized (markMappings) {
for (List<? extends DeviceMapping<?>> list : markMappings.values()) {
for (DeviceMapping<?> mapping : list) {
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
earliestMappingStart = mapping.getTimeRange().from();
}
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
latestMappingEnd = mapping.getTimeRange().to();
}
for (List<? extends DeviceMapping<?>> list : markMappings.values()) {
for (DeviceMapping<?> mapping : list) {
if (mapping.getTimeRange().from().before(earliestMappingStart)) {
earliestMappingStart = mapping.getTimeRange().from();
}
if (mapping.getTimeRange().to().after(latestMappingEnd)) {
latestMappingEnd = mapping.getTimeRange().to();
}
}
}
@@ -308,37 +305,34 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
private void updateMarkMappings(boolean loadIfNotCovered) {
// TODO remove fixes, if mappings have been removed
// check if there are new time ranges not covered so far
Map<Mark, List<DeviceMapping<Mark>>> newMappings = getNewMarkMappings();
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);
if (loadIfNotCovered) {
for (Mark mark : newMappings.keySet()) {
DynamicGPSFixTrack<Mark, GPSFix> track = trackedRace.getOrCreateTrack(mark);
List<DeviceMapping<Mark>> oldMappings = markMappings.get(mark);
if (oldMappings != null) {
for (DeviceMapping<Mark> newMapping : newMappings.get(mark)) {
if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) {
try {
gpsFixStore.loadMarkTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load mark track " + newMapping.getMappedTo());
}
if (oldMappings != null) {
for (DeviceMapping<Mark> newMapping : newMappings.get(mark)) {
if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) {
try {
gpsFixStore.loadMarkTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load mark track " + newMapping.getMappedTo());
}
}
}
}
}
markMappings.clear();
markMappings.putAll(newMappings);
markMappingsByDevices.clear();
markMappingsByDevices.putAll(transformToMappingsByDevice(markMappings));
}
markMappings.clear();
markMappings.putAll(newMappings);
markMappingsByDevices.clear();
markMappingsByDevices.putAll(transformToMappingsByDevice(markMappings));
updateStartAndEndOfTracking();
}
@@ -359,40 +353,39 @@ public class RaceLogRaceTracker implements RaceTracker, GPSFixReceivedListener {
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();
// 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);
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)) {
try {
gpsFixStore.loadCompetitorTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load competitor track " + newMapping.getMappedTo());
}
for (DeviceMapping<Competitor> newMapping : newMappings.get(competitor)) {
if (!hasMappingAlreadyBeenLoaded(newMapping, oldMappings)) {
try {
gpsFixStore.loadCompetitorTrack(track, newMapping);
} catch (TransformationException | NoCorrespondingServiceRegisteredException e) {
logger.log(Level.WARNING, "Could not load competitor track " + newMapping.getMappedTo());
}
}
}
}
competitorMappings.clear();
competitorMappings.putAll(newMappings);
competitorMappingsByDevices.clear();
competitorMappingsByDevices.putAll(transformToMappingsByDevice(competitorMappings));
}
competitorMappings.clear();
competitorMappings.putAll(newMappings);
competitorMappingsByDevices.clear();
competitorMappingsByDevices.putAll(transformToMappingsByDevice(competitorMappings));
updateStartAndEndOfTracking();
}
private void onStartTrackingEvent(RaceLogStartTrackingEvent event) {
if (trackedRace == null)
if (trackedRace == null) {
startTracking(event);
}
}
private void onCourseDesignChangedEvent(RaceLogCourseDesignChangedEvent event) {
@@ -129,4 +129,10 @@ public class TimeRangeTest {
assertEquals(0, one.timeDifference(new MillisecondsTimePoint(7)).asMillis());
assertEquals(2, one.timeDifference(new MillisecondsTimePoint(12)).asMillis());
}
@Test
public void testEndOfTime() {
assertTrue(TimePoint.EndOfTime.after(TimePoint.BeginningOfTime));
assertTrue(TimePoint.EndOfTime.after(MillisecondsTimePoint.now()));
}
}
@@ -117,7 +117,7 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor {
final Distance result;
final Distance preResult = getDistanceTraveled(timePoint);
final Waypoint from = getLeg().getFrom();
if (from == getTrackedRace().getRace().getCourse().getFirstWaypoint()) {
if (preResult != null && from == getTrackedRace().getRace().getCourse().getFirstWaypoint()) {
result = preResult.add(getTrackedRace().getAdditionalGateStartDistance(getCompetitor(), timePoint));
} else {
result = preResult;
@@ -46,6 +46,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.shared.controls.SelectionCheckboxColumn;
import com.sap.sailing.gwt.ui.shared.RaceLogDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.common.Util;
import com.sap.sse.gwt.client.ErrorReporter;
@@ -619,4 +620,33 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel implement
});
dialog.show();
}
protected void showRegattaLog() {
final String selectedLeaderboardName = getSelectedLeaderboardName();
sailingService.getRegattaLog(selectedLeaderboardName,
new MarkedAsyncCallback<RegattaLogDTO>(
new AsyncCallback<RegattaLogDTO>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError(caught.getMessage(), true);
}
@Override
public void onSuccess(RegattaLogDTO result) {
openRegattaLogDialog(result);
}
}));
}
private void openRegattaLogDialog(RegattaLogDTO regattaLogDTO) {
RegattaLogDialog dialog = new RegattaLogDialog(regattaLogDTO, stringMessages, new DialogCallback<RegattaLogDTO>() {
@Override
public void cancel() {
}
@Override
public void ok(RegattaLogDTO result) {
}
});
dialog.show();
}
}
@@ -0,0 +1,184 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Comparator;
import java.util.Date;
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.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.AbstractLogDTO;
import com.sap.sailing.gwt.ui.shared.AbstractLogEventDTO;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public abstract class AbstractLogDialog<R extends AbstractLogDTO<E>, E extends AbstractLogEventDTO> extends DataEntryDialog<R> {
private final R logDTO;
private final SelectionModel<E> selectionModel;
private final CellTable<E> raceLogEventsTable;
private ListDataProvider<E> raceLogEventsList;
public AbstractLogDialog(final R logDTO, final StringMessages stringMessages, String logName, DialogCallback<R> callback) {
super(logName, null, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
this.logDTO = logDTO;
raceLogEventsList = new ListDataProvider<E>();
selectionModel = new SingleSelectionModel<E>();
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
raceLogEventsTable = new CellTable<E>(/* pageSize */10000, tableRes);
raceLogEventsTable.ensureDebugId("TrackedRacesTable");
raceLogEventsTable.setSelectionModel(selectionModel);
raceLogEventsList.setList(logDTO.getEntries());
ListHandler<E> columnSortHandler = new ListHandler<>(raceLogEventsList.getList());
raceLogEventsTable.addColumnSortHandler(columnSortHandler);
TextColumn<E> logEventAuthorColumn = new TextColumn<E>() {
@Override
public String getValue(E logEventDTO) {
return String.valueOf(logEventDTO.getAuthorName());
}
};
logEventAuthorColumn.setSortable(true);
columnSortHandler.setComparator(logEventAuthorColumn, new Comparator<E>() {
@Override
public int compare(E r1, E r2) {
return new NaturalComparator().compare(r1.getAuthorName(), r1.getAuthorName());
}
});
TextColumn<E> logEventAuthorPriorityColumn = new TextColumn<E>() {
@Override
public String getValue(E logEventDTO) {
return String.valueOf(logEventDTO.getAuthorPriority());
}
};
logEventAuthorPriorityColumn.setSortable(true);
columnSortHandler.setComparator(logEventAuthorPriorityColumn, new Comparator<E>() {
@Override
public int compare(E r1, E r2) {
return r1.getAuthorPriority() - r2.getAuthorPriority();
}
});
TextColumn<E> logEventCreatedColumn = new TextColumn<E>() {
@Override
public String getValue(E raceLogEventDTO) {
Date createdAt = raceLogEventDTO.getCreatedAt();
if(createdAt != null) {
return DateAndTimeFormatterUtil.defaultDateFormatter.render(createdAt) + " " +
DateAndTimeFormatterUtil.defaultTimeFormatter.render(createdAt);
}
return "";
}
};
logEventCreatedColumn.setSortable(true);
columnSortHandler.setComparator(logEventCreatedColumn, new Comparator<E>() {
@Override
public int compare(E r1, E r2) {
if (r1.getCreatedAt() != null && r2.getCreatedAt() != null) {
return r1.getCreatedAt().compareTo(r2.getCreatedAt());
}
return r1.getCreatedAt() == null ? (r2.getCreatedAt() == null ? 0 : -1) : 1;
}
});
TextColumn<E> logEventLogicalTimeColumn = new TextColumn<E>() {
@Override
public String getValue(E logEventDTO) {
Date logicalTimePoint = logEventDTO.getLogicalTimePoint();
if (logicalTimePoint != null) {
return DateAndTimeFormatterUtil.defaultDateFormatter.render(logicalTimePoint) + " " +
DateAndTimeFormatterUtil.defaultTimeFormatter.render(logicalTimePoint);
}
return "";
}
};
logEventLogicalTimeColumn.setSortable(true);
columnSortHandler.setComparator(logEventLogicalTimeColumn, new Comparator<E>() {
@Override
public int compare(E r1, E r2) {
if (r1.getLogicalTimePoint() != null && r2.getLogicalTimePoint() != null) {
return r1.getLogicalTimePoint().compareTo(r2.getLogicalTimePoint());
}
return r1.getLogicalTimePoint() == null ? (r2.getLogicalTimePoint() == null ? 0 : -1) : 1;
}
});
TextColumn<E> logEventTypeColumn = new TextColumn<E>() {
@Override
public String getValue(E logEventDTO) {
return logEventDTO.getType();
}
};
logEventTypeColumn.setSortable(true);
columnSortHandler.setComparator(logEventTypeColumn, new Comparator<E>() {
@Override
public int compare(E r1, E r2) {
return new NaturalComparator().compare(r1.getType(), r2.getType());
}
});
TextColumn<E> logEventInfoColumn = new TextColumn<E>() {
@Override
public String getValue(E logEventDTO) {
return logEventDTO.getInfo();
}
};
logEventInfoColumn.setSortable(true);
columnSortHandler.setComparator(logEventInfoColumn, new Comparator<E>() {
@Override
public int compare(E o1, E o2) {
return new NaturalComparator().compare(o1.getInfo(), o2.getInfo());
}
});
addFirstColumns(raceLogEventsTable, columnSortHandler);
raceLogEventsTable.addColumn(logEventTypeColumn, stringMessages.type());
raceLogEventsTable.addColumn(logEventCreatedColumn, "Created at");
raceLogEventsTable.addColumn(logEventLogicalTimeColumn, "Logical timepoint");
raceLogEventsTable.addColumn(logEventAuthorColumn, "Author");
raceLogEventsTable.addColumn(logEventAuthorPriorityColumn, "Priority");
raceLogEventsTable.addColumn(logEventInfoColumn, "Info");
addLastColumns(raceLogEventsTable, columnSortHandler);
raceLogEventsList.addDataDisplay(raceLogEventsTable);
raceLogEventsTable.getColumnSortList().push(logEventLogicalTimeColumn);
}
protected void addFirstColumns(CellTable<E> table, ListHandler<E> columnSortHandler) {}
protected void addLastColumns(CellTable<E> table, ListHandler<E> columnSortHandler) {}
@Override
protected R getResult() {
return null;
}
@Override
protected Widget getAdditionalWidget() {
VerticalPanel vPanel = new VerticalPanel();
addFirstWidgetComponents(vPanel);
ScrollPanel scrollPanel = new ScrollPanel(raceLogEventsTable);
scrollPanel.setSize("960px", "500px");
vPanel.add(scrollPanel);
addLastWidgetComponents(vPanel);
return vPanel;
}
protected R getLogDTO() {
return logDTO;
}
protected void addFirstWidgetComponents(VerticalPanel vPanel) {}
protected void addLastWidgetComponents(VerticalPanel vPanel) {}
}
@@ -16,6 +16,7 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
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_OPEN_COACH_DASHBOARD = "ACTION_OPEN_COACH_DASHBOARD";
public static final String ACTION_SHOW_REGATTA_LOG = "ACTION_SHOW_REGATTA_LOG";
private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
private final StringMessages stringMessages;
@@ -38,6 +39,7 @@ public class LeaderboardConfigImagesBarCell extends ImagesBarCell {
new ImageSpec(ACTION_CONFIGURE_URL, stringMessages.actionConfigureUrl(), makeImagePrototype(resources.settingsActionIcon())),
new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon())),
new ImageSpec(ACTION_EXPORT_XML, stringMessages.actionExportXML(), makeImagePrototype(resources.exportXMLIcon())),
new ImageSpec(ACTION_OPEN_COACH_DASHBOARD, stringMessages.actionOpenDashboard(), makeImagePrototype(resources.openCoachDashboard())));
new ImageSpec(ACTION_OPEN_COACH_DASHBOARD, stringMessages.actionOpenDashboard(), makeImagePrototype(resources.openCoachDashboard())),
new ImageSpec(ACTION_SHOW_REGATTA_LOG, stringMessages.regattaLog(), makeImagePrototype(resources.flagIcon())));
}
}
@@ -261,6 +261,8 @@ TrackedRaceChangedListener, LeaderboardsDisplayer {
Map<String, String> dashboardURLParameters = new HashMap<String, String>();
dashboardURLParameters.put("leaderboardName", leaderboardDTO.name);
Window.open(EntryPointLinkFactory.createDashboardLink(dashboardURLParameters), "", null);
} else if (LeaderboardConfigImagesBarCell.ACTION_SHOW_REGATTA_LOG.equals(value)) {
showRegattaLog();
}
}
});
@@ -1,62 +1,26 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Comparator;
import java.util.Date;
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.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.domain.common.impl.NaturalComparator;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sailing.gwt.ui.shared.RaceLogDTO;
import com.sap.sailing.gwt.ui.shared.RaceLogEventDTO;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public class RaceLogDialog extends DataEntryDialog<RaceLogDTO> {
public class RaceLogDialog extends AbstractLogDialog<RaceLogDTO, RaceLogEventDTO> {
private final StringMessages stringMessages;
private final RaceLogDTO raceLogDTO;
private final SelectionModel<RaceLogEventDTO> selectionModel;
private final CellTable<RaceLogEventDTO> raceLogEventsTable;
private ListDataProvider<RaceLogEventDTO> raceLogEventsList;
protected static class RaceLogValidator implements Validator<RaceLogDTO> {
public RaceLogValidator() {
super();
}
@Override
public String getErrorMessage(RaceLogDTO valueToValidate) {
return null;
}
}
public RaceLogDialog(final RaceLogDTO raceLogDTO, final StringMessages stringMessages, DialogCallback<RaceLogDTO> callback) {
super(stringMessages.raceLog(), null, stringMessages.ok(), stringMessages.cancel(), new RaceLogValidator(), callback);
super(raceLogDTO, stringMessages, stringMessages.raceLog(), callback);
this.stringMessages = stringMessages;
this.raceLogDTO = raceLogDTO;
raceLogEventsList = new ListDataProvider<RaceLogEventDTO>();
selectionModel = new SingleSelectionModel<RaceLogEventDTO>();
AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
raceLogEventsTable = new CellTable<RaceLogEventDTO>(/* pageSize */10000, tableRes);
raceLogEventsTable.ensureDebugId("TrackedRacesTable");
raceLogEventsTable.setSelectionModel(selectionModel);
raceLogEventsList.setList(raceLogDTO.getEntries());
ListHandler<RaceLogEventDTO> columnSortHandler = new ListHandler<RaceLogEventDTO>(raceLogEventsList.getList());
raceLogEventsTable.addColumnSortHandler(columnSortHandler);
}
@Override
protected void addFirstColumns(CellTable<RaceLogEventDTO> table, ListHandler<RaceLogEventDTO> columnSortHandler) {
TextColumn<RaceLogEventDTO> raceLogEventPassIdColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
@@ -70,117 +34,12 @@ public class RaceLogDialog extends DataEntryDialog<RaceLogDTO> {
return (r1.getPassId()<r2.getPassId() ? -1 : (r1.getPassId()==r2.getPassId() ? 0 : 1));
}
});
TextColumn<RaceLogEventDTO> raceLogEventAuthorColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
return String.valueOf(raceLogEventDTO.getAuthorName());
}
};
TextColumn<RaceLogEventDTO> raceLogEventAuthorPriorityColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
return String.valueOf(raceLogEventDTO.getAuthorPriority());
}
};
TextColumn<RaceLogEventDTO> raceLogEventCreatedColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
Date createdAt = raceLogEventDTO.getCreatedAt();
if(createdAt != null) {
return DateAndTimeFormatterUtil.defaultDateFormatter.render(createdAt) + " " +
DateAndTimeFormatterUtil.defaultTimeFormatter.render(createdAt);
}
return "";
}
};
raceLogEventCreatedColumn.setSortable(true);
columnSortHandler.setComparator(raceLogEventCreatedColumn, new Comparator<RaceLogEventDTO>() {
@Override
public int compare(RaceLogEventDTO r1, RaceLogEventDTO r2) {
if (r1.getCreatedAt() != null && r2.getCreatedAt() != null) {
return r1.getCreatedAt().compareTo(r2.getCreatedAt());
}
return r1.getCreatedAt() == null ? (r2.getCreatedAt() == null ? 0 : -1) : 1;
}
});
TextColumn<RaceLogEventDTO> raceLogEventLogicalTimeColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
Date logicalTimePoint = raceLogEventDTO.getLogicalTimePoint();
if(logicalTimePoint != null) {
return DateAndTimeFormatterUtil.defaultDateFormatter.render(logicalTimePoint) + " " +
DateAndTimeFormatterUtil.defaultTimeFormatter.render(logicalTimePoint);
}
return "";
}
};
raceLogEventLogicalTimeColumn.setSortable(true);
columnSortHandler.setComparator(raceLogEventCreatedColumn, new Comparator<RaceLogEventDTO>() {
@Override
public int compare(RaceLogEventDTO r1, RaceLogEventDTO r2) {
if (r1.getLogicalTimePoint() != null && r2.getLogicalTimePoint() != null) {
return r1.getLogicalTimePoint().compareTo(r2.getLogicalTimePoint());
}
return r1.getLogicalTimePoint() == null ? (r2.getLogicalTimePoint() == null ? 0 : -1) : 1;
}
});
TextColumn<RaceLogEventDTO> raceLogEventTypeColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
return raceLogEventDTO.getType();
}
};
raceLogEventTypeColumn.setSortable(true);
columnSortHandler.setComparator(raceLogEventTypeColumn, new Comparator<RaceLogEventDTO>() {
@Override
public int compare(RaceLogEventDTO r1, RaceLogEventDTO r2) {
return new NaturalComparator().compare(r1.getType(), r2.getType());
}
});
TextColumn<RaceLogEventDTO> raceLogEventInfoColumn = new TextColumn<RaceLogEventDTO>() {
@Override
public String getValue(RaceLogEventDTO raceLogEventDTO) {
return raceLogEventDTO.getInfo();
}
};
raceLogEventsTable.addColumn(raceLogEventPassIdColumn, "PassId");
raceLogEventsTable.addColumn(raceLogEventTypeColumn, stringMessages.type());
raceLogEventsTable.addColumn(raceLogEventCreatedColumn, "Created at");
raceLogEventsTable.addColumn(raceLogEventLogicalTimeColumn, "Logical timepoint");
raceLogEventsTable.addColumn(raceLogEventAuthorColumn, "Author");
raceLogEventsTable.addColumn(raceLogEventAuthorPriorityColumn, "Priority");
raceLogEventsTable.addColumn(raceLogEventInfoColumn, "Info");
raceLogEventsList.addDataDisplay(raceLogEventsTable);
raceLogEventsTable.getColumnSortList().push(raceLogEventLogicalTimeColumn);
table.addColumn(raceLogEventPassIdColumn, "PassId");
}
@Override
protected RaceLogDTO getResult() {
return null;
}
@Override
protected Widget getAdditionalWidget() {
VerticalPanel vPanel = new VerticalPanel();
Label currentPassLabel = new Label(stringMessages.currentPass() + ":" + raceLogDTO.getCurrentPassId());
protected void addFirstWidgetComponents(VerticalPanel vPanel) {
Label currentPassLabel = new Label(stringMessages.currentPass() + ":" + getLogDTO().getCurrentPassId());
vPanel.add(currentPassLabel);
ScrollPanel scrollPanel = new ScrollPanel(raceLogEventsTable);
scrollPanel.setSize("960px", "500px");
vPanel.add(scrollPanel);
return vPanel;
}
}
@@ -12,6 +12,7 @@ public class RaceLogTrackingEventManagementImagesBarCell extends ImagesBarCell {
public final static String ACTION_COMPETITOR_REGISTRATIONS = "ACTION_COMPETITOR_REGISTRATIONS";
public final static String ACTION_MAP_DEVICES = "ACTION_MAP_DEVICES";
public final static String ACTION_INVITE_BUOY_TENDERS = "ACTION_INVITE_BUOY_TENDERS";
public static final String ACTION_SHOW_REGATTA_LOG = "ACTION_SHOW_REGATTA_LOG";
private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
private final StringMessages stringMessages;
@@ -37,6 +38,8 @@ public class RaceLogTrackingEventManagementImagesBarCell extends ImagesBarCell {
makeImagePrototype(resources.mapDevices())));
result.add(new ImageSpec(ACTION_INVITE_BUOY_TENDERS, stringMessages.inviteBuoyTenders(),
makeImagePrototype(resources.inviteBuoyTenders())));
result.add(new ImageSpec(ACTION_SHOW_REGATTA_LOG, stringMessages.regattaLog(),
makeImagePrototype(resources.flagIcon())));
return result;
}
@@ -140,6 +140,8 @@ public class RaceLogTrackingEventManagementPanel extends AbstractLeaderboardConf
leaderboardName).show();
} else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_INVITE_BUOY_TENDERS.equals(value)) {
openChooseEventDialogAndSendMails(leaderboardName);
} else if (RaceLogTrackingEventManagementImagesBarCell.ACTION_SHOW_REGATTA_LOG.equals(value)) {
showRegattaLog();
}
}
});
@@ -0,0 +1,11 @@
package com.sap.sailing.gwt.ui.adminconsole;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RegattaLogDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogEventDTO;
public class RegattaLogDialog extends AbstractLogDialog<RegattaLogDTO, RegattaLogEventDTO> {
public RegattaLogDialog(final RegattaLogDTO regattaLogDTO, final StringMessages stringMessages, DialogCallback<RegattaLogDTO> callback) {
super(regattaLogDTO, stringMessages, stringMessages.raceLog(), callback);
}
}
@@ -66,6 +66,7 @@ import com.sap.sailing.gwt.ui.shared.RaceLogDTO;
import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogDTO;
import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.RemoteSailingServerReferenceDTO;
@@ -397,6 +398,8 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
RaceLogDTO getRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet);
RegattaLogDTO getRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException;
List<String> getLeaderboardGroupNamesFromRemoteServer(String host);
UUID importMasterData(String host, String[] groupNames, boolean override, boolean compress, boolean exportWind);
@@ -586,4 +589,5 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName,
String emails, String localeInfoName) throws MailException;
}
@@ -56,6 +56,7 @@ import com.sap.sailing.gwt.ui.shared.RaceLogDTO;
import com.sap.sailing.gwt.ui.shared.RaceLogSetStartTimeAndProcedureDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogDTO;
import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.RemoteSailingServerReferenceDTO;
@@ -506,8 +507,9 @@ public interface SailingServiceAsync extends BuildVersionRetriever, FileStorageM
void getRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet,
AsyncCallback<RaceLogDTO> callback);
void importMasterData(String host, String[] names, boolean override, boolean compress,
boolean exportWind,
void getRegattaLog(String leaderboardName, AsyncCallback<RegattaLogDTO> callback);
void importMasterData(String host, String[] names, boolean override, boolean compress, boolean exportWind,
AsyncCallback<UUID> asyncCallback);
void getImportOperationProgress(UUID id, AsyncCallback<DataImportProgress> asyncCallback);
@@ -692,5 +694,6 @@ public interface SailingServiceAsync extends BuildVersionRetriever, FileStorageM
void getMarksInRaceLogsAndTrackedRaces(String leaderboardName, AsyncCallback<Iterable<MarkDTO>> callback);
void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName,
String emails, String localeInfoName, AsyncCallback<Void> callback);
String emails, String localeInfoName, AsyncCallback<Void> callback);
}
@@ -754,6 +754,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, c
String protestEndsAt();
String unknown();
String raceLog();
String regattaLog();
String refreshRaceLog();
String raceLogReloaded();
String reloadAllRaceLogs();
@@ -748,6 +748,7 @@ protestEndsAt=Protest ends at
unknown=Unknown
earlyStarters=Early starters
raceLog=Race log
regattaLog=Regatta log
refreshRaceLog=Refresh race log
raceLogReloaded=Race log successfully reloaded from database
reloadAllRaceLogs=Reload all race logs
@@ -744,6 +744,7 @@ protestEndsAt=Protestzeit endet
unknown=Unbekannt
earlyStarters=Frühstarter
raceLog=RaceLog
regattaLog=RegattaLog
refreshRaceLog=RaceLog neu laden
raceLogReloaded=RaceLog wurde neu geladen
reloadAllRaceLogs=Alle RaceLogs neu laden
@@ -738,6 +738,7 @@ protestEndsAt=Срок подачи протеста завершается в
unknown=Неизвестно
earlyStarters=Совершивших фальшстарт
raceLog=Запись о гонке
regattaLog=Regatta log
refreshRaceLog=Обновить запись о гонке
raceLogReloaded=Запись о гонке успешно повторно загружена из базы данных
reloadAllRaceLogs=Повторно загрузить все записи о гонке
@@ -74,6 +74,7 @@ import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.DefinedMa
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogOpenEndedDeviceMappingCloser;
import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLog;
import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent;
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceCompetitorMappingFinder;
import com.sap.sailing.domain.abstractlog.shared.analyzing.DeviceMarkMappingFinder;
import com.sap.sailing.domain.abstractlog.shared.analyzing.RegisteredCompetitorsAnalyzer;
@@ -301,6 +302,8 @@ import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RaceWithCompetitorsDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogDTO;
import com.sap.sailing.gwt.ui.shared.RegattaLogEventDTO;
import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO.ScoreCorrectionEntryDTO;
@@ -4251,6 +4254,30 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return result;
}
@Override
public RegattaLogDTO getRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException {
RegattaLogDTO result = null;
RegattaLog regattaLog = getRegattaLogInternal(leaderboardName);
if (regattaLog != null) {
List<RegattaLogEventDTO> entries = new ArrayList<>();
result = new RegattaLogDTO(leaderboardName, entries);
regattaLog.lockForRead();
try {
for(RegattaLogEvent raceLogEvent: regattaLog.getRawFixes()) {
RegattaLogEventDTO entry = new RegattaLogEventDTO(
raceLogEvent.getAuthor().getName(), raceLogEvent.getAuthor().getPriority(),
raceLogEvent.getCreatedAt() != null ? raceLogEvent.getCreatedAt().asDate() : null,
raceLogEvent.getLogicalTimePoint() != null ? raceLogEvent.getLogicalTimePoint().asDate() : null,
raceLogEvent.getClass().getSimpleName(), raceLogEvent.getShortInfo());
entries.add(entry);
}
} finally {
regattaLog.unlockAfterRead();
}
}
return result;
}
@Override
public List<String> getLeaderboardGroupNamesFromRemoteServer(String url) {
com.sap.sse.common.Util.Pair<String, Integer> hostnameAndPort = parseHostAndPort(url);
@@ -4818,7 +4845,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return getRaceLog(triple.getA(), triple.getB(), triple.getC());
}
private RegattaLog getRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException {
private RegattaLog getRegattaLogInternal(String leaderboardName) throws DoesNotHaveRegattaLogException {
Leaderboard l = getService().getLeaderboardByName(leaderboardName);
if (! (l instanceof HasRegattaLike)) {
throw new DoesNotHaveRegattaLogException();
@@ -4844,7 +4871,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
throws DoesNotHaveRegattaLogException {
return convertToCompetitorDTOs(
new RegisteredCompetitorsAnalyzer<>(
getRegattaLog(leaderboardName)).analyze());
getRegattaLogInternal(leaderboardName)).analyze());
}
private Competitor getCompetitor(CompetitorDTO dto) {
@@ -4866,7 +4893,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public void setCompetitorRegistrations(String leaderboardName, Set<CompetitorDTO> competitorDTOs)
throws DoesNotHaveRegattaLogException {
RegattaLog regattaLog = getRegattaLog(leaderboardName);
RegattaLog regattaLog = getRegattaLogInternal(leaderboardName);
Set<Competitor> competitors = new HashSet<Competitor>();
for (CompetitorDTO dto : competitorDTOs) {
competitors.add(getCompetitor(dto));
@@ -0,0 +1,28 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log with all raw race log entries
*/
public class AbstractLogDTO<E extends AbstractLogEventDTO> implements IsSerializable {
private String leaderboardName;
private List<E> entries;
AbstractLogDTO() {}
public AbstractLogDTO(String leaderboardName, List<E> entries) {
this.leaderboardName = leaderboardName;
this.entries = entries;
}
public String getLeaderboardName() {
return leaderboardName;
}
public List<E> getEntries() {
return entries;
}
}
@@ -0,0 +1,64 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log entry.
*/
public class AbstractLogEventDTO implements IsSerializable {
private String authorName;
private Integer authorPriority;
private Date createdAt;
private Date logicalTimePoint;
/** RaceLogEvent.getClass().getSimpleName() */
private String type;
/** RaceLogEvent.toString() */
private String info;
AbstractLogEventDTO() {}
public AbstractLogEventDTO(String authorName, Integer authorPriority, Date createdAt, Date logicalTimePoint,
String type, String info) {
this.authorName = authorName;
this.authorPriority = authorPriority;
this.createdAt = createdAt;
this.logicalTimePoint = logicalTimePoint;
this.type = type;
this.info = info;
}
public String getAuthorName() {
return authorName;
}
public Integer getAuthorPriority() {
return authorPriority;
}
public Date getLogicalTimePoint() {
return logicalTimePoint;
}
public String getType() {
String result = type;
if(result.startsWith("RaceLog")) {
result = result.substring("RaceLog".length(), result.length());
}
if(result.endsWith("EventImpl")) {
result = result.substring(0, result.length()- "EventImpl".length());
}
return result;
}
public String getInfo() {
return info;
}
public Date getCreatedAt() {
return createdAt;
}
}
@@ -7,25 +7,18 @@ import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log with all raw race log entries
*/
public class RaceLogDTO implements IsSerializable {
private String leaderboardName;
public class RaceLogDTO extends AbstractLogDTO<RaceLogEventDTO> implements IsSerializable {
private String raceColumnName;
private String fleetName;
private Integer currentPassId;
private List<RaceLogEventDTO> entries;
RaceLogDTO() {}
public RaceLogDTO(String leaderboardName, String raceColumnName, String fleetName, Integer currentPassId, List<RaceLogEventDTO> entries) {
this.leaderboardName = leaderboardName;
super(leaderboardName, entries);
this.raceColumnName = raceColumnName;
this.fleetName = fleetName;
this.currentPassId = currentPassId;
this.entries = entries;
}
public String getLeaderboardName() {
return leaderboardName;
}
public String getRaceColumnName() {
@@ -36,10 +29,6 @@ public class RaceLogDTO implements IsSerializable {
return fleetName;
}
public List<RaceLogEventDTO> getEntries() {
return entries;
}
public Integer getCurrentPassId() {
return currentPassId;
}
@@ -7,64 +7,18 @@ import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log entry.
*/
public class RaceLogEventDTO implements IsSerializable {
public class RaceLogEventDTO extends AbstractLogEventDTO implements IsSerializable {
private Integer passId;
private String authorName;
private Integer authorPriority;
private Date createdAt;
private Date logicalTimePoint;
/** RaceLogEvent.getClass().getSimpleName() */
private String type;
/** RaceLogEvent.toString() */
private String info;
RaceLogEventDTO() {}
public RaceLogEventDTO(int passId, String authorName, Integer authorPriority, Date createdAt, Date logicalTimePoint,
String type, String info) {
super(authorName, authorPriority, createdAt, logicalTimePoint, type, info);
this.passId = passId;
this.authorName = authorName;
this.authorPriority = authorPriority;
this.createdAt = createdAt;
this.logicalTimePoint = logicalTimePoint;
this.type = type;
this.info = info;
}
public int getPassId() {
return passId;
}
public String getAuthorName() {
return authorName;
}
public Integer getAuthorPriority() {
return authorPriority;
}
public Date getLogicalTimePoint() {
return logicalTimePoint;
}
public String getType() {
String result = type;
if(result.startsWith("RaceLog")) {
result = result.substring("RaceLog".length(), result.length());
}
if(result.endsWith("EventImpl")) {
result = result.substring(0, result.length()- "EventImpl".length());
}
return result;
}
public String getInfo() {
return info;
}
public Date getCreatedAt() {
return createdAt;
}
}
@@ -0,0 +1,16 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log with all raw race log entries
*/
public class RegattaLogDTO extends AbstractLogDTO<RegattaLogEventDTO> implements IsSerializable {
RegattaLogDTO() {}
public RegattaLogDTO(String leaderboardName, List<RegattaLogEventDTO> entries) {
super(leaderboardName, entries);
}
}
@@ -0,0 +1,17 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
/**
* DTO for a race log entry.
*/
public class RegattaLogEventDTO extends AbstractLogEventDTO implements IsSerializable {
RegattaLogEventDTO() {}
public RegattaLogEventDTO(String authorName, Integer authorPriority, Date createdAt, Date logicalTimePoint,
String type, String info) {
super(authorName, authorPriority, createdAt, logicalTimePoint, type, info);
}
}