Merge branch 'master' of ssh://sapsailing.com/home/trac/git

This commit is contained in:
STG (Server) committed 2013-06-26 17:07:54 +02:00
commit 5b7c5562d0
46 files changed
+409 -91

No files matched your search

@@ -0,0 +1,5 @@
package com.sap.sailing.domain.common;
public enum CompetitorGenderType {
Men, Women, Mixed, Open
}
@@ -591,6 +591,10 @@ public class IncrementalLeaderboardDTO extends LeaderboardDTO implements Increme
} else {
LeaderboardEntryDTO newLeaderboardEntryDTO = new LeaderboardEntryDTO();
cloner.clone(raceColumnNameAndLeaderboardEntry.getValue(), newLeaderboardEntryDTO);
// clone the leg details collection to ensure that when we need to manipulate it we don't manipulate the original
if (newLeaderboardEntryDTO.legDetails != null) {
newLeaderboardEntryDTO.legDetails = new ArrayList<LegEntryDTO>(newLeaderboardEntryDTO.legDetails);
}
newFieldsByRaceColumnName.put(raceColumnNameAndLeaderboardEntry.getKey(), newLeaderboardEntryDTO);
if (newLeaderboardEntryDTO.legDetails != null) {
for (int legDetailsIndex = 0; legDetailsIndex < newLeaderboardEntryDTO.legDetails.size(); legDetailsIndex++) {
@@ -2,11 +2,13 @@ package com.sap.sailing.domain.persistence.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import com.mongodb.DB;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogStore;
@@ -15,23 +17,35 @@ public class MongoRaceLogStoreImpl implements RaceLogStore {
private final MongoObjectFactory mongoObjectFactory;
private final DomainObjectFactory domainObjectFactory;
private final Map<RaceLogIdentifier, RaceLog> raceLogCache;
private final WeakHashMap<RaceLog, MongoRaceLogListener> listeners;
public MongoRaceLogStoreImpl(DB db, MongoObjectFactory mongoObjectFactory, DomainObjectFactory domainObjectFactory) {
this.db = db;
this.mongoObjectFactory = mongoObjectFactory;
this.domainObjectFactory = domainObjectFactory;
this.raceLogCache = new HashMap<>();
this.listeners = new WeakHashMap<RaceLog, MongoRaceLogListener>();
}
@Override
public RaceLog getRaceLog(RaceLogIdentifier identifier) {
if (raceLogCache.containsKey(identifier)) {
public RaceLog getRaceLog(RaceLogIdentifier identifier, boolean ignoreCache) {
if (!ignoreCache && raceLogCache.containsKey(identifier)) {
return raceLogCache.get(identifier);
}
RaceLog result = domainObjectFactory.loadRaceLog(identifier);
result.addListener(new MongoRaceLogListener(identifier, mongoObjectFactory, db));
MongoRaceLogListener listener = new MongoRaceLogListener(identifier, mongoObjectFactory, db);
listeners.put(result, listener);
result.addListener(listener);
raceLogCache.put(identifier, result);
return result;
}
@Override
public void removeListenersAddedByStoreFrom(RaceLog raceLog) {
RaceLogEventVisitor visitor = listeners.get(raceLog);
if (visitor != null) {
raceLog.removeListener(visitor);
}
}
}
@@ -71,4 +71,8 @@ public class MarkImpl extends NamedImpl implements Mark {
public MarkType getType() {
return type;
}
public String toString() {
return getId() + " " + getColor() + super.toString();
}
}
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.racelog;
import java.util.HashSet;
import com.sap.sailing.domain.common.WithID;
import com.sap.sailing.domain.racelog.impl.RaceLogEventComparator;
import com.sap.sailing.domain.tracking.Track;
@@ -46,6 +48,12 @@ public interface RaceLog extends Track<RaceLogEvent>, WithID {
*/
void removeListener(RaceLogEventVisitor listener);
/**
* Removes all listeners
* @return
*/
HashSet<RaceLogEventVisitor> removeAllListeners();
/**
* Checks if the race log is empty.
*/
@@ -54,4 +62,8 @@ public interface RaceLog extends Track<RaceLogEvent>, WithID {
Iterable<RaceLogEvent> getRawFixesDescending();
Iterable<RaceLogEvent> getFixesDescending();
void addAllListeners(HashSet<RaceLogEventVisitor> listeners);
Iterable<RaceLogEventVisitor> getAllListeners();
}
@@ -149,4 +149,23 @@ public class RaceLogImpl extends TrackImpl<RaceLogEvent> implements RaceLog {
return getFixes().descendingSet();
}
@Override
public HashSet<RaceLogEventVisitor> removeAllListeners() {
synchronized(listeners) {
HashSet<RaceLogEventVisitor> clonedListeners = new HashSet<RaceLogEventVisitor>(listeners);
listeners = new HashSet<RaceLogEventVisitor>();
return clonedListeners;
}
}
@Override
public void addAllListeners(HashSet<RaceLogEventVisitor> listeners) {
this.listeners = listeners;
}
@Override
public Iterable<RaceLogEventVisitor> getAllListeners() {
return this.listeners;
}
}
@@ -34,6 +34,7 @@ import com.sap.sailing.domain.common.dto.LegEntryDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.test.StoredTrackBasedTest;
import com.sap.sailing.util.ClonerImpl;
@@ -143,7 +144,24 @@ public class LeaderboardDTODiffingTest {
}
newVersion.rows = newRows;
Map<CompetitorDTO, LeaderboardRowDTO> rowsBeforeStripping = newVersion.rows;
Map<Pair<CompetitorDTO, String>, List<LegEntryDTO>> previousLegDetailsBeforeStripping = new HashMap<>();
for (Map.Entry<CompetitorDTO, LeaderboardRowDTO> e : rowsBeforeStripping.entrySet()) {
for (Map.Entry<String, LeaderboardEntryDTO> e2 : e.getValue().fieldsByRaceColumnName.entrySet()) {
if (e2.getValue().legDetails != null) {
previousLegDetailsBeforeStripping.put(new Pair<CompetitorDTO, String>(e.getKey(), e2.getKey()),
new ArrayList<>(e2.getValue().legDetails));
}
}
}
newVersion.strip(previousVersion);
// see bug 1455; check that the stripping doesn't kill the previous leaderboard's legDetails lists
for (Map.Entry<Pair<CompetitorDTO, String>, List<LegEntryDTO>> e : previousLegDetailsBeforeStripping.entrySet()) {
final LeaderboardRowDTO leaderboardRowDTO = rowsBeforeStripping.get(e.getKey().getA());
if (leaderboardRowDTO != null) {
List<LegEntryDTO> newLegDetails = leaderboardRowDTO.fieldsByRaceColumnName.get(e.getKey().getB()).legDetails;
assertEquals(e.getValue(), newLegDetails);
}
}
assertAllRowsKeysAreIdenticalToAllLeaderboardRowDTOCompetitors(newVersion);
assertNotNull(newVersion.rows);
assertEquals(previousVersion.rows.size()-17, newVersion.rows.size()); // all rows have changed except for 17 that have no leg details in leg 8
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.tractracadapter.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
@@ -91,8 +92,11 @@ public class MarkPositionReceiver extends AbstractReceiverWithQueue<ControlPoint
TimePoint now = MillisecondsTimePoint.now();
long fromTime = startOfTracking == null ? 0l : startOfTracking.compareTo(now) > 0 ? now.asMillis() : startOfTracking.asMillis();
long toTime = endOfTracking == null ? Long.MAX_VALUE : endOfTracking.asMillis();
logger.fine("subscribing to ControlPointPositionData for time range "+new MillisecondsTimePoint(fromTime)+"/"+
new MillisecondsTimePoint(toTime));
Collection<Race> races = getTracTracEvent().getRaceList();
for (Race race : races) {
logger.info("Subscribing to ControlPointPositionData for time range "+new MillisecondsTimePoint(fromTime)+"/"+
new MillisecondsTimePoint(toTime) + " for event " + getTracTracEvent().getName() + " " + race.getName());
}
TypeController controlPointListener = ControlPointPositionData.subscribe(getTracTracEvent(),
new ICallbackData<ControlPoint, ControlPointPositionData>() {
@Override
@@ -196,6 +196,9 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl implements
throw new RuntimeException("Connection failed. Could not connect to " + paramURL);
}
logger.info("Starting race tracker: " + tractracEvent.getName() + " " + paramURL + " " + liveURI
+ storedURI + " startOfTracking:" + (startOfTracking != null ? startOfTracking.asMillis() : "n/a") + " endOfTracking:" + (endOfTracking != null ? endOfTracking.asMillis() : "n/a"));
// Initialize data controller using live and stored data sources
controller = new DataController(liveURI, storedURI, this);
// Start live and stored data streams
@@ -35,6 +35,8 @@ public interface RaceColumn extends Named {
*/
void setRaceLogInformation(RaceLogInformation information);
RaceLogInformation getRaceLogInformation();
/**
* Gets the race column's race log associated to the passed fleet.
*
@@ -112,6 +114,8 @@ public interface RaceColumn extends Named {
*
* @param fleet
* the fleet for which to associate a race by its identifier
* @param raceIdentifier
* the race that should be associated with this column+fleet. It should never be null.
*/
void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier);
@@ -133,7 +137,7 @@ public interface RaceColumn extends Named {
/**
* Releases the {@link TrackedRace} previously set by {@link #setTrackedRace(Fleet, TrackedRace)} but leaves the
* {@link #getRaceIdentifier(Fleet) race identifier} untouched. Therefore, the {@link TrackedRace} may be garbage
* {@link #getRaceIdentifier(Fleet) race identifier} untouched(!). Therefore, the {@link TrackedRace} may be garbage
* collected but may be re-resolved for this column using the race identifier at a later time.
*
* @param fleet
@@ -159,6 +163,8 @@ public interface RaceColumn extends Named {
boolean isStartsWithZeroScore();
boolean isDiscardable();
boolean isCarryForward();
/**
* @param factor if <code>null</code>, {@link #getFactor()} will again compute a default value; otherwise, {@link #getFactor()} will
@@ -177,5 +183,22 @@ public interface RaceColumn extends Named {
* @param fleet
* @return
*/
RaceLogIdentifier getRaceLogIdentifier(Fleet fleet);
RaceLogIdentifier getRaceLogIdentifier(Fleet fleet);
/**
* Sets (or reloads) {@link RaceLog} for this column with the given fleet
*
* @param raceLogInformation
* @param fleetImpl
*/
void setOrReloadRaceLogInformation(RaceLogInformation raceLogInformation, Fleet fleetImpl);
/**
* Remove the association between a race and a column. This is different from
* {@link RaceColumn#releaseTrackedRace(Fleet)} because it will also remove the
* association from database.
*
* @param fleet
*/
void removeRaceIdentifier(Fleet fleet);
}
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.base.impl;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
@@ -12,6 +13,7 @@ import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogEventVisitor;
import com.sap.sailing.domain.racelog.RaceLogIdentifier;
import com.sap.sailing.domain.racelog.RaceLogIdentifierTemplate;
import com.sap.sailing.domain.racelog.RaceLogInformation;
@@ -28,11 +30,12 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
private final Map<Fleet, RaceLog> raceLogs;
/**
* holds the race log identifer template needed to create the appropriate RaceLogIdentifer that is constructed from the
* holds the race log identifier template needed to create the appropriate RaceLogIdentifer that is constructed from the
* parent object name, name of this raceColumn and the name of a fleet of this raceColumn to access the RaceLog in the
* RaceLogStore for persistence purposes.
*/
private RaceLogIdentifierTemplate raceLogsIdentifierTemplate;
private transient RaceLogInformation raceLogInformation;
private RaceLogIdentifierTemplate raceLogIdentifierTemplate;
public AbstractRaceColumn() {
this.trackedRaces = new HashMap<Fleet, TrackedRace>();
@@ -42,25 +45,21 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
@Override
public synchronized void setRaceLogInformation(final RaceLogInformation information) {
raceLogs.clear();
raceLogsIdentifierTemplate = information.getIdentifierTemplate();
RaceLogStore store = information.getStore();
for (final Fleet fleet : getFleets()) {
RaceLogIdentifier identifier = raceLogsIdentifierTemplate.compileRaceLogIdentifier(fleet);
RaceLog raceLog = store.getRaceLog(identifier);
raceLog.addListener(new RaceColumnRaceLogReplicator(this, identifier));
raceLogs.put(fleet, raceLog);
setOrReloadRaceLogInformation(information, fleet);
}
}
@Override
public RaceLog getRaceLog(Fleet fleet) {
return raceLogs.get(fleet);
synchronized (raceLogs) {
return raceLogs.get(fleet);
}
}
@Override
public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) {
return new RaceLogIdentifierImpl(raceLogsIdentifierTemplate, getName(), fleet);
return new RaceLogIdentifierImpl(raceLogInformation.getIdentifierTemplate(), getName(), fleet);
}
@Override
@@ -72,20 +71,13 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
public void setTrackedRace(Fleet fleet, TrackedRace trackedRace) {
TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet);
if (trackedRace != previouslyLinkedRace) {
releaseTrackedRace(fleet);
synchronized (this) {
if (trackedRace == null) {
setRaceIdentifier(fleet, null);
this.trackedRaces.remove(fleet);
} else {
if (trackedRace != null) {
this.trackedRaces.put(fleet, trackedRace);
this.setRaceIdentifier(fleet, trackedRace.getRaceIdentifier());
}
}
if (previouslyLinkedRace != null) {
RaceLogIdentifierImpl identifier = new RaceLogIdentifierImpl(raceLogsIdentifierTemplate, getName(), fleet);
previouslyLinkedRace.detachRaceLog(identifier);
getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(this, fleet, previouslyLinkedRace);
}
if (trackedRace != null) {
trackedRace.attachRaceLog(getRaceLog(fleet));
getRaceColumnListeners().notifyListenersAboutTrackedRaceLinked(this, fleet, trackedRace);
@@ -100,18 +92,28 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
@Override
public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) {
if (raceIdentifier == null) {
this.raceIdentifiers.remove(fleet);
} else {
if (raceIdentifier != null) {
this.raceIdentifiers.put(fleet, raceIdentifier);
}
}
@Override
public synchronized void releaseTrackedRace(Fleet fleet) {
setTrackedRace(fleet, null);
TrackedRace previouslyLinkedRace = this.trackedRaces.get(fleet);
this.trackedRaces.remove(fleet);
if (previouslyLinkedRace != null) {
RaceLogIdentifierImpl identifier = new RaceLogIdentifierImpl(raceLogInformation.getIdentifierTemplate(), getName(), fleet);
previouslyLinkedRace.detachRaceLog(identifier);
getRaceColumnListeners().notifyListenersAboutTrackedRaceUnlinked(this, fleet, previouslyLinkedRace);
}
}
@Override
public void removeRaceIdentifier(Fleet fleet) {
releaseTrackedRace(fleet);
this.raceIdentifiers.remove(fleet);
}
@Override
public Fleet getFleetOfCompetitor(Competitor competitor) {
for (Map.Entry<Fleet, TrackedRace> e : trackedRaces.entrySet()) {
@@ -146,22 +148,53 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
}
return null;
}
@Override
public String toString() {
return getName();
}
@Override
public RaceLogInformation getRaceLogInformation() {
return raceLogInformation;
}
@Override
public void setOrReloadRaceLogInformation(RaceLogInformation information, Fleet fleetImpl) {
synchronized(raceLogs) {
raceLogInformation = information;
RaceLogStore store = information.getStore();
HashSet<RaceLogEventVisitor> listeners = new HashSet<RaceLogEventVisitor>();
RaceLog raceLogAvailable = raceLogs.get(fleetImpl);
if (raceLogAvailable != null) {
store.removeListenersAddedByStoreFrom(raceLogAvailable);
listeners = raceLogAvailable.removeAllListeners();
raceLogs.remove(fleetImpl);
}
raceLogIdentifierTemplate = raceLogInformation.getIdentifierTemplate();
RaceLogIdentifier identifier = raceLogIdentifierTemplate.compileRaceLogIdentifier(fleetImpl);
RaceLog raceLog = store.getRaceLog(identifier, /*ignoreCache*/ true);
if (listeners.isEmpty()) {
RaceColumnRaceLogReplicator listener = new RaceColumnRaceLogReplicator(this, identifier);
raceLog.addListener(listener);
} else {
raceLog.addAllListeners(listeners);
}
raceLogs.put(fleetImpl, raceLog);
}
}
/**
* When deserializing, replication listeners are registered on all race logs.
*/
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
for (Entry<Fleet, RaceLog> entry : raceLogs.entrySet()) {
Fleet fleet = entry.getKey();
RaceLog raceLog = entry.getValue();
raceLog.addListener(new RaceColumnRaceLogReplicator(this, raceLogsIdentifierTemplate.compileRaceLogIdentifier(fleet)));
raceLog.addListener(new RaceColumnRaceLogReplicator(this, raceLogIdentifierTemplate.compileRaceLogIdentifier(fleet)));
}
}
}
@@ -106,4 +106,9 @@ public class RaceColumnInSeriesImpl extends AbstractRaceColumn implements RaceCo
public boolean isDiscardable() {
return !isMedalRace() && (!isFirstColumnInSeries() || !getSeries().isFirstColumnIsNonDiscardableCarryForward());
}
@Override
public boolean isCarryForward() {
return isFirstColumnInSeries() && getSeries().isFirstColumnIsNonDiscardableCarryForward();
}
}
@@ -90,4 +90,9 @@ public abstract class SimpleAbstractRaceColumn implements RaceColumn {
return !isMedalRace();
}
@Override
public boolean isCarryForward() {
return false;
}
}
@@ -127,8 +127,15 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
o2ScoreSum += o2Score;
}
if (raceColumn.isMedalRace()) {
o1MedalRaceScore = o1Score;
o2MedalRaceScore = o2Score;
// only count the score for the medal race score if it wasn't a carry-forward column
if (!raceColumn.isCarryForward()) {
if (o1Score != null) {
o1MedalRaceScore += o1Score;
}
if (o2Score != null) {
o2MedalRaceScore += o2Score;
}
}
// similar to compareByFleet, however, tracking is not required; having medal race column points
// (tracked or manual) is sufficient
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
@@ -180,4 +180,17 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
public RaceLogIdentifier getRaceLogIdentifier(Fleet fleet) {
return null;
}
@Override
public RaceLogInformation getRaceLogInformation() {
return null;
}
@Override
public void setOrReloadRaceLogInformation(RaceLogInformation raceLogInformation, Fleet fleetImpl) {
}
@Override
public void removeRaceIdentifier(Fleet fleet) {
}
}
@@ -34,4 +34,6 @@ public interface RaceLogIdentifierTemplate extends Serializable {
* @param resolver the resolver that resolves this template, either for {@link Leaderboard} or for {@link Regatta}.
*/
void resolve(RaceLogIdentifierTemplateResolver resolver);
String getRaceColumnName();
}
@@ -34,4 +34,5 @@ public interface RaceLogInformation {
* and {@link Fleet}
*/
RaceLog getRaceLog(RaceColumn raceColumn, Fleet fleet);
}
@@ -3,6 +3,8 @@ package com.sap.sailing.domain.racelog;
public interface RaceLogStore {
RaceLog getRaceLog(RaceLogIdentifier identifier);
RaceLog getRaceLog(RaceLogIdentifier identifier, boolean ignoreCache);
void removeListenersAddedByStoreFrom(RaceLog raceLogAvailable);
}
@@ -11,7 +11,11 @@ public enum EmptyRaceLogStore implements RaceLogStore {
INSTANCE;
@Override
public RaceLog getRaceLog(RaceLogIdentifier identifier) {
public RaceLog getRaceLog(RaceLogIdentifier identifier, boolean ignoreCache) {
return new RaceLogImpl(UUID.randomUUID().toString(), identifier.getIdentifier());
}
@Override
public void removeListenersAddedByStoreFrom(RaceLog raceLogAvailable) {
}
}
@@ -29,7 +29,7 @@ public class RaceLogInformationImpl implements RaceLogInformation {
@Override
public RaceLog getRaceLog(RaceColumn raceColumn, Fleet fleet) {
return store.getRaceLog(identifierTemplate.compileRaceLogIdentifier(fleet));
return store.getRaceLog(identifierTemplate.compileRaceLogIdentifier(fleet), false);
}
}
@@ -32,4 +32,9 @@ public class RaceLogOnLeaderboardIdentifier implements RaceLogIdentifierTemplate
return leaderboardName;
}
@Override
public String getRaceColumnName() {
return raceColumnName;
}
}
@@ -32,4 +32,9 @@ public class RaceLogOnRegattaIdentifier implements RaceLogIdentifierTemplate {
return regattaName;
}
@Override
public String getRaceColumnName() {
return raceColumnName;
}
}
@@ -323,9 +323,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
try {
final Map<? extends WindSource, ? extends WindTrack> loadedWindTracks = windStore.loadWindTracks(
trackedRegatta, TrackedRaceImpl.this, millisecondsOverWhichToAverageWind);
synchronized (windTracks) {
windTracks.putAll(loadedWindTracks);
}
windTracks.putAll(loadedWindTracks);
} finally {
LockUtil.unlockAfterRead(serializationLock);
synchronized (TrackedRaceImpl.this) {
@@ -2257,9 +2255,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
public Iterable<WindSource> getWindSources() {
while (true) {
try {
synchronized (windTracks) {
return new HashSet<WindSource>(windTracks.keySet());
}
return new HashSet<WindSource>(windTracks.keySet());
} catch (ConcurrentModificationException cme) {
logger.info("Caught " + cme + "; trying again.");
}
@@ -17,6 +17,12 @@ interface AdminConsoleResources extends ClientBundle {
@Source("com/sap/sailing/gwt/ui/client/images/edit.png")
ImageResource editIcon();
@Source("com/sap/sailing/gwt/ui/client/images/import.png")
ImageResource importIcon();
@Source("com/sap/sailing/gwt/ui/client/images/reload.png")
ImageResource reloadIcon();
@Source("com/sap/sailing/gwt/ui/client/images/link.png")
ImageResource linkIcon();
@@ -413,10 +413,21 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
trackedRacesPanel.add(trackedRacesListComposite);
trackedRacesListComposite.addTrackedRaceChangeListener(this);
raceSelectionProvider.addRaceSelectionChangeListener(this);
HorizontalPanel hPanel = new HorizontalPanel();
hPanel.setSpacing(5);
vPanel.add(hPanel);
Button reloadAllRaceLogs = new Button(stringMessages.reloadAllRaceLogs());
reloadAllRaceLogs.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
StrippedLeaderboardDTO leaderboard = getSelectedLeaderboard();
for (RaceColumnDTO column : leaderboard.getRaceList()) {
for (FleetDTO fleet : column.getFleets()) {
refreshRaceLog(column, fleet, false);
}
}
Window.alert(stringMessages.raceLogReloaded());
}
});
vPanel.add(reloadAllRaceLogs);
// ------------ races of the selected leaderboard ----------------
AnchorCell raceAnchorCell = new AnchorCell();
@@ -492,6 +503,8 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
editRaceColumnOfLeaderboard(object);
} else if (LeaderboardRaceConfigImagesBarCell.ACTION_UNLINK.equals(value)) {
unlinkRaceColumnFromTrackedRace(object.getA().getRaceColumnName(), object.getB());
} else if (LeaderboardRaceConfigImagesBarCell.ACTION_REFRESH_RACELOG.equals(value)) {
refreshRaceLog(object.getA(), object.getB(), false);
}
}
});
@@ -675,6 +688,24 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb
}
});
}
private void refreshRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleet, final boolean showAlerts) {
final String selectedLeaderboardName = getSelectedLeaderboardName();
sailingService.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
if (showAlerts) {
errorReporter.reportError(caught.getMessage());
}
}
@Override
public void onSuccess(Void result) {
if (showAlerts) {
Window.alert(stringMessages.raceLogReloaded());
}
}
});
}
private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) {
final String selectedLeaderboardName = getSelectedLeaderboardName();
@@ -11,6 +11,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell {
public static final String ACTION_REMOVE = "ACTION_REMOVE";
public static final String ACTION_UNLINK = "ACTION_UNLINK";
public static final String ACTION_EDIT = "ACTION_EDIT";
public final static String ACTION_REFRESH_RACELOG = "ACTION_REFRESH_RACE_LOG";
private final StringMessages stringMessages;
private final SelectedLeaderboardProvider selectedLeaderboardProvider;
private static AdminConsoleResources resources = GWT.create(AdminConsoleResources.class);
@@ -31,6 +32,7 @@ public class LeaderboardRaceConfigImagesBarCell extends ImagesBarCell {
// race columns cannot be removed from a regatta leaderboard; they need to be removed from the regatta instead
result.add(new ImageSpec(ACTION_REMOVE, stringMessages.actionRaceRemove(), makeImagePrototype(resources.removeIcon())));
}
result.add(new ImageSpec(ACTION_REFRESH_RACELOG, stringMessages.refreshRaceLog(), makeImagePrototype(resources.reloadIcon())));
return result;
}
}
@@ -21,7 +21,9 @@ import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
@@ -315,4 +317,6 @@ public interface SailingService extends RemoteService {
void stopAllReplicas();
void stopSingleReplicaInstance(String identifier);
void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet);
}
@@ -21,7 +21,9 @@ import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
@@ -435,6 +437,9 @@ public interface SailingServiceAsync {
void stopAllReplicas(AsyncCallback<Void> asyncCallback);
void stopSingleReplicaInstance(String identifier, AsyncCallback<Void> asyncCallback);
void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet,
AsyncCallback<Void> asyncCallback);
}
@@ -689,4 +689,7 @@ public interface StringMessages extends Messages {
String earlyStarters();
String noMoreRacingToday();
String furtherSignalsAshore();
String refreshRaceLog();
String raceLogReloaded();
String reloadAllRaceLogs();
}
@@ -681,4 +681,7 @@ flags=Flags
lastUpdate=Last update
noMoreRacingToday=No more racing today
furtherSignalsAshore=Further signals ashore
earlyStarters=Early starters
earlyStarters=Early starters
refreshRaceLog=Refresh race log
raceLogReloaded=RaceLog successfully reloaded from database
reloadAllRaceLogs=Reload all race logs
@@ -679,4 +679,7 @@ raceIsScheduled=Start angesetzt
raceIsFinished=Beendet
raceIsFinishing=Zieleinlauf
raceIsRunning=Rennen läuft
earlyStarters=Frühstarter
earlyStarters=Frühstarter
refreshRaceLog=RaceLog neu laden
raceLogReloaded=RaceLog wurde neu geladen
reloadAllRaceLogs=Alle RaceLogs neu laden
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.ui.client.shared.filter;
import java.util.List;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.dto.CompetitorDTO;
import com.sap.sailing.domain.common.dto.LeaderboardDTO;
@@ -32,21 +34,31 @@ public class CompetitorRaceRankFilter extends AbstractNumberFilter<CompetitorDTO
public boolean matches(CompetitorDTO competitorDTO) {
boolean result = false;
if (value != null && operator != null && getLeaderboard() != null && getSelectedRace() != null) {
RaceColumnDTO theRaceColumnDTO = null;
RaceColumnDTO theRaceColumnDTOThatContainsCompetitorRace = null;
for (RaceColumnDTO raceColumnDTO : getLeaderboard().getRaceList()) {
if (raceColumnDTO.containsRace(getSelectedRace())) {
theRaceColumnDTO = raceColumnDTO;
theRaceColumnDTOThatContainsCompetitorRace = raceColumnDTO;
break;
}
}
if (theRaceColumnDTO != null && getLeaderboard().rows.get(competitorDTO) != null) {
LeaderboardEntryDTO entryDTO = getLeaderboard().rows.get(competitorDTO).fieldsByRaceColumnName.get(theRaceColumnDTO.getName());
if (entryDTO.totalPoints != null || !theRaceColumnDTO.isLiveInServerTime(entryDTO.fleet)) {
int raceRank = getLeaderboard().getCompetitorsFromBestToWorst(theRaceColumnDTO).indexOf(competitorDTO)+1;
if (raceRank > 0) {
result = operator.matchValues(value, raceRank);
List<CompetitorDTO> competitors = getLeaderboard().getCompetitorsFromBestToWorst(theRaceColumnDTOThatContainsCompetitorRace);
if (theRaceColumnDTOThatContainsCompetitorRace != null && getLeaderboard().rows.get(competitorDTO) != null) {
LeaderboardEntryDTO entryDTO = getLeaderboard().rows.get(competitorDTO).fieldsByRaceColumnName.get(theRaceColumnDTOThatContainsCompetitorRace.getName());
int counter = 0; int raceRank = 0;
for (CompetitorDTO competitorDTOIterated : competitors) {
LeaderboardEntryDTO entryDTOIterated = getLeaderboard().rows.get(competitorDTOIterated).fieldsByRaceColumnName.get(theRaceColumnDTOThatContainsCompetitorRace.getName());
if (entryDTOIterated.fleet.equals(entryDTO.fleet)) {
counter += 1;
if (competitorDTOIterated.equals(competitorDTO)) {
raceRank = counter;
break;
}
}
}
if (raceRank > 0) {
result = operator.matchValues(value, raceRank);
}
}
}
return result;
@@ -3109,4 +3109,9 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
throw new RuntimeException(e);
}
}
@Override
public void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet) {
getService().reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

@@ -12,6 +12,7 @@ import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.CompetitorGenderType;
import com.sap.sailing.util.DateParser;
import com.sap.sailing.util.InvalidDateException;
@@ -39,6 +40,7 @@ public class Manage2SailEventResultsParser {
regattaResult.setIsafId((String) jsonRegatta.get("IsafId"));
regattaResult.setExternalId((String) jsonRegatta.get("ExternalId"));
regattaResult.setName((String) jsonRegatta.get("Name"));
regattaResult.setCompetitorGenderType(parseCompetitorGenderType(jsonRegatta, "Gender"));
regattaResult.setClassName((String) jsonRegatta.get("ClassName"));
regattaResult.setPdfUrl(parseURL(jsonRegatta, "PdfUrl"));
regattaResult.setXrrPreliminaryUrl(parseURL(jsonRegatta, "XrrPreliminaryUrl"));
@@ -56,6 +58,20 @@ public class Manage2SailEventResultsParser {
}
return result;
}
private CompetitorGenderType parseCompetitorGenderType(JSONObject jsonDate, String attributeName) {
CompetitorGenderType result = null;
String genderTypeAsString = (String) jsonDate.get(attributeName);
if(genderTypeAsString != null) {
switch(genderTypeAsString) {
case "M" : result = CompetitorGenderType.Men; break;
case "W" : result = CompetitorGenderType.Women; break;
case "X" : result = CompetitorGenderType.Mixed; break;
case "Open" : result = CompetitorGenderType.Open; break;
}
}
return result;
}
private Date parseDate(JSONObject jsonDate, String attributeName) {
Date result = null;
@@ -40,12 +40,12 @@ public class Manage2SailResultDocumentProvider implements ResultDocumentProvider
URLConnection regattaResultConn = regattaResult.getXrrFinalUrl().openConnection();
result.add(new ResultDocumentDescriptorImpl((InputStream) regattaResultConn.getContent(),
regattaResult.getXrrPreliminaryUrl().toString(), new MillisecondsTimePoint(regattaResult.getPublishedAt()),
eventResult.getName(), regattaResult.getName(), boatClass));
eventResult.getName(), regattaResult.getName(), boatClass, regattaResult.getCompetitorGenderType()));
} else if (regattaResult.getXrrPreliminaryUrl() != null) {
URLConnection regattaResultConn = regattaResult.getXrrPreliminaryUrl().openConnection();
result.add(new ResultDocumentDescriptorImpl((InputStream) regattaResultConn.getContent(),
regattaResult.getXrrPreliminaryUrl().toString(), new MillisecondsTimePoint(regattaResult.getPublishedAt()),
eventResult.getName(), regattaResult.getName(), boatClass));
eventResult.getName(), regattaResult.getName(), boatClass, regattaResult.getCompetitorGenderType()));
}
}
}
@@ -3,12 +3,15 @@ package com.sap.sailing.manage2sail.resultimport;
import java.net.URL;
import java.util.Date;
import com.sap.sailing.domain.common.CompetitorGenderType;
public class RegattaResultDescriptor {
private String id;
private String isafId;
private String externalId;
private String name;
private String className;
private CompetitorGenderType competitorGenderType;
private URL pdfUrl;
private URL xrrPreliminaryUrl;
private URL xrrFinalUrl;
@@ -82,4 +85,10 @@ public class RegattaResultDescriptor {
public void setIsFinal(Boolean isFinal) {
this.isFinal = isFinal;
}
public CompetitorGenderType getCompetitorGenderType() {
return competitorGenderType;
}
public void setCompetitorGenderType(CompetitorGenderType competitorGenderType) {
this.competitorGenderType = competitorGenderType;
}
}
@@ -26,6 +26,7 @@ import com.sap.sailing.xrr.resultimport.ParserFactory;
import com.sap.sailing.xrr.resultimport.impl.XRRRegattaResultsAsScoreCorrections;
import com.sap.sailing.xrr.resultimport.schema.Division;
import com.sap.sailing.xrr.resultimport.schema.Event;
import com.sap.sailing.xrr.resultimport.schema.EventGender;
import com.sap.sailing.xrr.resultimport.schema.RegattaResults;
public class ScoreCorrectionProviderImpl implements ScoreCorrectionProvider, ResultUrlProvider {
@@ -63,6 +64,9 @@ public class ScoreCorrectionProviderImpl implements ScoreCorrectionProvider, Res
String eventName = resultDocDescr.getEventName() != null ? resultDocDescr.getEventName() : resultDocDescr.getRegattaName();
String boatClass = resultDocDescr.getBoatClass();
if(boatClass != null && eventName != null) {
if(resultDocDescr.getCompetitorGenderType() != null) {
boatClass += ", " + resultDocDescr.getCompetitorGenderType().name();
}
Set<Pair<String, TimePoint>> eventResultsSet = result.get(eventName);
if(eventResultsSet == null) {
eventResultsSet = new HashSet<Pair<String, TimePoint>>();
@@ -92,7 +96,12 @@ public class ScoreCorrectionProviderImpl implements ScoreCorrectionProvider, Res
for (Object eventO : event.getRaceOrDivisionOrRegattaSeriesResult()) {
if (eventO instanceof Division) {
Division division = (Division) eventO;
if (boatClassName.equals(parser.getBoatClassName(division))) {
EventGender divisionGender = division.getGender();
String divisionBoatClassAndGender = parser.getBoatClassName(division);
if(divisionGender != null) {
divisionBoatClassAndGender += ", " + divisionGender.name();
}
if (boatClassName.equalsIgnoreCase(divisionBoatClassAndGender)) {
return new XRRRegattaResultsAsScoreCorrections(event, division, this,
parser);
}
@@ -112,7 +121,11 @@ public class ScoreCorrectionProviderImpl implements ScoreCorrectionProvider, Res
private Parser resolveParser(String eventName, String boatClassName) throws IOException {
Parser result = null;
for (ResultDocumentDescriptor resultDocDescr : documentProvider.getResultDocumentDescriptors()) {
if(eventName.equals(resultDocDescr.getEventName()) && boatClassName.equals(resultDocDescr.getBoatClass())) {
String boatClassAndGenderType = resultDocDescr.getBoatClass();
if(resultDocDescr.getCompetitorGenderType() != null) {
boatClassAndGenderType += ", " + resultDocDescr.getCompetitorGenderType().name();
}
if(eventName.equals(resultDocDescr.getEventName()) && boatClassName.equals(boatClassAndGenderType)) {
result = parserFactory.createParser(resultDocDescr.getInputStream(), resultDocDescr.getEventName());
break;
}
@@ -2,12 +2,14 @@ package com.sap.sailing.resultimport;
import java.io.InputStream;
import com.sap.sailing.domain.common.CompetitorGenderType;
import com.sap.sailing.domain.common.TimePoint;
public interface ResultDocumentDescriptor {
String getEventName();
String getRegattaName();
String getBoatClass();
CompetitorGenderType getCompetitorGenderType();
TimePoint getLastModified();
@@ -2,6 +2,7 @@ package com.sap.sailing.resultimport.impl;
import java.io.InputStream;
import com.sap.sailing.domain.common.CompetitorGenderType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.resultimport.ResultDocumentDescriptor;
@@ -12,29 +13,36 @@ public class ResultDocumentDescriptorImpl implements ResultDocumentDescriptor {
private String eventName;
private String regattaName;
private String boatClass;
private CompetitorGenderType competitorGenderType;
public ResultDocumentDescriptorImpl(InputStream inputStream, String documentName, TimePoint lastModified) {
this(inputStream, documentName, lastModified, null, null, null);
this(inputStream, documentName, lastModified, null, null, null, null);
}
public ResultDocumentDescriptorImpl(InputStream inputStream, String documentName, TimePoint lastModified,
String eventName) {
this(inputStream, documentName, lastModified, eventName, null, null);
this(inputStream, documentName, lastModified, eventName, null, null, null);
}
public ResultDocumentDescriptorImpl(InputStream inputStream, String documentName, TimePoint lastModified,
String eventName, String regattaName) {
this(inputStream, documentName, lastModified, eventName, regattaName, null);
this(inputStream, documentName, lastModified, eventName, regattaName, null, null);
}
public ResultDocumentDescriptorImpl(InputStream inputStream, String documentName, TimePoint lastModified,
String eventName, String regattaName, String boatClass) {
this(inputStream, documentName, lastModified, eventName, regattaName, boatClass, null);
}
public ResultDocumentDescriptorImpl(InputStream inputStream, String documentName, TimePoint lastModified,
String eventName, String regattaName, String boatClass, CompetitorGenderType competitorGenderType) {
this.inputStream = inputStream;
this.lastModified = lastModified;
this.documentName = documentName;
this.eventName = eventName;
this.regattaName = regattaName;
this.boatClass = boatClass;
this.competitorGenderType = competitorGenderType;
}
@Override
@@ -66,4 +74,8 @@ public class ResultDocumentDescriptorImpl implements ResultDocumentDescriptor {
public String getDocumentName() {
return documentName;
}
public CompetitorGenderType getCompetitorGenderType() {
return competitorGenderType;
}
}
@@ -32,6 +32,8 @@ import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.RegattaName;
import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.common.media.MediaTrack;
@@ -523,4 +525,6 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
Collection<MediaTrack> getAllMediaTracks();
void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet);
}
@@ -54,6 +54,7 @@ import com.sap.sailing.domain.common.ScoringSchemeType;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO;
import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO;
import com.sap.sailing.domain.common.impl.Util;
@@ -81,6 +82,7 @@ import com.sap.sailing.domain.persistence.MongoRaceLogStoreFactory;
import com.sap.sailing.domain.persistence.media.DBMediaTrack;
import com.sap.sailing.domain.persistence.media.MediaDB;
import com.sap.sailing.domain.persistence.media.MediaDBFactory;
import com.sap.sailing.domain.racelog.RaceLog;
import com.sap.sailing.domain.racelog.RaceLogStore;
import com.sap.sailing.domain.swisstimingadapter.Race;
import com.sap.sailing.domain.swisstimingadapter.SailMasterConnector;
@@ -715,7 +717,9 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
logger.info("Retrieving TracTrac race records from " + jsonURL);
JSONService jsonService = getTracTracDomainFactory().parseJSONURL(jsonURL);
logger.info("OK retrieving TracTrac race records from " + jsonURL);
return new Pair<String, List<RaceRecord>>(jsonService.getEventName(), jsonService.getRaceRecords());
}
@@ -1957,4 +1961,20 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
return "RacingEventService: " + this.hashCode() + " Build: " + BuildVersion.getBuildVersion();
}
@Override
public void reloadRaceLog(String selectedLeaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet) {
Leaderboard leaderboard = getLeaderboardByName(selectedLeaderboardName);
if (leaderboard != null) {
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnDTO.getName());
if (raceColumn != null) {
Fleet fleetImpl = raceColumn.getFleetByName(fleet.getName());
RaceLog racelog = raceColumn.getRaceLog(fleetImpl);
if (racelog != null) {
raceColumn.setOrReloadRaceLogInformation(raceColumn.getRaceLogInformation(), fleetImpl);
logger.info("Reloaded race log for fleet " + fleetImpl + " for race column " + raceColumn.getName() + " for leaderboard " + leaderboard.getName());
}
}
}
}
}
@@ -21,7 +21,7 @@ public class DisconnectLeaderboardColumnFromTrackedRace extends AbstractLeaderbo
if (leaderboard != null) {
RaceColumn raceColumn = leaderboard.getRaceColumnByName(getColumnName());
if (raceColumn != null) {
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), null);
raceColumn.removeRaceIdentifier(raceColumn.getFleetByName(fleetName));
updateDB(toState, leaderboard, raceColumn);
} else {
throw new IllegalArgumentException("Didn't find race "+getColumnName()+" in leaderboard "+getLeaderboardName());
@@ -9,6 +9,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class UDPReceiver<MessageType extends UDPMessage, ListenerType extends UDPMessageListener<MessageType>> implements Runnable {
@@ -136,9 +137,10 @@ public abstract class UDPReceiver<MessageType extends UDPMessage, ListenerType e
}
}
} catch (IOException e) {
e.printStackTrace();
logger.log(Level.SEVERE, "Exception while receiving UDP packet", e);
}
}
logger.info("Closing UDP socket on port "+udpSocket.getPort());
udpSocket.close();
if (udpSocket.isConnected()) {
udpSocket.disconnect();