Merge branch 'master' into mak-change-timepanel-controls

This commit is contained in:
Marcus Kammer committed 2012-05-22 11:45:06 +02:00
commit 6b4325a32d
85 files changed
+1808 -978

No files matched your search

@@ -30,7 +30,7 @@ public class RegattaNameAndRaceName extends RegattaName implements RegattaAndRac
}
@Override
public String toString() {
return raceName;
return getRegattaName()+"/"+getRaceName();
}
@Override
@@ -3,8 +3,9 @@ package com.sap.sailing.domain.persistence;
import java.util.Map;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.leaderboard.Leaderboard;
@@ -44,4 +45,7 @@ public interface DomainObjectFactory {
Map<? extends WindSource, ? extends WindTrack> loadWindTracks(Regatta regatta, RaceDefinition race,
long millisecondsOverWhichToAverageWind);
Event loadEvent(String name);
Regatta loadRegatta(String name);
}
@@ -1,14 +1,14 @@
package com.sap.sailing.domain.persistence;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
/**
* Offers methods to construct {@link DBObject MongoDB objects} from domain objects.
@@ -37,8 +37,6 @@ public interface MongoObjectFactory {
void renameLeaderboard(String oldName, String newName);
void storeRaceIdentifier(RaceIdentifier raceIdentifier, DBObject dbObject);
/**
* Stores the group, if it doesn't exist or updates it.<br />
* Leaderboards in the group, which aren't stored in the database, will be stored.
@@ -55,4 +53,16 @@ public interface MongoObjectFactory {
*/
void renameLeaderboardGroup(String oldName, String newName);
/**
* Stores the event with its name, venue and the venue's course areas. The regattas obtained by
* {@link Event#getRegattas()} are <em>not</em> stored by this call. They need to be stored separately
* by calls to {@link #storeRegatta} where a reference to their owning event is stored.
*/
void storeEvent(Event event);
/**
* Stores the regatta together with its name, {@link Series} definitions and an optional link to the
* {@link Event} to which the regatta belongs.
*/
void storeRegatta(Regatta regatta);
}
@@ -1,5 +1,43 @@
package com.sap.sailing.domain.persistence.impl;
/**
* Defines literals providing the names for MongoDB collections. The literal documentation described the semantics
* of the collection identified by that literal.
*
* @author Axel Uhl (D043530)
*
*/
public enum CollectionNames {
WIND_TRACKS, LEADERBOARDS, LEADERBOARD_GROUPS;
/**
* Stores the wind fixes recorded from persistent wind sources.
*/
WIND_TRACKS,
/**
* Stores the leaderboards with their names, score corrections, competitor display name overrides, race
* columns and their fleets as well as the per-fleet tracked race assignments.
*/
LEADERBOARDS,
/**
* Stores the leaderboard group configurations with references to the {@link #LEADERBOARDS} collection
*/
LEADERBOARD_GROUPS,
/**
* Top-level event information about events such as Kiel Week 2011, or IDM Travemünde 2011, including name and
* course areas.
*/
EVENTS,
/**
* Stores regatta definitions including their series layout and fleets and race columns. Regattas can reference
* the event from the {@link #EVENTS} collection to which they belong.
*/
REGATTAS,
/**
* Stores boat class-specific master data such as the class's hull length, logo, name, number of sailors, etc.
*/
BOAT_CLASSES;
}
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.persistence.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
@@ -15,15 +16,23 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.base.impl.VenueImpl;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Position;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.WindSourceType;
@@ -155,14 +164,43 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
discardIndexResultsStartingWithHowManyRaces[i++] = (Integer) discardingThresholdAsObject;
}
ThresholdBasedResultDiscardingRule resultDiscardingRule = new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces);
LeaderboardImplWithDelayedCarriedPoints result = new LeaderboardImplWithDelayedCarriedPoints(
FlexibleLeaderboardImplWithDelayedCarriedPoints result = new FlexibleLeaderboardImplWithDelayedCarriedPoints(
(String) o.get(FieldNames.LEADERBOARD_NAME.name()), scoreCorrection, resultDiscardingRule);
BasicDBList dbRaceColumns = (BasicDBList) o.get(FieldNames.LEADERBOARD_COLUMNS.name());
// For a FlexibleLeaderboard, fleets are owned by the leaderboard's RaceColumn objects. We need to manage them here:
Map<String, Fleet> fleetsByName = new HashMap<String, Fleet>();
for (Object dbRaceColumnAsObject : dbRaceColumns) {
BasicDBObject dbRaceColumn = (BasicDBObject) dbRaceColumnAsObject;
Map<String, RaceIdentifier> raceIdentifiers = loadRaceIdentifiers(dbRaceColumn);
RaceIdentifier defaultFleetRaceIdentifier = raceIdentifiers.get(null);
if (defaultFleetRaceIdentifier != null) {
Fleet defaultFleet = result.getFleet(null);
if (defaultFleet != null) {
raceIdentifiers.put(defaultFleet.getName(), defaultFleetRaceIdentifier);
} else {
// leaderboard has no default fleet; don't know what to do with default RaceIdentifier
logger.warning("Discarding RaceIdentifier "+defaultFleetRaceIdentifier+" for default fleet for leaderboard "+result.getName()+
" because no default fleet was found in leaderboard");
}
raceIdentifiers.remove(null);
}
List<Fleet> fleets = new ArrayList<Fleet>();
for (String fleetName : raceIdentifiers.keySet()) {
Fleet fleet = fleetsByName.get(fleetName);
if (fleet == null) {
fleet = new FleetImpl(fleetName);
fleetsByName.put(fleetName, fleet);
}
fleets.add(fleet);
}
if (fleets.isEmpty()) {
fleets.add(result.getFleet(null));
}
RaceColumn raceColumn = result.addRaceColumn((String) dbRaceColumn.get(FieldNames.LEADERBOARD_COLUMN_NAME.name()),
(Boolean) dbRaceColumn.get(FieldNames.LEADERBOARD_IS_MEDAL_RACE_COLUMN.name()));
raceColumn.setRaceIdentifier(loadRaceIdentifier(dbRaceColumn));
(Boolean) dbRaceColumn.get(FieldNames.LEADERBOARD_IS_MEDAL_RACE_COLUMN.name()), fleets.toArray(new Fleet[0]));
for (Map.Entry<String, RaceIdentifier> e : raceIdentifiers.entrySet()) {
raceColumn.setRaceIdentifier(fleetsByName.get(e.getKey()), e.getValue());
}
}
DBObject carriedPoints = (DBObject) o.get(FieldNames.LEADERBOARD_CARRIED_POINTS.name());
if (carriedPoints != null) {
@@ -199,6 +237,33 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return result;
}
/**
* Expects a DBObject under the key {@link FieldNames#RACE_IDENTIFIERS} whose keys are the fleet names and whose
* values are the race identifiers as DBObjects (see {@link #loadRaceIdentifier(DBObject)}). If legacy DB instances
* have a {@link RaceIdentifier} that is not associated with a fleet name, it may be stored directly in the
* <code>dbRaceColumn</code>. In this case, it is returned with <code>null</code> as the fleet name key.
*
* @return a map with fleet names as key and the corresponding fleet's race identifier as value; the special
* <code>null</code> key is used to identify a "default fleet" for backward compatibility with stored
* leaderboards which don't know about fleets yet; this key should be mapped to the leaderboard's default
* fleet.
*/
private Map<String, RaceIdentifier> loadRaceIdentifiers(BasicDBObject dbRaceColumn) {
Map<String, RaceIdentifier> result = new HashMap<String, RaceIdentifier>();
// try to load a deprecated single race identifier to associate with the default fleet:
RaceIdentifier singleLegacyRaceIdentifier = loadRaceIdentifier(dbRaceColumn);
if (singleLegacyRaceIdentifier != null) {
result.put(null, singleLegacyRaceIdentifier);
}
DBObject raceIdentifiersPerFleet = (DBObject) dbRaceColumn.get(FieldNames.RACE_IDENTIFIERS.name());
if (raceIdentifiersPerFleet != null) {
for (String fleetName : raceIdentifiersPerFleet.keySet()) {
result.put(fleetName, loadRaceIdentifier((DBObject) raceIdentifiersPerFleet.get(fleetName)));
}
}
return result;
}
@Override
public LeaderboardGroup loadLeaderboardGroup(String name) {
DBCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name());
@@ -304,4 +369,52 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
return result;
}
@Override
public Event loadEvent(String name) {
Event result;
BasicDBObject query = new BasicDBObject();
query.put(FieldNames.EVENT_NAME.name(), name);
DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name());
DBObject eventDBObject = eventCollection.findOne(query);
if (eventDBObject != null) {
result = loadEvent(eventDBObject);
} else {
result = null;
}
return result;
}
/**
* An event doesn't store its regattas; it's the regatta that stores a reference to its event; the regatta
* needs to add itself to the event when loaded or instantiated.
*/
private Event loadEvent(DBObject eventDBObject) {
String name = (String) eventDBObject.get(FieldNames.EVENT_NAME.name());
Venue venue = loadVenue((DBObject) eventDBObject.get(FieldNames.VENUE.name()));
Event result = new EventImpl(name, venue);
return result;
}
private Venue loadVenue(DBObject dbObject) {
String name = (String) dbObject.get(FieldNames.VENUE_NAME.name());
BasicDBList dbCourseAreas = (BasicDBList) dbObject.get(FieldNames.COURSE_AREAS.name());
Venue result = new VenueImpl(name);
for (Object courseAreaDBObject : dbCourseAreas) {
CourseArea courseArea = loadCourseArea((DBObject) courseAreaDBObject);
result.addCourseArea(courseArea);
}
return result;
}
private CourseArea loadCourseArea(DBObject courseAreaDBObject) {
String name = (String) courseAreaDBObject.get(FieldNames.COURSE_AREA_NAME.name());
return new CourseAreaImpl(name);
}
@Override
public Regatta loadRegatta(String name) {
// TODO Auto-generated method stub
return null;
}
}
@@ -4,6 +4,8 @@ public enum FieldNames {
// general:
TIME_AS_MILLIS, KNOT_SPEED, DEGREE_BEARING, LAT_DEG, LNG_DEG,
FLEET, RACE_IDENTIFIERS,
/**
* TODO this will have to be renamed to REGATTA_NAME, but compatibility concerns keep us from doing so at the moment
*/
@@ -11,6 +13,12 @@ public enum FieldNames {
RACE_NAME,
VENUE,
VENUE_NAME,
COURSE_AREAS,
COURSE_AREA_NAME,
// wind:
WIND_SOURCE_NAME, WIND_SOURCE_ID, WIND,
@@ -5,12 +5,13 @@ import java.util.Iterator;
import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.RaceColumnImpl;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -29,7 +30,7 @@ import com.sap.sailing.domain.tracking.TrackedRace;
* @author Axel Uhl (d043530)
*
*/
public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
public class FlexibleLeaderboardImplWithDelayedCarriedPoints extends FlexibleLeaderboardImpl {
private static final long serialVersionUID = -8933075542228571746L;
private final Map<String, Integer> carriedPointsByCompetitorName;
private final Map<String, Map<RaceColumn, MaxPointsReason>> maxPointsReasonsByCompetitorName;
@@ -37,28 +38,28 @@ public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
private final Map<String, String> displayNamesByCompetitorName;
/**
* A wrapper for {@link RaceColumn} that, when its {@link #setTrackedRace(TrackedRace)} method is called,
* additionally calls {@link LeaderboardImplWithDelayedCarriedPoints#assignLeftOvers(TrackedRace)}.
* A wrapper for {@link RaceColumn} that, when its {@link #setTrackedRace(Fleet, TrackedRace)} method is called,
* additionally calls {@link FlexibleLeaderboardImplWithDelayedCarriedPoints#assignLeftOvers(TrackedRace)}.
*
* @author Axel Uhl (D043530)
*/
private class RaceInLeaderboardForDelayedCarriedPoints extends RaceColumnImpl {
private class RaceColumnForDelayedCarriedPoints extends RaceColumnImpl {
private static final long serialVersionUID = -1243132535406059096L;
public RaceInLeaderboardForDelayedCarriedPoints(Leaderboard leaderboard, String name, boolean medalRace) {
super(name, medalRace);
public RaceColumnForDelayedCarriedPoints(Leaderboard leaderboard, String name, boolean medalRace, Iterable<Fleet> fleets) {
super(name, medalRace, fleets);
}
@Override
public void setTrackedRace(TrackedRace trackedRace) {
super.setTrackedRace(trackedRace);
public void setTrackedRace(Fleet fleet, TrackedRace trackedRace) {
super.setTrackedRace(fleet, trackedRace);
if (trackedRace != null) {
assignLeftOvers(trackedRace);
}
}
}
public LeaderboardImplWithDelayedCarriedPoints(String name, SettableScoreCorrection scoreCorrection,
public FlexibleLeaderboardImplWithDelayedCarriedPoints(String name, SettableScoreCorrection scoreCorrection,
ThresholdBasedResultDiscardingRule resultDiscardingRule) {
super(name, scoreCorrection, resultDiscardingRule);
carriedPointsByCompetitorName = new HashMap<String, Integer>();
@@ -69,15 +70,15 @@ public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
private void assertNoTrackedRaceAssociatedYet() {
for (RaceColumn raceColumn : getRaceColumns()) {
if (raceColumn.getTrackedRace() != null) {
if (raceColumn.hasTrackedRaces()) {
throw new IllegalStateException("Can't enqueue competitor name-based state while tracked races are already associated with leaderboard");
}
}
}
@Override
protected RaceColumnImpl createRaceColumn(String columnName, boolean medalRace) {
return new RaceInLeaderboardForDelayedCarriedPoints(this, columnName, medalRace);
protected RaceColumnImpl createRaceColumn(String columnName, boolean medalRace, Fleet... fleets) {
return new RaceColumnForDelayedCarriedPoints(this, columnName, medalRace, turnNullOrEmptyFleetsIntoDefaultFleet(fleets));
}
public void setCarriedPoints(String competitorName, int carriedPoints) {
@@ -106,13 +107,13 @@ public class LeaderboardImplWithDelayedCarriedPoints extends LeaderboardImpl {
}
/**
* Performs the regular {@link LeaderboardImpl#addRace(TrackedRace, String, boolean)} and then checks if
* Performs the regular {@link FlexibleLeaderboardImpl#addRace(TrackedRace, String, boolean)} and then checks if
* there are any carried points etc. left over to assign to the competitor objects (see
* {@link #assignLeftOvers(TrackedRace)}).
*/
@Override
public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace) {
RaceColumn result = super.addRace(race, columnName, medalRace);
public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace, Fleet fleet) {
RaceColumn result = super.addRace(race, columnName, medalRace, fleet);
assignLeftOvers(race);
return result;
}
@@ -10,10 +10,14 @@ import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.SpeedWithBearing;
import com.sap.sailing.domain.base.Timed;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.RaceIdentifier;
@@ -25,8 +29,8 @@ import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.domain.tracking.Positioned;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.TrackedRace;
import com.sap.sailing.domain.tracking.TrackedRegatta;
import com.sap.sailing.domain.tracking.Wind;
import com.sap.sailing.domain.tracking.WindTrack;
@@ -96,8 +100,20 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
return result;
}
@Override
public void storeRaceIdentifier(RaceIdentifier raceIdentifier, DBObject dbObject) {
private void storeRaceIdentifiers(RaceColumn raceColumn, DBObject dbObject) {
BasicDBObject raceIdentifiersPerFleet = new BasicDBObject();
for (Fleet fleet : raceColumn.getFleets()) {
RaceIdentifier raceIdentifier = raceColumn.getRaceIdentifier(fleet);
if (raceIdentifier != null) {
DBObject raceIdentifierForFleet = new BasicDBObject();
storeRaceIdentifier(raceIdentifierForFleet, raceIdentifier);
raceIdentifiersPerFleet.put(fleet.getName(), raceIdentifierForFleet);
}
}
dbObject.put(FieldNames.RACE_IDENTIFIERS.name(), raceIdentifiersPerFleet);
}
private void storeRaceIdentifier(DBObject dbObject, RaceIdentifier raceIdentifier) {
if (raceIdentifier != null) {
dbObject.put(FieldNames.EVENT_NAME.name(), raceIdentifier.getRegattaName());
dbObject.put(FieldNames.RACE_NAME.name(), raceIdentifier.getRaceName());
@@ -122,7 +138,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
BasicDBObject dbRaceColumn = new BasicDBObject();
dbRaceColumn.put(FieldNames.LEADERBOARD_COLUMN_NAME.name(), raceColumn.getName());
dbRaceColumn.put(FieldNames.LEADERBOARD_IS_MEDAL_RACE_COLUMN.name(), raceColumn.isMedalRace());
storeRaceIdentifier(raceColumn.getRaceIdentifier(), dbRaceColumn);
storeRaceIdentifiers(raceColumn, dbRaceColumn);
dbRaceColumns.add(dbRaceColumn);
}
if (leaderboard.hasCarriedPoints()) {
@@ -240,7 +256,36 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
BasicDBObject update = new BasicDBObject("$set", new BasicDBObject(FieldNames.LEADERBOARD_GROUP_NAME.name(), newName));
leaderboardGroupCollection.update(query, update);
}
@Override
public void storeEvent(Event event) {
DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name());
DBObject query = new BasicDBObject();
query.put(FieldNames.EVENT_NAME.name(), event.getName());
DBObject eventDBObject = new BasicDBObject();
eventDBObject.put(FieldNames.EVENT_NAME.name(), event.getName());
DBObject venueDBObject = getVenueAsDBObject(event.getVenue());
eventDBObject.put(FieldNames.VENUE.name(), venueDBObject);
eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false);
}
private DBObject getVenueAsDBObject(Venue venue) {
DBObject result = new BasicDBObject();
result.put(FieldNames.VENUE_NAME.name(), venue.getName());
BasicDBList courseAreaList = new BasicDBList();
result.put(FieldNames.COURSE_AREAS.name(), courseAreaList);
for (CourseArea courseArea : venue.getCourseAreas()) {
DBObject dbCourseArea = new BasicDBObject();
courseAreaList.add(dbCourseArea);
dbCourseArea.put(FieldNames.COURSE_AREA_NAME.name(), courseArea.getName());
}
return result;
}
@Override
public void storeRegatta(Regatta regatta) {
// TODO Auto-generated method stub
}
}
@@ -118,7 +118,7 @@ public class SwissTimingRaceTrackerImpl extends AbstractRaceTrackerImpl implemen
}
@Override
public DynamicTrackedRegatta getTrackedEvent() {
public DynamicTrackedRegatta getTrackedRegatta() {
return SwissTimingRaceTrackerImpl.this.getTrackedRegatta();
}
@@ -60,7 +60,7 @@ public class FetchTracksAndStoreLocallyTest extends OnlineTracTracBasedTest {
track.addGPSFix((GPSFixMoving) fix);
}
};
DynamicTrackedRegatta trackedRegatta = getTrackedEvent();
DynamicTrackedRegatta trackedRegatta = getTrackedRegatta();
trackedRegatta.addRaceListener(new RaceListener() {
@Override
public void raceAdded(TrackedRace trackedRace) {
@@ -10,6 +10,7 @@ import java.util.GregorianCalendar;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.NoWindException;
@@ -18,7 +19,7 @@ import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.WindSourceImpl;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.tracking.impl.WindImpl;
@@ -26,7 +27,7 @@ import com.sap.sailing.domain.tractracadapter.ReceiverType;
public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest {
private LeaderboardImpl leaderboard;
private FlexibleLeaderboardImpl leaderboard;
public LeaderboardForKielWeekTest() throws MalformedURLException, URISyntaxException {
super();
@@ -34,24 +35,25 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest {
@Test
public void leaderboardWithOneRaceTest() throws URISyntaxException, NoWindException, IOException, InterruptedException {
leaderboard = new LeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(new int[] { 3, 6 }));
leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(new int[] { 3, 6 }));
Fleet defaultFleet = leaderboard.getFleet(null);
MillisecondsTimePoint now = MillisecondsTimePoint.now();
loadRace("357c700a-9d9a-11e0-85be-406186cbf87c"); // 505 Race 2
Competitor hasso = getCompetitorByName("Dr.Plattner");
RaceColumn column = leaderboard.addRace(getTrackedRace(), "Test Race 1", /* medalRace */ false);
RaceColumn column = leaderboard.addRace(getTrackedRace(), "Test Race 1", /* medalRace */ false, defaultFleet);
assertEquals(21, leaderboard.getTotalPoints(hasso, now));
Pair<Competitor, RaceColumn> key = new Pair<Competitor, RaceColumn>(hasso, column);
assertEquals(21, leaderboard.getContent(now).get(key).getTotalPoints());
assertEquals(21, leaderboard.getEntry(hasso, column, now).getTotalPoints());
loadRace("e876c3a0-9da8-11e0-85be-406186cbf87c"); // 505 Race 3
column = leaderboard.addRace(getTrackedRace(), "Test Race 2", /* medalRace */ false);
column = leaderboard.addRace(getTrackedRace(), "Test Race 2", /* medalRace */ false, defaultFleet);
key = new Pair<Competitor, RaceColumn>(hasso, column);
// In Race 3, Hasso ranked 31st
assertEquals(52, leaderboard.getTotalPoints(hasso, now));
assertEquals(31, leaderboard.getContent(now).get(key).getTotalPoints());
assertEquals(31, leaderboard.getEntry(hasso, column, now).getTotalPoints());
loadRace("7c666e50-9dde-11e0-85be-406186cbf87c"); // 505 Race 4
column = leaderboard.addRace(getTrackedRace(), "Test Race 3", /* medalRace */ false);
column = leaderboard.addRace(getTrackedRace(), "Test Race 3", /* medalRace */ false, defaultFleet);
key = new Pair<Competitor, RaceColumn>(hasso, column);
// now the second race is discarded because Hasso ranked worst compared to the other two; in race 4 he ranked 11th
assertEquals(32, leaderboard.getTotalPoints(hasso, now));
@@ -15,6 +15,7 @@ import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.impl.BoatClassImpl;
import com.sap.sailing.domain.base.impl.BoatImpl;
import com.sap.sailing.domain.base.impl.CompetitorImpl;
@@ -27,9 +28,9 @@ import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.tracking.TrackedRace;
@@ -98,12 +99,13 @@ public class LeaderboardOfflineTest {
@Test
public void ensureMedalRaceParamIsIgnoredIfRaceColumnAlreadyExists() {
Leaderboard leaderboard = new LeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
new int[] { 5, 8 }));
Fleet defaultFleet = leaderboard.getFleet(null);
final String columnName = "abc";
setupRaces(1, 0);
leaderboard.addRaceColumn(columnName, /* medalRace */ true);
leaderboard.addRace(testRaces.iterator().next(), columnName, /* medalRace */ false);
leaderboard.addRace(testRaces.iterator().next(), columnName, /* medalRace */ false, defaultFleet);
assertTrue(leaderboard.getRaceColumnByName(columnName).isMedalRace());
}
@@ -120,14 +122,15 @@ public class LeaderboardOfflineTest {
testRaces.add(r); // hash set should take care of more or less randomly permuting the races
}
ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl();
Leaderboard leaderboard = new LeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl(
FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl(
new int[] { 1 }));
Fleet defaultFleet = leaderboard.getFleet(null);
int i=0;
int bestScore = Integer.MAX_VALUE;
RaceColumn bestScoringRaceColumn = null;
for (TrackedRace race : testRaces) {
i++;
RaceColumn raceColumn = leaderboard.addRace(race, "Test Race " + i, /* medalRace */ false);
RaceColumn raceColumn = leaderboard.addRace(race, "Test Race " + i, /* medalRace */ false, defaultFleet);
raceColumnsInLeaderboard.put(race, raceColumn);
if (race.getRank(competitor) < bestScore) {
bestScore = race.getRank(competitor);
@@ -136,7 +139,7 @@ public class LeaderboardOfflineTest {
}
scoreCorrection.setMaxPointsReason(competitor, bestScoringRaceColumn, MaxPointsReason.DSQ);
// assert that best scoring but now disqualified race gets max net points because of disqualification:
assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace().getRace().getCompetitors())+1,
assertEquals(Util.size(bestScoringRaceColumn.getTrackedRace(defaultFleet).getRace().getCompetitors())+1,
leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getNetPoints());
// now assert that it gets discarded because due to disqualification it scores worse than all others:
assertEquals(0, leaderboard.getEntry(competitor, bestScoringRaceColumn, MillisecondsTimePoint.now()).getTotalPoints());
@@ -145,13 +148,14 @@ public class LeaderboardOfflineTest {
protected void testLeaderboard(int numberOfStartedRaces, int numberOfNotStartedRaces, int firstDiscardingThreshold,
int secondDiscardingThreshold, Integer carry, boolean addOneMedalRace, int numberOfUntrackedRaces) throws NoWindException {
setupRaces(numberOfStartedRaces, numberOfNotStartedRaces);
Leaderboard leaderboard = new LeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
new int[] { firstDiscardingThreshold, secondDiscardingThreshold }));
Fleet defaultFleet = leaderboard.getFleet(null);
int i=0;
for (TrackedRace race : testRaces) {
i++;
raceColumnsInLeaderboard.put(race, leaderboard.addRace(race, "Test Race "+i,
/* medalRace */ numberOfUntrackedRaces == 0 && addOneMedalRace && i == testRaces.size()));
/* medalRace */ numberOfUntrackedRaces == 0 && addOneMedalRace && i == testRaces.size(), defaultFleet));
}
// add a few race columns not yet connected to a tracked race
for (int j=0; j<numberOfUntrackedRaces; j++) {
@@ -164,14 +168,14 @@ public class LeaderboardOfflineTest {
List<Integer> ranksOfNonMedalStartedRaces = new ArrayList<Integer>();
TimePoint now = MillisecondsTimePoint.now();
for (RaceColumn column : raceColumnsInLeaderboard.values()) {
if (!column.isMedalRace() && column.getTrackedRace() != null && column.getTrackedRace().hasStarted(now)) {
ranksOfNonMedalStartedRaces.add(column.getTrackedRace().getRank(competitor, now));
if (!column.isMedalRace() && column.getTrackedRace(defaultFleet) != null && column.getTrackedRace(defaultFleet).hasStarted(now)) {
ranksOfNonMedalStartedRaces.add(column.getTrackedRace(defaultFleet).getRank(competitor, now));
}
}
Collections.sort(ranksOfNonMedalStartedRaces);
int carryInt = (carry == null ? 0 : carry);
int totalPoints = carryInt;
int medalRacePoints = getMedalRacePoints(competitor, now);
int medalRacePoints = getMedalRacePoints(competitor, now, defaultFleet);
int numberOfRacesFromWhichToDiscard = ranksOfNonMedalStartedRaces.size();
for (TrackedRace race : testRaces) {
RaceColumn raceColumn = raceColumnsInLeaderboard.get(race);
@@ -207,11 +211,11 @@ public class LeaderboardOfflineTest {
assertEquals(totalPoints, leaderboard.getTotalPoints(competitor, now));
}
private int getMedalRacePoints(Competitor competitor, TimePoint at) throws NoWindException {
private int getMedalRacePoints(Competitor competitor, TimePoint at, Fleet fleet) throws NoWindException {
for (TrackedRace r : testRaces) {
if (raceColumnsInLeaderboard.get(r) != null && raceColumnsInLeaderboard.get(r).isMedalRace() &&
raceColumnsInLeaderboard.get(r).getTrackedRace().hasStarted(at)) {
return raceColumnsInLeaderboard.get(r).getTrackedRace().getRank(competitor, at);
raceColumnsInLeaderboard.get(r).getTrackedRace(fleet).hasStarted(at)) {
return raceColumnsInLeaderboard.get(r).getTrackedRace(fleet).getRank(competitor, at);
}
}
return 0;
@@ -114,7 +114,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
for (Receiver receiver : receivers) {
receiver.join();
}
trackedRace = getTrackedEvent().getTrackedRace(race);
trackedRace = getTrackedRegatta().getTrackedRace(race);
}
@@ -205,7 +205,7 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest {
return domainEvent;
}
protected DynamicTrackedRegatta getTrackedEvent() {
protected DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
@@ -74,7 +74,7 @@ public class ParseTracTracJSONServiceOutputTest {
@Test
public void testWeymouthOnline() throws MalformedURLException, IOException, java.text.ParseException, ParseException, URISyntaxException {
JSONService jsonService = DomainFactory.INSTANCE.parseJSONURL(new URL(
"http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php"));
"http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php?trickOurProxy=true"));
assertEquals("Academy Tracking 2011", jsonService.getEventName());
List<RaceRecord> races = jsonService.getRaceRecords();
assertTrue(races.size()>=28);
@@ -273,7 +273,7 @@ public class MockedTrackedRace implements DynamicTrackedRace {
}
@Override
public DynamicTrackedRegatta getTrackedEvent() {
public DynamicTrackedRegatta getTrackedRegatta() {
return new DynamicTrackedRegatta() {
private static final long serialVersionUID = 2651590861333064588L;
@@ -59,7 +59,7 @@ public abstract class AbstractReceiverWithQueue<A, B, C> implements Runnable, Re
return tractracEvent;
}
protected DynamicTrackedRegatta getTrackedEvent() {
protected DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
@@ -81,7 +81,7 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
// Therefore, don't create TrackedRace again because it already exists.
try {
getDomainFactory().updateCourseWaypoints(existingRaceDefinitionForRace.getCourse(), event.getB().getPoints());
if (getTrackedEvent().getExistingTrackedRace(existingRaceDefinitionForRace) == null) {
if (getTrackedRegatta().getExistingTrackedRace(existingRaceDefinitionForRace) == null) {
createTrackedRace(existingRaceDefinitionForRace);
}
} catch (PatchFailedException e) {
@@ -91,13 +91,13 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
} else {
logger.log(Level.INFO, "Received course for non-existing race "+event.getC().getName()+". Creating RaceDefinition.");
// create race definition and add to event
getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(getTrackedEvent(), event.getC(), course,
getDomainFactory().getOrCreateRaceDefinitionAndTrackedRace(getTrackedRegatta(), event.getC(), course,
windStore, millisecondsOverWhichToAverageWind, raceDefinitionSetToUpdate);
}
}
private void createTrackedRace(RaceDefinition race) {
getTrackedEvent().createTrackedRace(race,
getTrackedRegatta().createTrackedRace(race,
windStore, millisecondsOverWhichToAverageWind,
/* time over which to average speed: */ race.getBoatClass().getApproximateManeuverDurationInMilliseconds(),
raceDefinitionSetToUpdate);
@@ -39,7 +39,7 @@ public class RaceHandleImpl implements RacesHandle {
}
@Override
public DynamicTrackedRegatta getTrackedEvent() {
public DynamicTrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
@@ -9,6 +9,6 @@ import com.sap.sailing.domain.common.Named;
* @author Axel Uhl (D043530)
*
*/
public interface RaceArea extends Named {
public interface CourseArea extends Named {
}
@@ -1,13 +1,24 @@
package com.sap.sailing.domain.base;
import com.sap.sailing.domain.common.Named;
/**
* An event is a group of {@link Regatta regattas} carried out at a common venue within a common time frame. For
* example, Kiel Week is an event, and the International German Championship held, e.g., in Travemünde, is an event,
* example, Kiel Week 2011 is an event, and the International German Championship 2011 held, e.g., in Travemünde, is an event,
* too.
*
* @author Axel Uhl (D043530)
*
*/
public interface Event {
public interface Event extends Named {
/**
* @return a non-<code>null</code> venue for this event
*/
Venue getVenue();
Iterable<Regatta> getRegattas();
void addRegatta(Regatta regatta);
void removeRegatta(Regatta regatta);
}
@@ -26,9 +26,6 @@ public interface Regatta extends Named {
* For example, it may be the case that a {@link RaceDefinition} is returned by this method for which no
* {@link TrackedRace} exists in the corresponding {@link TrackedRegatta}. This could be the case, e.g., during
* the initialization of the tracker as well as during removing a race from the server.<p>
*
* Callers iterating over the result that anticipate concurrent modifications shall synchronize the iteration
* on the result.
*/
Iterable<RaceDefinition> getAllRaces();
@@ -9,5 +9,9 @@ import com.sap.sailing.domain.common.Named;
*
*/
public interface Venue extends Named {
Iterable<RaceArea> getRaceAreas();
Iterable<CourseArea> getCourseAreas();
void addCourseArea(CourseArea courseArea);
void removeCourseArea(CourseArea courseArea);
}
@@ -0,0 +1,12 @@
package com.sap.sailing.domain.base.impl;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.common.impl.NamedImpl;
public class CourseAreaImpl extends NamedImpl implements CourseArea {
private static final long serialVersionUID = 5912385360170509150L;
public CourseAreaImpl(String name) {
super(name);
}
}
@@ -0,0 +1,53 @@
package com.sap.sailing.domain.base.impl;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.common.impl.NamedImpl;
public class EventImpl extends NamedImpl implements Event {
private static final long serialVersionUID = 855135446595485715L;
private final Set<Regatta> regattas;
private final Venue venue;
public EventImpl(String name, String venueName) {
this(name, new VenueImpl(venueName));
}
/**
* @param venue must not be <code>null</code>
*/
public EventImpl(String name, Venue venue) {
super(name);
assert venue != null;
this.venue = venue;
this.regattas = new HashSet<Regatta>();
}
@Override
public Iterable<Regatta> getRegattas() {
return Collections.unmodifiableSet(regattas);
}
@Override
public void addRegatta(Regatta regatta) {
regattas.add(regatta);
}
@Override
public void removeRegatta(Regatta regatta) {
regattas.remove(regatta);
}
@Override
public Venue getVenue() {
return venue;
}
}
@@ -64,7 +64,9 @@ public class RegattaImpl extends NamedImpl implements Regatta {
@Override
public Iterable<RaceDefinition> getAllRaces() {
return races;
synchronized (races) {
return new ArrayList<RaceDefinition>(races);
}
}
@Override
@@ -74,15 +76,12 @@ public class RegattaImpl extends NamedImpl implements Regatta {
@Override
public RaceDefinition getRaceByName(String raceName) {
Iterable<RaceDefinition> allRaces = getAllRaces();
synchronized (allRaces) {
for (RaceDefinition r : getAllRaces()) {
if (r.getName().equals(raceName)) {
return r;
}
for (RaceDefinition r : getAllRaces()) {
if (r.getName().equals(raceName)) {
return r;
}
return null;
}
return null;
}
@Override
@@ -0,0 +1,40 @@
package com.sap.sailing.domain.base.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.common.impl.NamedImpl;
public class VenueImpl extends NamedImpl implements Venue {
private static final long serialVersionUID = 6854152040737643290L;
/**
* The course areas are ordered because they typically follow an ordered naming pattern borrowed from the
* "NATO alphabet" (Alpha, Bravo, Charlie, ...).
*/
private final List<CourseArea> courseAreas;
public VenueImpl(String name) {
super(name);
courseAreas = new ArrayList<CourseArea>();
}
@Override
public Iterable<CourseArea> getCourseAreas() {
return Collections.unmodifiableList(courseAreas);
}
@Override
public void addCourseArea(CourseArea courseArea) {
courseAreas.add(courseArea);
}
@Override
public void removeCourseArea(CourseArea courseArea) {
courseAreas.remove(courseArea);
}
}
@@ -0,0 +1,65 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.tracking.TrackedRace;
/**
* A leaderboard that allows its clients to flexibly modify the race columns arranged in this leaderboard without the need to adhere
* to the constraints of a {@link Regatta} with its {@link Series} and {@link Fleet}s.
*
* @author Axel Uhl (D043530)
*
*/
public interface FlexibleLeaderboard extends Leaderboard {
/**
* Moves the column with the name <code>name</code> up.
* @param name The name of the column to move.
*/
void moveRaceColumnUp(String name);
/**
* Moves the column with the name <code>name</code> down.
* @param name The name of the column to move.
*/
void moveRaceColumnDown(String name);
/**
* Adds a new {@link RaceColumn} that has no {@link TrackedRace} associated yet to this leaderboard.
*
* @param name
* the name for the new race column such that none of the columns in {@link #getRaceColumns()}
* has that name yet; otherwise, an message will be logged, no race column will be added and
* the existing column will be returned for robustness reasons
* @param medalRace
* tells if the column to add represents a medal race which has double score and cannot be discarded
* @param fleets
* the fleets to add to the {@link RaceColumn} created. If no fleets are specified, a single default
* fleet will be assigned to the race column created.
*
* @return the race column in the leaderboard used to represent the tracked <code>race</code>
*/
RaceColumn addRaceColumn(String name, boolean medalRace, Fleet... fleets);
/**
* Adds a tracked race to this leaderboard. If a {@link RaceColumn} with name <code>columnName</code> already exists
* in this leaderboard, <code>race</code> is {@link RaceColumn#setTrackedRace(Fleet, TrackedRace) set as its tracked
* race} and <code>medalRace</code> is ignored. Otherwise, a new {@link RaceColumn} column, with <code>race</code>
* as its tracked race, is created and added to this leaderboard.
*
* @param medalRace
* tells if the column to add represents a medal race which has double score and cannot be discarded;
* ignored if the column named <code>columnName</code> already exists
*
* @param fleets
* the fleets to add to the {@link RaceColumn} created. If no fleets are specified, a single default
* fleet will be assigned to the race column created.
*
* @return the race column in the leaderboard used to represent the tracked <code>race</code>
*/
RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace, Fleet fleet);
void removeRaceColumn(String columnName);
}
@@ -3,6 +3,7 @@ package com.sap.sailing.domain.leaderboard;
import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.NoWindException;
@@ -51,6 +52,14 @@ public interface Leaderboard extends Named {
*/
Iterable<Competitor> getCompetitors();
/**
* Returns the first fleet found in the sequence of this leaderboard's {@link #getRaceColumns() race columns}'
* {@link RaceColumn#getFleets() fleets} whose name equals <code>fleetName</code>. If no such fleet is found,
* <code>null</code> is returned. If <code>fleetName</code> is <code>null</code>, the leaderboard may return
* a default fleet if it has one, or <code>null</code> otherwise.
*/
Fleet getFleet(String fleetName);
Entry getEntry(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException;
/**
@@ -108,21 +117,6 @@ public interface Leaderboard extends Named {
*/
boolean isDiscarded(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint);
/**
* Adds a tracked race to this leaderboard. If a {@link RaceColumn} with name <code>columnName</code> already
* exists in this leaderboard, <code>race</code> is {@link RaceColumn#setTrackedRace(TrackedRace) set as its
* tracked race} and <code>medalRace</code> is ignored. Otherwise, a new
* {@link RaceColumn} column, with <code>race</code> as its tracked race, is created and added to this
* leaderboard.
*
* @param medalRace
* tells if the column to add represents a medal race which has double score and cannot be discarded;
* ignored if the column named <code>columnName</code> already exists
*
* @return the race column in the leaderboard used to represent the tracked <code>race</code>
*/
RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace);
/**
* Sums up the {@link #getTotalPoints(Competitor, TrackedRace, TimePoint) total points} of <code>competitor</code>
* across all races tracked by this leaderboard.
@@ -147,15 +141,6 @@ public interface Leaderboard extends Named {
*/
void setName(String newName);
/**
* Adds a new {@link RaceColumn} that has no {@link TrackedRace} associated yet to this leaderboard.
* @param medalRace
* tells if the column to add represents a medal race which has double score and cannot be discarded
*
* @return the race column in the leaderboard used to represent the tracked <code>race</code>
*/
RaceColumn addRaceColumn(String name, boolean medalRace);
/**
* Retrieves all race columns that were added, either by {@link #addRace(TrackedRace, String, boolean)} or
* {@link #addRaceColumn(String, boolean)}.
@@ -168,18 +153,6 @@ public interface Leaderboard extends Named {
*/
RaceColumn getRaceColumnByName(String name);
/**
* Moves the column with the name <code>name</code> up.
* @param name The name of the column to move.
*/
void moveRaceColumnUp(String name);
/**
* Moves the column with the name <code>name</code> down.
* @param name The name of the column to move.
*/
void moveRaceColumnDown(String name);
/**
* A leaderboard can carry over points from races that are not tracked by this leaderboard in detail,
* so for which no {@link RaceColumn} column is present in this leaderboard. These scores are
@@ -204,8 +177,6 @@ public interface Leaderboard extends Named {
boolean hasCarriedPoints(Competitor competitor);
void removeRaceColumn(String columnName);
SettableScoreCorrection getScoreCorrection();
ThresholdBasedResultDiscardingRule getResultDiscardingRule();
@@ -1,45 +1,84 @@
package com.sap.sailing.domain.leaderboard;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.tracking.TrackedRace;
/**
* A column in a {@link Leaderboard} that represents the data of a race. Over the life time of this object it can be
* assigned a {@link TrackedRace} which then acts as a data provider to this column. If no tracked race has been
* assigned, the scores reported by this column will all default to zero.
* One or more races that would be noted together in a single column in a {@link Leaderboard}. If the number of
* competitors of a regatta is too big to have a single start, the set of competitors can be split into several
* {@link Fleet}s. Still, the regatta has a sequence of "races", only that each such "race" actually consists of several
* individual races, each tracked separately, with a separate start and a separate field of competitors which are
* distinct subsets of the regatta's competitors. These races are grouped in a {@link RaceColumn}. The
* {@link RaceColumn} therefore provides access to the {@link TrackedRace}s by {@link Fleet} and by {@link Competitor}.
* The {@link TrackedRace}s represent the data of a race. Over the life time of this object it can be assigned one or more
* {@link TrackedRace}s which then act(s) as data provider to this column. If no tracked race has been assigned, the
* scores reported by this column will all default to zero.
*
* @author Axel Uhl (D043530)
*
*/
public interface RaceColumn extends Named {
/**
* This does also update the {@link #getRaceIdentifier() race identifier} by setting it to <code>null</code> if <code>race</code>
* is <code>null</code>, and <code>race.getRaceIdentifier()</code> otherwise.
* @return the fleets for each of which this column has a single race and therefore optionally a {@link TrackedRace}
*/
void setTrackedRace(TrackedRace race);
Iterable<Fleet> getFleets();
Fleet getFleetByName(String fleetName);
/**
* This does also update the {@link #getRaceIdentifier(Fleet) race identifier} by setting it to <code>null</code> if <code>race</code>
* is <code>null</code>, and <code>race.getRaceIdentifier()</code> otherwise.
*
* @param fleet the fleet within this column with which to associate <code>race</code>
*/
void setTrackedRace(Fleet fleet, TrackedRace race);
/**
* Tells if at least one {@link TrackedRace} is associated with this race column. Short for
* {@link Util#isEmpty(Iterable) isEmpty(}{@link #getFleets() getFleets())}.
*/
boolean hasTrackedRaces();
/**
* @return <code>null</code> if this column does not currently have a tracked race associated; otherwise the tracked
* race from where all information relevant to this column can be obtained. See also
* {@link #getRaceIdentifier()}.
* @param fleet
* the fleet whose associated tracked race to obtain
*
* @return <code>null</code> if this column does not currently have a tracked race associated for <code>fleet</code>
* ; otherwise the tracked race for <code>fleet</code> from where all information relevant to this column
* can be obtained. See also {@link #getRaceIdentifier(Fleet)}.
*/
TrackedRace getTrackedRace();
TrackedRace getTrackedRace(Fleet fleet);
/**
* Tries to find a tracked race whose {@link RaceDefinition#getCompetitors() competitors} contain <code>competitor</code>. If
* no such {@link TrackedRace} is currently associated with this race column, <code>null</code> is returned.
*/
TrackedRace getTrackedRace(Competitor competitor);
/**
* If this column ever was assigned to a tracked race, that race's identifier can be obtained using this method;
* otherwise, <code>null</code> is returned.
* otherwise, <code>null</code> is returned.
*
* @param fleet
* the fleet for which to obtain the race identifier
*/
RaceIdentifier getRaceIdentifier();
RaceIdentifier getRaceIdentifier(Fleet fleet);
/**
* Records that this leaderboard column is to be associated with the race identified by <code>raceIdentifier</code>.
* This does not automatically load the tracked race, but the information may be used to re-associate a tracked
* race with this column based on its {@link TrackedRace#getRaceIdentifier() race identifier}.
* This does not automatically load the tracked race, but the information may be used to re-associate a tracked race
* with this column based on its {@link TrackedRace#getRaceIdentifier() race identifier}.
*
* @param fleet
* the fleet for which to associate a race by its identifier
*/
void setRaceIdentifier(RaceIdentifier raceIdentifier);
void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier);
/**
* A "medal race" cannot be discarded. It's score is doubled during score aggregation.
@@ -56,11 +95,14 @@ public interface RaceColumn extends Named {
Pair<Competitor, RaceColumn> getKey(Competitor competitor);
/**
* Releases the {@link TrackedRace} previously set by {@link #setTrackedRace(TrackedRace)} but leaves the
* {@link #getRaceIdentifier() race identifier} untouched. Therefore, the {@link TrackedRace} may be garbage
* 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
* collected but may be re-resolved for this column using the race identifier at a later time.
*
* @param fleet
* the fleet for which to release its tracked race
*/
void releaseTrackedRace();
void releaseTrackedRace(Fleet fleet);
}
@@ -1,16 +1,14 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.Named;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.TimePoint;
import com.sap.sailing.domain.common.impl.Util;
@@ -22,9 +20,8 @@ import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.tracking.TrackedRace;
public class LeaderboardImpl implements Named, Leaderboard {
public abstract class AbstractLeaderboardImpl implements Leaderboard {
private static final long serialVersionUID = -328091952760083438L;
private final List<RaceColumn> races;
private final SettableScoreCorrection scoreCorrection;
private ThresholdBasedResultDiscardingRule resultDiscardingRule;
private String name;
@@ -93,39 +90,33 @@ public class LeaderboardImpl implements Named, Leaderboard {
/**
* @param name must not be <code>null</code>
*/
public LeaderboardImpl(String name, SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) {
public AbstractLeaderboardImpl(String name, SettableScoreCorrection scoreCorrection, ThresholdBasedResultDiscardingRule resultDiscardingRule) {
if (name == null) {
throw new IllegalArgumentException("A leaderboard's name must not be null");
}
this.name = name;
this.carriedPoints = new HashMap<Competitor, Integer>();
this.races = new ArrayList<RaceColumn>();
this.scoreCorrection = scoreCorrection;
this.displayNames = new HashMap<Competitor, String>();
this.resultDiscardingRule = resultDiscardingRule;
}
@Override
public RaceColumn addRaceColumn(String name, boolean medalRace) {
RaceColumnImpl column = createRaceColumn(name, medalRace);
races.add(column);
return column;
public Fleet getFleet(String fleetName) {
for (RaceColumn raceColumn : getRaceColumns()) {
for (Fleet fleet : raceColumn.getFleets()) {
if (fleet.getName().equals(fleetName)) {
return fleet;
}
}
}
return null;
}
@Override
public void removeRaceColumn(String columnName) {
races.remove(getRaceColumnByName(columnName));
}
@Override
public Iterable<RaceColumn> getRaceColumns() {
return Collections.unmodifiableCollection(new ArrayList<RaceColumn>(races));
}
@Override
public RaceColumn getRaceColumnByName(String columnName) {
RaceColumn result = null;
for (RaceColumn r : races) {
for (RaceColumn r : getRaceColumns()) {
if (r.getName().equals(columnName)) {
result = r;
break;
@@ -134,27 +125,14 @@ public class LeaderboardImpl implements Named, Leaderboard {
return result;
}
@Override
public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace) {
RaceColumn column = getRaceColumnByName(columnName);
if (column == null) {
column = createRaceColumn(columnName, medalRace);
races.add(column);
}
column.setTrackedRace(race);
return column;
}
protected RaceColumnImpl createRaceColumn(String columnName, boolean medalRace) {
return new RaceColumnImpl(columnName, medalRace);
}
private Iterable<TrackedRace> getTrackedRaces() {
Set<TrackedRace> trackedRaces = new HashSet<TrackedRace>();
for (RaceColumn r : races) {
TrackedRace trackedRace = r.getTrackedRace();
if (trackedRace != null) {
trackedRaces.add(trackedRace);
for (RaceColumn r : getRaceColumns()) {
for (Fleet fleet : r.getFleets()) {
TrackedRace trackedRace = r.getTrackedRace(fleet);
if (trackedRace != null) {
trackedRaces.add(trackedRace);
}
}
}
return Collections.unmodifiableSet(trackedRaces);
@@ -203,8 +181,8 @@ public class LeaderboardImpl implements Named, Leaderboard {
@Override
public int getTrackedPoints(Competitor competitor, RaceColumn race, TimePoint timePoint) throws NoWindException {
return race.getTrackedRace() == null ? 0 : race.getTrackedRace().hasStarted(timePoint) ? race.getTrackedRace()
.getRank(competitor, timePoint) : 0;
final TrackedRace trackedRace = race.getTrackedRace(competitor);
return trackedRace == null ? 0 : trackedRace.hasStarted(timePoint) ? trackedRace.getRank(competitor, timePoint) : 0;
}
@Override
@@ -217,7 +195,7 @@ public class LeaderboardImpl implements Named, Leaderboard {
@Override
public MaxPointsReason getMaxPointsReason(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint)
throws NoWindException {
return raceColumn.getTrackedRace() == null ? MaxPointsReason.NONE : getScoreCorrection().getCorrectedScore(
return raceColumn.getTrackedRace(competitor) == null ? MaxPointsReason.NONE : getScoreCorrection().getCorrectedScore(
getTrackedPoints(competitor, raceColumn, timePoint), competitor, raceColumn, timePoint, Util.size(getCompetitors()))
.getMaxPointsReason();
}
@@ -263,9 +241,9 @@ public class LeaderboardImpl implements Named, Leaderboard {
for (RaceColumn raceColumn : getRaceColumns()) {
for (Competitor competitor : getCompetitors()) {
int trackedPoints;
// TODO when a column has more than one race, keyed by fleet, find the one for competitor
if (raceColumn.getTrackedRace() != null && raceColumn.getTrackedRace().hasStarted(timePoint)) {
trackedPoints = raceColumn.getTrackedRace().getRank(competitor, timePoint);
final TrackedRace trackedRace = raceColumn.getTrackedRace(competitor);
if (trackedRace != null && trackedRace.hasStarted(timePoint)) {
trackedPoints = trackedRace.getRank(competitor, timePoint);
} else {
trackedPoints = 0;
}
@@ -329,9 +307,17 @@ public class LeaderboardImpl implements Named, Leaderboard {
@Override
public boolean considerForDiscarding(RaceColumn raceInLeaderboard, TimePoint timePoint) {
return !raceInLeaderboard.isMedalRace()
&& (raceInLeaderboard.getTrackedRace() != null && raceInLeaderboard.getTrackedRace().hasStarted(
timePoint)) || getScoreCorrection().hasCorrectionFor(raceInLeaderboard);
boolean result = getScoreCorrection().hasCorrectionFor(raceInLeaderboard);
if (!result && !raceInLeaderboard.isMedalRace()) {
for (Fleet fleet : raceInLeaderboard.getFleets()) {
TrackedRace trackedRace = raceInLeaderboard.getTrackedRace(fleet);
if (trackedRace != null && trackedRace.hasStarted(timePoint)) {
result = true;
break;
}
}
}
return result;
}
@Override
@@ -344,59 +330,20 @@ public class LeaderboardImpl implements Named, Leaderboard {
displayNames.put(competitor, displayName);
}
@Override
public void moveRaceColumnUp(String name) {
RaceColumn race = null;
for (RaceColumn r : races){
if (r.getName().equals(name))
race = r;
}
if (race == null)
return;
int index = 0;
index = races.lastIndexOf(race);
index--;
if (index >= 0){
races.remove(race);
races.add(index, race);
}
}
@Override
public void moveRaceColumnDown(String name) {
RaceColumn race = null;
for (RaceColumn r : races){
if (r.getName().equals(name))
race = r;
}
if (race == null)
return;
int index = 0;
index = races.lastIndexOf(race);
if (index == -1)
return;
index++;
if (index < races.size()){
races.remove(race);
races.add(index, race);
}
}
@Override
public void updateIsMedalRace(String raceName, boolean isMedalRace) {
RaceColumn race = null;
for (RaceColumn r : races){
if (r.getName().equals(raceName))
race = r;
}
if (race == null)
return;
race.setIsMedalRace(isMedalRace);
}
@Override
public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) {
this.resultDiscardingRule = discardingRule;
}
@Override
public void updateIsMedalRace(String raceName, boolean isMedalRace) {
RaceColumn race = null;
for (RaceColumn r : getRaceColumns()) {
if (r.getName().equals(raceName))
race = r;
}
if (race != null) {
race.setIsMedalRace(isMedalRace);
}
}
@Override
public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) {
this.resultDiscardingRule = discardingRule;
}
}
@@ -0,0 +1,139 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
import com.sap.sailing.domain.tracking.TrackedRace;
/**
* A leaderboard implementation that allows users to flexibly configure which columns exist. No constraints need to be observed regarding
* the columns belonging to the same regatta or even boat class.
*
* @author Axel Uhl (D043530)
*
*/
public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements FlexibleLeaderboard {
private static Logger logger = Logger.getLogger(FlexibleLeaderboardImpl.class.getName());
protected static final Fleet defaultFleet = new FleetImpl("Default");
private static final long serialVersionUID = -5708971849158747846L;
private final List<RaceColumn> races;
public FlexibleLeaderboardImpl(String name, SettableScoreCorrection scoreCorrection,
ThresholdBasedResultDiscardingRule resultDiscardingRule) {
super(name, scoreCorrection, resultDiscardingRule);
this.races = new ArrayList<RaceColumn>();
}
@Override
public RaceColumn addRaceColumn(String name, boolean medalRace, Fleet... fleets) {
RaceColumn column = getRaceColumnByName(name);
if (column != null) {
final String msg = "Trying to create race column with duplicate name "+name+" in leaderboard +"+getName();
logger.severe(msg);
} else {
column = createRaceColumn(name, medalRace, fleets);
races.add(column);
}
return column;
}
@Override
public Fleet getFleet(String fleetName) {
Fleet result;
if (fleetName == null) {
result = defaultFleet;
} else {
result = super.getFleet(fleetName);
}
return result;
}
@Override
public void removeRaceColumn(String columnName) {
races.remove(getRaceColumnByName(columnName));
}
@Override
public Iterable<RaceColumn> getRaceColumns() {
return Collections.unmodifiableCollection(new ArrayList<RaceColumn>(races));
}
@Override
public RaceColumn addRace(TrackedRace race, String columnName, boolean medalRace, Fleet fleet) {
RaceColumn column = getRaceColumnByName(columnName);
if (column == null) {
column = createRaceColumn(columnName, medalRace);
races.add(column);
}
column.setTrackedRace(fleet, race);
return column;
}
protected RaceColumnImpl createRaceColumn(String columnName, boolean medalRace, Fleet... fleets) {
return new RaceColumnImpl(columnName, medalRace, turnNullOrEmptyFleetsIntoDefaultFleet(fleets));
}
protected Iterable<Fleet> turnNullOrEmptyFleetsIntoDefaultFleet(Fleet... fleets) {
Iterable<Fleet> theFleets;
if (fleets == null || fleets.length == 0) {
theFleets = Collections.singleton(defaultFleet);
} else {
theFleets = Arrays.asList(fleets);
}
return theFleets;
}
@Override
public void moveRaceColumnUp(String name) {
RaceColumn race = null;
for (RaceColumn r : races) {
if (r.getName().equals(name)) {
race = r;
}
}
if (race == null) {
return;
}
int index = 0;
index = races.lastIndexOf(race);
index--;
if (index >= 0) {
races.remove(race);
races.add(index, race);
}
}
@Override
public void moveRaceColumnDown(String name) {
RaceColumn race = null;
for (RaceColumn r : races) {
if (r.getName().equals(name)) {
race = r;
}
}
if (race == null) {
return;
}
int index = 0;
index = races.lastIndexOf(race);
if (index == -1) {
return;
}
index++;
if (index < races.size()) {
races.remove(race);
races.add(index, race);
}
}
}
@@ -1,21 +1,35 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.HashMap;
import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.tracking.TrackedRace;
public class RaceColumnImpl implements RaceColumn {
private static final long serialVersionUID = -7801617988982540470L;
private TrackedRace trackedRace;
/**
* All fleets for which this column can contain a race. This is the maximum set of keys possible for
* {@link #trackedRaces} and {@link #raceIdentifiers}.
*/
private final Iterable<Fleet> fleets;
private final Map<Fleet, TrackedRace> trackedRaces;
private boolean medalRace;
private String name;
private RaceIdentifier raceIdentifier;
private final Map<Fleet, RaceIdentifier> raceIdentifiers;
public RaceColumnImpl(String name, boolean medalRace) {
public RaceColumnImpl(String name, boolean medalRace, Iterable<Fleet> fleets) {
this.name = name;
this.medalRace = medalRace;
this.fleets = fleets;
this.trackedRaces = new HashMap<Fleet, TrackedRace>();
this.raceIdentifiers = new HashMap<Fleet, RaceIdentifier>();
}
@Override
@@ -24,14 +38,14 @@ public class RaceColumnImpl implements RaceColumn {
}
@Override
public TrackedRace getTrackedRace() {
return trackedRace;
public TrackedRace getTrackedRace(Fleet fleet) {
return trackedRaces.get(fleet);
}
@Override
public void setTrackedRace(TrackedRace trackedRace) {
this.trackedRace = trackedRace;
this.setRaceIdentifier(trackedRace == null ? null : trackedRace.getRaceIdentifier());
public void setTrackedRace(Fleet fleet, TrackedRace trackedRace) {
this.trackedRaces.put(fleet, trackedRace);
this.setRaceIdentifier(fleet, trackedRace == null ? null : trackedRace.getRaceIdentifier());
}
@Override
@@ -55,17 +69,47 @@ public class RaceColumnImpl implements RaceColumn {
}
@Override
public RaceIdentifier getRaceIdentifier() {
return raceIdentifier;
public RaceIdentifier getRaceIdentifier(Fleet fleet) {
return raceIdentifiers.get(fleet);
}
@Override
public void setRaceIdentifier(RaceIdentifier raceIdentifier) {
this.raceIdentifier = raceIdentifier;
public void setRaceIdentifier(Fleet fleet, RaceIdentifier raceIdentifier) {
this.raceIdentifiers.put(fleet, raceIdentifier);
}
@Override
public void releaseTrackedRace() {
trackedRace = null;
public void releaseTrackedRace(Fleet fleet) {
trackedRaces.remove(fleet);
}
@Override
public Iterable<Fleet> getFleets() {
return fleets;
}
@Override
public Fleet getFleetByName(String fleetName) {
for (Fleet fleet : getFleets()) {
if (fleet.getName().equals(fleetName)) {
return fleet;
}
}
return null;
}
@Override
public boolean hasTrackedRaces() {
return !trackedRaces.isEmpty();
}
@Override
public TrackedRace getTrackedRace(Competitor competitor) {
for (TrackedRace trackedRace : trackedRaces.values()) {
if (Util.contains(trackedRace.getRace().getCompetitors(), competitor)) {
return trackedRace;
}
}
return null;
}
}
@@ -0,0 +1,39 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.ArrayList;
import java.util.List;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
/**
* A leaderboard that is based on the definition of a {@link Regatta} with its {@link Series} and {@link Fleet}.
*
* @author Axel Uhl (D043530)
*
*/
public class RegattaLeaderboard extends AbstractLeaderboardImpl {
private static final long serialVersionUID = -8243802111008628779L;
private final Regatta regatta;
public RegattaLeaderboard(Regatta regatta, SettableScoreCorrection scoreCorrection,
ThresholdBasedResultDiscardingRule resultDiscardingRule) {
super(regatta.getName(), scoreCorrection, resultDiscardingRule);
this.regatta = regatta;
}
@Override
public Iterable<RaceColumn> getRaceColumns() {
List<RaceColumn> result = new ArrayList<RaceColumn>();
for (Series series : regatta.getSeries()) {
for (RaceColumn raceColumnInSeries : series.getRaceColumns()) {
result.add(raceColumnInSeries);
}
}
return result;
}
}
@@ -93,7 +93,7 @@ public class ScoreCorrectionImpl implements SettableScoreCorrection {
// e.g., in case we have an untracked race and the number of competitors is estimated incorrectly
Integer correctedNonMaxedScore = correctedScores.get(raceColumn.getKey(competitor));
if (correctedNonMaxedScore == null) {
result = getMaxPoints(raceColumn.getTrackedRace(), numberOfCompetitorsInLeaderboard);
result = getMaxPoints(raceColumn.getTrackedRace(competitor), numberOfCompetitorsInLeaderboard);
} else {
result = correctedNonMaxedScore;
}
@@ -57,7 +57,7 @@ public interface DynamicTrackedRace extends TrackedRace {
void setMillisecondsOverWhichToAverageWind(long millisecondsOverWhichToAverageWind);
DynamicTrackedRegatta getTrackedEvent();
DynamicTrackedRegatta getTrackedRegatta();
/**
* If and only if <code>raceIsKnownToStartUpwind</code> is <code>true</code>, this tracked race is allowed to use
@@ -33,7 +33,7 @@ public interface RacesHandle {
*/
Set<RaceDefinition> getRaces(long timeoutInMilliseconds);
DynamicTrackedRegatta getTrackedEvent();
DynamicTrackedRegatta getTrackedRegatta();
/**
* The tracker managing the tracking of the race to which this is a handle.
@@ -301,7 +301,7 @@ public interface TrackedRace extends Serializable {
*/
Tack getTack(Competitor competitor, TimePoint timePoint);
TrackedRegatta getTrackedEvent();
TrackedRegatta getTrackedRegatta();
/**
* Computes a default wind direction based on the direction of the first leg at time <code>at</code>, with a default
@@ -492,8 +492,8 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
}
@Override
public DynamicTrackedRegatta getTrackedEvent() {
return (DynamicTrackedRegatta) super.getTrackedEvent();
public DynamicTrackedRegatta getTrackedRegatta() {
return (DynamicTrackedRegatta) super.getTrackedRegatta();
}
@Override
@@ -270,7 +270,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
abstract protected TrackedLeg createTrackedLeg(Leg leg);
public RegattaAndRaceIdentifier getRaceIdentifier() {
return new RegattaNameAndRaceName(getTrackedEvent().getRegatta().getName(), getRace().getName());
return new RegattaNameAndRaceName(getTrackedRegatta().getRegatta().getName(), getRace().getName());
}
@Override
@@ -1117,7 +1117,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
}
@Override
public TrackedRegatta getTrackedEvent() {
public TrackedRegatta getTrackedRegatta() {
return trackedRegatta;
}
@@ -15,7 +15,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.ExpandableSortableColumn;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO;
public class GwtTestCaseColumnToggling extends GWTTestCase {
@@ -27,6 +27,7 @@ public class GwtTestCaseColumnToggling extends GWTTestCase {
//Test data.
private final String LEADERBOARD_NAME = "test";
private static final String DEFAULT_FLEET_NAME = "Default";
private final String COLUMN1_NAME = "r1";
private final String EVENT_NAME = "Sailing Team Germany (STG)";
protected static final boolean tractracTunnel = true; // Boolean.valueOf(System.getProperty("tractrac.tunnel", "false"));
@@ -128,18 +129,18 @@ public class GwtTestCaseColumnToggling extends GWTTestCase {
@Override
public void onSuccess(Void result) {
System.out.println("Added column to leaderboard.");
RaceInLeaderboardDTO race = new RaceInLeaderboardDTO();
RaceColumnDTO race = new RaceColumnDTO();
race.setRaceColumnName(COLUMN1_NAME);
race.setMedalRace(false);
race.setRaceIdentifier(null);
leaderboardPanel.addColumn(leaderboardPanel.createRaceColumn(race));
linkTrackedRace();
}
});
}
private void linkTrackedRace(){
service.connectTrackedRaceToLeaderboardColumn(LEADERBOARD_NAME, COLUMN1_NAME, new RegattaNameAndRaceName(EVENT_NAME, TRACKED_RACE),
private void linkTrackedRace() {
service.connectTrackedRaceToLeaderboardColumn(LEADERBOARD_NAME, COLUMN1_NAME, DEFAULT_FLEET_NAME,
new RegattaNameAndRaceName(EVENT_NAME, TRACKED_RACE),
new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
@@ -10,7 +10,7 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory;
import com.sap.sailing.gwt.ui.leaderboard.SortableColumn;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
public class LeaderboardPanelMock extends LeaderboardPanel {
@@ -29,7 +29,7 @@ public class LeaderboardPanelMock extends LeaderboardPanel {
}
@Override
public RaceColumn<?> createRaceColumn(RaceInLeaderboardDTO race) {
public RaceColumn<?> createRaceColumn(RaceColumnDTO race) {
// TODO Auto-generated method stub
return super.createRaceColumn(race);
}
@@ -15,12 +15,13 @@ import org.junit.Test;
import com.sap.sailing.gwt.ui.server.SailingServiceImpl;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
public class TestColumnSwapping {
private LeaderboardDTO lb = null;
private static final String LEADERBOARDNAME = "test";
private static final String DEFAULT_FLEET_NAME = "Default";
private SailingServiceImpl service;
private LeaderboardDTO leaderboardOriginalDTO;
private LeaderboardDTO leaderboardDTO;
@@ -49,9 +50,9 @@ public class TestColumnSwapping {
try {
// get Leaderboard with name and current date
leaderboardOriginalDTO = new LeaderboardDTO();
leaderboardOriginalDTO.addRace("Race1", true, null, null);
leaderboardOriginalDTO.addRace("Race3", true, null, null);
leaderboardOriginalDTO.addRace("Race2", true, null, null);
leaderboardOriginalDTO.addRace("Race1", DEFAULT_FLEET_NAME, true, null, null);
leaderboardOriginalDTO.addRace("Race3", DEFAULT_FLEET_NAME, true, null, null);
leaderboardOriginalDTO.addRace("Race2", DEFAULT_FLEET_NAME, true, null, null);
} catch (Exception e) {
e.printStackTrace();
}
@@ -100,9 +101,9 @@ public class TestColumnSwapping {
public void testLeaderBoardDTOMethods() {
lb = new LeaderboardDTO();
assertNotNull("Leaderboard != NULL", lb);
lb.addRace("1", false, null, null);
lb.addRace("2", false, null, null);
lb.addRace("3", true, null, null);
lb.addRace("1", DEFAULT_FLEET_NAME, false, null, null);
lb.addRace("2", DEFAULT_FLEET_NAME, false, null, null);
lb.addRace("3", DEFAULT_FLEET_NAME, true, null, null);
lb.moveRaceDown("1");
String[] s = new String[] { "2", "1", "3" };
for (int i = 0; i < lb.getRaceList().size(); i++)
@@ -120,13 +121,13 @@ public class TestColumnSwapping {
}
// check if leaderboardDTO an dleaderboardOriginalDTO same
List<RaceInLeaderboardDTO> leaderboardList = leaderboardDTO.getRaceList();
List<RaceInLeaderboardDTO> leaderboardOriginalList = leaderboardOriginalDTO.getRaceList();
List<RaceColumnDTO> leaderboardList = leaderboardDTO.getRaceList();
List<RaceColumnDTO> leaderboardOriginalList = leaderboardOriginalDTO.getRaceList();
// ??????? assert races in list
assertArrayEquals(leaderboardList.toArray(), leaderboardOriginalList.toArray());
for (RaceInLeaderboardDTO raceDTO : leaderboardOriginalList) {
for (RaceColumnDTO raceDTO : leaderboardOriginalList) {
assert leaderboardDTO.raceIsMedalRace(raceDTO.getRaceColumnName()) == leaderboardOriginalDTO.raceIsMedalRace(raceDTO.getRaceColumnName());
assert leaderboardDTO.raceIsTracked(raceDTO.getRaceColumnName()) == leaderboardOriginalDTO.raceIsTracked(raceDTO.getRaceColumnName());
}
@@ -4,7 +4,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.cell.client.CheckboxCell;
@@ -45,16 +47,16 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.URLFactory;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplayer, RaceSelectionChangeListener,
TrackedRaceChangedListener {
@@ -67,17 +69,17 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
private final ListDataProvider<LeaderboardDTO> leaderboardList;
private final ListDataProvider<RaceInLeaderboardDTO> raceColumnList;
private final ListDataProvider<Pair<RaceColumnDTO, String>> raceColumnAndFleetNameList;
private final ErrorReporter errorReporter;
private final CellTable<LeaderboardDTO> leaderboardTable;
private final CellTable<RaceInLeaderboardDTO> raceColumnTable;
private final CellTable<Pair<RaceColumnDTO, String>> raceColumnTable;
private LeaderboardDTO selectedLeaderboard;
private RaceInLeaderboardDTO selectedRaceInLeaderboard;
private Pair<RaceColumnDTO, String> selectedRaceInLeaderboard;
private final Button addColumnButton;
@@ -90,7 +92,7 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
private TextBox filterLeaderboardTextbox;
final SingleSelectionModel<RaceInLeaderboardDTO> raceColumnTableSelectionModel;
final SingleSelectionModel<Pair<RaceColumnDTO, String>> raceColumnTableSelectionModel;
private List<LeaderboardDTO> availableLeaderboardList;
@@ -118,7 +120,7 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
this.stringMessages = theStringConstants;
this.sailingService = sailingService;
leaderboardList = new ListDataProvider<LeaderboardDTO>();
raceColumnList = new ListDataProvider<RaceInLeaderboardDTO>();
raceColumnAndFleetNameList = new ListDataProvider<Pair<RaceColumnDTO, String>>();
this.errorReporter = errorReporter;
this.availableLeaderboardList = new ArrayList<LeaderboardDTO>();
VerticalPanel mainPanel = new VerticalPanel();
@@ -302,60 +304,66 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
// ------------ races of the selected leaderboard ----------------
AnchorCell raceAnchorCell = new AnchorCell();
Column<RaceInLeaderboardDTO, SafeHtml> raceLinkColumn = new Column<RaceInLeaderboardDTO, SafeHtml>(raceAnchorCell) {
Column<Pair<RaceColumnDTO, String>, SafeHtml> raceLinkColumn = new Column<Pair<RaceColumnDTO, String>, SafeHtml>(raceAnchorCell) {
@Override
public SafeHtml getValue(RaceInLeaderboardDTO raceInLeaderboardDTO) {
if(raceInLeaderboardDTO.getRaceIdentifier() != null) {
RegattaNameAndRaceName raceIdentifier = (RegattaNameAndRaceName) raceInLeaderboardDTO.getRaceIdentifier();
public SafeHtml getValue(Pair<RaceColumnDTO, String> raceInLeaderboardDTOAndFleetName) {
if (raceInLeaderboardDTOAndFleetName.getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB()) != null) {
RegattaNameAndRaceName raceIdentifier = (RegattaNameAndRaceName) raceInLeaderboardDTOAndFleetName
.getA().getRaceIdentifier(raceInLeaderboardDTOAndFleetName.getB());
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName="
+ selectedLeaderboard.name + "&raceName=" + raceIdentifier.getRaceName() + "&regattaName="
+ raceIdentifier.getRegattaName()
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
return ANCHORTEMPLATE.cell(link, raceInLeaderboardDTO.getRaceColumnName());
return ANCHORTEMPLATE.cell(link, raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName());
} else {
return SafeHtmlUtils.fromString(raceInLeaderboardDTO.getRaceColumnName());
return SafeHtmlUtils.fromString(raceInLeaderboardDTOAndFleetName.getA().getRaceColumnName());
}
}
};
Column<RaceInLeaderboardDTO, Boolean> isMedalRaceCheckboxColumn = new Column<RaceInLeaderboardDTO, Boolean>(
new CheckboxCell()) {
TextColumn<Pair<RaceColumnDTO, String>> fleetNameColumn = new TextColumn<Pair<RaceColumnDTO, String>>() {
@Override
public Boolean getValue(RaceInLeaderboardDTO race) {
return race.isMedalRace();
public String getValue(Pair<RaceColumnDTO, String> object) {
return object.getB();
}
};
isMedalRaceCheckboxColumn.setFieldUpdater(new FieldUpdater<RaceInLeaderboardDTO, Boolean>() {
Column<Pair<RaceColumnDTO, String>, Boolean> isMedalRaceCheckboxColumn = new Column<Pair<RaceColumnDTO, String>, Boolean>(
new CheckboxCell()) {
@Override
public void update(int index, RaceInLeaderboardDTO object, Boolean value) {
setIsMedalRace(selectedLeaderboard.name, object, value);
public Boolean getValue(Pair<RaceColumnDTO, String> race) {
return race.getA().isMedalRace();
}
};
isMedalRaceCheckboxColumn.setFieldUpdater(new FieldUpdater<Pair<RaceColumnDTO, String>, Boolean>() {
@Override
public void update(int index, Pair<RaceColumnDTO, String> object, Boolean value) {
setIsMedalRace(selectedLeaderboard.name, object.getA(), value);
}
});
isMedalRaceCheckboxColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
TextColumn<RaceInLeaderboardDTO> isLinkedRaceColumn = new TextColumn<RaceInLeaderboardDTO>() {
TextColumn<Pair<RaceColumnDTO, String>> isLinkedRaceColumn = new TextColumn<Pair<RaceColumnDTO, String>>() {
@Override
public String getValue(RaceInLeaderboardDTO race) {
boolean isTrackedRace = race.isTrackedRace();
public String getValue(Pair<RaceColumnDTO, String> raceColumnAndFleetName) {
boolean isTrackedRace = raceColumnAndFleetName.getA().isTrackedRace(raceColumnAndFleetName.getB());
return isTrackedRace ? stringMessages.yes() : stringMessages.no();
}
};
ImagesBarColumn<RaceInLeaderboardDTO, LeaderboardRaceConfigImagesBarCell> raceActionColumn = new ImagesBarColumn<RaceInLeaderboardDTO, LeaderboardRaceConfigImagesBarCell>(
new LeaderboardRaceConfigImagesBarCell(stringMessages));
raceActionColumn.setFieldUpdater(new FieldUpdater<RaceInLeaderboardDTO, String>() {
ImagesBarColumn<Pair<RaceColumnDTO, String>, LeaderboardRaceConfigImagesBarCell> raceActionColumn =
new ImagesBarColumn<Pair<RaceColumnDTO, String>, LeaderboardRaceConfigImagesBarCell>(
new LeaderboardRaceConfigImagesBarCell(stringMessages));
raceActionColumn.setFieldUpdater(new FieldUpdater<Pair<RaceColumnDTO, String>, String>() {
@Override
public void update(int index, RaceInLeaderboardDTO object, String value) {
public void update(int index, Pair<RaceColumnDTO, String> object, String value) {
if ("ACTION_REMOVE".equals(value)) {
if (Window.confirm(stringMessages.reallyRemoveRace(object.getRaceColumnName()))) {
removeRaceColumn(object);
if (Window.confirm(stringMessages.reallyRemoveRace(object.getA().getRaceColumnName()))) {
removeRaceColumn(object.getA());
}
} else if ("ACTION_EDIT".equals(value)) {
editRaceColumnOfLeaderboard(object);
} else if ("ACTION_UNLINK".equals(value)) {
unlinkRaceColumnFromTrackedRace(object.getRaceColumnName());
unlinkRaceColumnFromTrackedRace(object.getA().getRaceColumnName(), object.getB());
}
}
});
@@ -363,14 +371,15 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
Label lblRaceNamesIn = new Label(stringMessages.races());
vPanel.add(lblRaceNamesIn);
raceColumnTable = new CellTable<RaceInLeaderboardDTO>(/* pageSize */200, tableRes);
raceColumnTable = new CellTable<Pair<RaceColumnDTO, String>>(/* pageSize */200, tableRes);
raceColumnTable.addColumn(raceLinkColumn, stringMessages.name());
raceColumnTable.addColumn(fleetNameColumn, stringMessages.fleet());
raceColumnTable.addColumn(isMedalRaceCheckboxColumn, stringMessages.medalRace());
raceColumnTable.addColumn(isLinkedRaceColumn, stringMessages.islinked());
raceColumnTable.addColumn(raceActionColumn, stringMessages.actions());
raceColumnList.addDataDisplay(raceColumnTable);
raceColumnAndFleetNameList.addDataDisplay(raceColumnTable);
raceColumnTable.setWidth("500px");
raceColumnTableSelectionModel = new SingleSelectionModel<RaceInLeaderboardDTO>();
raceColumnTableSelectionModel = new SingleSelectionModel<Pair<RaceColumnDTO, String>>();
raceColumnTable.setSelectionModel(raceColumnTableSelectionModel);
@@ -455,40 +464,46 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
}
}
private void unlinkRaceColumnFromTrackedRace(final String raceColumn) {
private void unlinkRaceColumnFromTrackedRace(final String raceColumnName, final String fleetName) {
final String selectedLeaderboardName = getSelectedLeaderboardName();
sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumn,
sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, fleetName,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumn
errorReporter.reportError("Error trying to unlink tracked race from column " + raceColumnName
+ " from leaderboard " + selectedLeaderboardName + ": " + t.getMessage());
}
@Override
public void onSuccess(Void arg0) {
trackedRacesListComposite.clearSelection();
getSelectedRaceInLeaderboard().setRaceIdentifier(null);
raceColumnList.refresh();
getSelectedRaceColumnAndFleetName().getA().setRaceIdentifier(fleetName, null);
raceColumnAndFleetNameList.refresh();
}
});
}
private void removeRaceColumn(final RaceInLeaderboardDTO raceColumn) {
final String raceColumnString = raceColumn.getRaceColumnName();
private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) {
final String raceColumnString = raceColumnDTO.getRaceColumnName();
sailingService.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumn
errorReporter.reportError("Error trying to remove leaderboard race column " + raceColumnDTO
+ " in leaderboard " + getSelectedLeaderboardName() + ": " + t.getMessage());
}
@Override
public void onSuccess(Void arg0) {
raceColumnList.getList().remove(raceColumn);
if (raceColumnTableSelectionModel.isSelected(raceColumn)) {
raceColumnTableSelectionModel.setSelected(raceColumn, false);
Iterator<Pair<RaceColumnDTO, String>> rowIter = raceColumnAndFleetNameList.getList().iterator();
while (rowIter.hasNext()) {
Pair<RaceColumnDTO, String> next = rowIter.next();
if (raceColumnTableSelectionModel.isSelected(next)) {
raceColumnTableSelectionModel.setSelected(next, false);
}
if (next.getA() == raceColumnDTO) {
rowIter.remove();
}
}
// selectedLeaderboard.raceNamesAndMedalRaceAndTracked.remove(raceColumn);
selectedLeaderboard.removeRace(raceColumnString);
@@ -497,9 +512,12 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
});
}
/**
* The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case,
* move all fleet-based rows of the same RaceColumn down.
*/
private void moveSelectedRaceColumnDown() {
final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getRaceColumnName();
final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName();
sailingService.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName,
new AsyncCallback<Void>() {
@Override
@@ -511,34 +529,17 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onSuccess(Void result) {
int rowIndex = getRowIndexOfSelectedRaceColumn();
if (rowIndex < raceColumnList.getList().size() - 1) {
Collections.swap(raceColumnList.getList(), rowIndex, rowIndex + 1);
selectedLeaderboard.moveRaceDown(selectedRaceColumnName);
}
leaderboardSelectionChanged();
}
});
}
private int getRowIndexOfSelectedRaceColumn() {
final RaceInLeaderboardDTO selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject();
int rowIndex = -1;
if (selectedRaceColumnName != null) {
int listSize = raceColumnList.getList().size();
for (int i = 0; i < listSize; i++) {
if (selectedRaceColumnName.equals(raceColumnList.getList().get(i))) {
rowIndex = i;
break;
}
}
}
return rowIndex;
}
/**
* The selected row is potentially only one of several fleet-based rows of the same RaceColumn. In this case,
* move all fleet-based rows of the same RaceColumn down.
*/
private void moveSelectedRaceColumnUp() {
final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getRaceColumnName();
final String selectedRaceColumnName = raceColumnTableSelectionModel.getSelectedObject().getA().getRaceColumnName();
sailingService.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName,
new AsyncCallback<Void>() {
@Override
@@ -550,21 +551,18 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onSuccess(Void result) {
int rowIndex = getRowIndexOfSelectedRaceColumn();
if (rowIndex > 0) {
Collections.swap(raceColumnList.getList(), rowIndex, rowIndex - 1);
selectedLeaderboard.moveRaceUp(selectedRaceColumnName);
}
leaderboardSelectionChanged();
}
});
}
private void leaderboardRaceColumnSelectionChanged() {
selectedRaceInLeaderboard = getSelectedRaceInLeaderboard();
selectedRaceInLeaderboard = getSelectedRaceColumnAndFleetName();
if (selectedRaceInLeaderboard != null) {
columnMoveUpButton.setEnabled(true);
columnMoveDownButton.setEnabled(true);
reloadRaceInLeaderboardRow(selectedRaceInLeaderboard.getRaceColumnName(), selectedRaceInLeaderboard);
reloadRaceInLeaderboardRow(selectedRaceInLeaderboard.getA().getRaceColumnName(), /* fleet name */ selectedRaceInLeaderboard.getB(),
selectedRaceInLeaderboard);
selectTrackedRaceInRaceList();
} else {
columnMoveUpButton.setEnabled(false);
@@ -575,9 +573,11 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
private void selectTrackedRaceInRaceList() {
final String selectedLeaderboardName = getSelectedLeaderboardName();
final String selectedRaceColumnName = getSelectedRaceInLeaderboard().getRaceColumnName();
final Pair<RaceColumnDTO, String> selectedRaceColumnAndFleetNameInLeaderboard = getSelectedRaceColumnAndFleetName();
final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA().getRaceColumnName();
final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB();
sailingService.getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName,
selectedRaceColumnName, new AsyncCallback<Pair<String, String>>() {
selectedRaceColumnName, new AsyncCallback<Map<String, RegattaAndRaceIdentifier>>() {
@Override
public void onFailure(Throwable t) {
errorReporter.reportError("Error trying to determine tracked race linked to race column "
@@ -586,9 +586,14 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
}
@Override
public void onSuccess(Pair<String, String> regattaAndRaceName) {
if (regattaAndRaceName != null) {
selectRaceInList(regattaAndRaceName.getA(), regattaAndRaceName.getB());
public void onSuccess(Map<String, RegattaAndRaceIdentifier> regattaAndRaceNamesPerFleet) {
if (regattaAndRaceNamesPerFleet != null && !regattaAndRaceNamesPerFleet.isEmpty()) {
RegattaAndRaceIdentifier raceIdentifier = regattaAndRaceNamesPerFleet.get(selectedFleetName);
if (raceIdentifier != null) {
selectRaceInList(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName());
} else {
trackedRacesListComposite.clearSelection();
}
} else {
trackedRacesListComposite.clearSelection();
}
@@ -601,26 +606,26 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
trackedRacesListComposite.selectRaceByIdentifier(raceIdentifier);
}
private RaceInLeaderboardDTO getSelectedRaceInLeaderboard() {
RaceInLeaderboardDTO raceInLeaderboard = raceColumnTableSelectionModel.getSelectedObject();
return raceInLeaderboard;
private Pair<RaceColumnDTO, String> getSelectedRaceColumnAndFleetName() {
Pair<RaceColumnDTO, String> raceInLeaderboardAndFleetName = raceColumnTableSelectionModel.getSelectedObject();
return raceInLeaderboardAndFleetName;
}
private void editRaceColumnOfLeaderboard(final RaceInLeaderboardDTO raceInLeaderboard) {
final String oldRaceName = raceInLeaderboard.getRaceColumnName();
List<RaceInLeaderboardDTO> existingRacesWithoutThisRace = new ArrayList<RaceInLeaderboardDTO>();
existingRacesWithoutThisRace.addAll(raceColumnList.getList());
existingRacesWithoutThisRace.remove(raceInLeaderboard);
final RaceInLeaderboardDialog raceDialog = new RaceInLeaderboardDialog(existingRacesWithoutThisRace,
raceInLeaderboard, stringMessages, new AsyncCallback<RaceInLeaderboardDTO>() {
private void editRaceColumnOfLeaderboard(final Pair<RaceColumnDTO, String> object) {
final String oldRaceName = object.getA().getRaceColumnName();
List<Pair<RaceColumnDTO, String>> existingRacesWithoutThisRace = new ArrayList<Pair<RaceColumnDTO, String>>();
existingRacesWithoutThisRace.addAll(raceColumnAndFleetNameList.getList());
existingRacesWithoutThisRace.remove(object);
final RaceColumnDialog raceDialog = new RaceColumnDialog(existingRacesWithoutThisRace,
object.getA(), stringMessages, new AsyncCallback<Pair<RaceColumnDTO, String>>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(final RaceInLeaderboardDTO result) {
public void onSuccess(final Pair<RaceColumnDTO, String> result) {
sailingService.renameLeaderboardColumn(getSelectedLeaderboardName(), oldRaceName,
result.getRaceColumnName(), new AsyncCallback<Void>() {
result.getA().getRaceColumnName(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
@@ -629,7 +634,7 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onSuccess(Void v) {
sailingService.updateIsMedalRace(getSelectedLeaderboardName(),
result.getRaceColumnName(), result.isMedalRace(),
result.getA().getRaceColumnName(), result.getA().isMedalRace(),
new AsyncCallback<Void>() {
@Override
@@ -638,8 +643,8 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onSuccess(Void v) {
raceInLeaderboard.setMedalRace(result.isMedalRace());
reloadRaceInLeaderboardRow(oldRaceName, result);
object.getA().setMedalRace(result.getA().isMedalRace());
reloadRaceInLeaderboardRow(oldRaceName, /* fleet name */ result.getB(), result);
}
});
}
@@ -650,22 +655,22 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
raceDialog.show();
}
private void reloadRaceInLeaderboardRow(String oldRaceName, RaceInLeaderboardDTO raceInLeaderboard) {
private void reloadRaceInLeaderboardRow(String oldRaceName, String oldFleetName, Pair<RaceColumnDTO, String> newRaceColumnAndFleetName) {
int index = -1;
for (int i = 0; i < raceColumnList.getList().size(); i++) {
RaceInLeaderboardDTO race = raceColumnList.getList().get(i);
if (race.getRaceColumnName().equals(oldRaceName)) {
for (int i = 0; i < raceColumnAndFleetNameList.getList().size(); i++) {
Pair<RaceColumnDTO, String> raceColumnAndFleetName = raceColumnAndFleetNameList.getList().get(i);
if (raceColumnAndFleetName.getA().getRaceColumnName().equals(oldRaceName) && raceColumnAndFleetName.getB().equals(oldFleetName)) {
index = i;
break;
}
}
if (index != -1) {
raceColumnList.getList().set(index, raceInLeaderboard);
raceColumnAndFleetNameList.getList().set(index, newRaceColumnAndFleetName);
}
raceColumnList.refresh();
raceColumnAndFleetNameList.refresh();
}
private void setIsMedalRace(String leaderboardName, final RaceInLeaderboardDTO raceInLeaderboard,
private void setIsMedalRace(String leaderboardName, final RaceColumnDTO raceInLeaderboard,
final boolean isMedalRace) {
sailingService.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace,
new AsyncCallback<Void>() {
@@ -682,24 +687,22 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
}
private void addRaceColumnToLeaderboard() {
final RaceInLeaderboardDTO raceInLeaderboard = new RaceInLeaderboardDTO();
final RaceColumnDTO raceInLeaderboard = new RaceColumnDTO();
final String leaderboardName = getSelectedLeaderboardName();
final RaceInLeaderboardDialog raceDialog = new RaceInLeaderboardDialog(raceColumnList.getList(),
raceInLeaderboard, stringMessages, new AsyncCallback<RaceInLeaderboardDTO>() {
final RaceColumnDialog raceDialog = new RaceColumnDialog(raceColumnAndFleetNameList.getList(),
raceInLeaderboard, stringMessages, new AsyncCallback<Pair<RaceColumnDTO, String>>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(final RaceInLeaderboardDTO result) {
sailingService.addColumnToLeaderboard(result.getRaceColumnName(), leaderboardName,
result.isMedalRace(), new AsyncCallback<Void>() {
public void onSuccess(final Pair<RaceColumnDTO, String> result) {
sailingService.addColumnToLeaderboard(result.getA().getRaceColumnName(), leaderboardName,
result.getA().isMedalRace(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError("Error trying to add column "
+ result.getRaceColumnName() + " to leaderboard " + leaderboardName
+ result.getA().getRaceColumnName() + " to leaderboard " + leaderboardName
+ ": " + caught.getMessage());
}
@@ -707,12 +710,12 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onSuccess(Void v) {
// columnNamesInSelectedLeaderboardListBox.addItem(columnNameAndMedalRace.getA());
raceColumnList.getList().add(result);
raceColumnAndFleetNameList.getList().add(result);
// selectedLeaderboard.raceNamesAndMedalRaceAndTracked.put(columnNameAndMedalRace.getA(),
// new Pair<Boolean, Boolean>(/* medal race */ columnNameAndMedalRace.getB(),
// /* tracked */ false));
selectedLeaderboard.addRace(result.getRaceColumnName(), result.isMedalRace(),
null, null);
selectedLeaderboard.addRace(result.getA().getRaceColumnName(), /* fleet name */ result.getB(),
result.getA().isMedalRace(), /* tracked race identifier */ null, /* StrippedRaceDTO */ null);
selectedLeaderboard.invalidateCompetitorOrdering();
}
});
@@ -738,12 +741,16 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
}
});
if (selectedLeaderboard != null) {
raceColumnList.getList().clear();
raceColumnList.getList().addAll(selectedLeaderboard.getRaceList());
selectedLeaderBoardPanel.setVisible(true);
trackedRacesCaptionPanel.setVisible(true);
selectedLeaderBoardPanel.setCaptionText("Details of leaderboard '" + selectedLeaderboard.name + "'");
addColumnButton.setEnabled(true);
raceColumnAndFleetNameList.getList().clear();
for (RaceColumnDTO raceColumn : selectedLeaderboard.getRaceList()) {
for (String fleetName : raceColumn.getFleetNames()) {
raceColumnAndFleetNameList.getList().add(new Pair<RaceColumnDTO, String>(raceColumn, fleetName));
}
}
selectedLeaderBoardPanel.setVisible(true);
trackedRacesCaptionPanel.setVisible(true);
selectedLeaderBoardPanel.setCaptionText("Details of leaderboard '" + selectedLeaderboard.name + "'");
addColumnButton.setEnabled(true);
} else {
selectedLeaderBoardPanel.setVisible(false);
trackedRacesCaptionPanel.setVisible(false);
@@ -760,12 +767,12 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void changeTrackingRace(RegattaNameAndRaceName regattaNameAndRaceName, boolean isTracked) {
for (RaceInLeaderboardDTO race : raceColumnList.getList()) {
if (race.getRaceColumnName().equals(regattaNameAndRaceName.getRaceName())) {
race.setRaceIdentifier(regattaNameAndRaceName);
for (Pair<RaceColumnDTO, String> raceColumnAndFleetName : raceColumnAndFleetNameList.getList()) {
if (raceColumnAndFleetName.getA().getRaceColumnName().equals(regattaNameAndRaceName.getRaceName())) {
raceColumnAndFleetName.getA().setRaceIdentifier(raceColumnAndFleetName.getB(), regattaNameAndRaceName);
}
}
raceColumnList.refresh();
raceColumnAndFleetNameList.refresh();
}
private void addNewLeaderboard() {
@@ -850,20 +857,21 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
@Override
public void onRaceSelectionChange(List<RegattaAndRaceIdentifier> selectedRaces) {
// if no leaderboard column is selected, ignore the race selection change
RaceInLeaderboardDTO selectedRaceInLeaderboard = getSelectedRaceInLeaderboard();
if (selectedRaceInLeaderboard != null) {
Pair<RaceColumnDTO, String> selectedRaceColumnAndFleetName = getSelectedRaceColumnAndFleetName();
if (selectedRaceColumnAndFleetName != null) {
if (selectedRaces.isEmpty()) {
unlinkRaceColumnFromTrackedRace(selectedRaceInLeaderboard.getRaceColumnName());
unlinkRaceColumnFromTrackedRace(selectedRaceColumnAndFleetName.getA().getRaceColumnName(), selectedRaceColumnAndFleetName.getB());
} else {
linkTrackedRaceToSelectedRaceColumn(selectedRaceInLeaderboard, selectedRaces.iterator().next());
linkTrackedRaceToSelectedRaceColumn(selectedRaceColumnAndFleetName.getA(), selectedRaceColumnAndFleetName.getB(),
selectedRaces.iterator().next());
}
}
}
private void linkTrackedRaceToSelectedRaceColumn(final RaceInLeaderboardDTO selectedRaceInLeaderboard,
final RegattaAndRaceIdentifier selectedRace) {
private void linkTrackedRaceToSelectedRaceColumn(final RaceColumnDTO selectedRaceInLeaderboard,
final String fleetName, final RegattaAndRaceIdentifier selectedRace) {
sailingService.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), selectedRaceInLeaderboard
.getRaceColumnName(), selectedRace,
.getRaceColumnName(), fleetName, selectedRace,
new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable t) {
@@ -877,8 +885,8 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
public void onSuccess(Boolean success) {
if (success) {
// TODO consider enabling the Unlink button
selectedRaceInLeaderboard.setRaceIdentifier(selectedRace);
raceColumnList.refresh();
selectedRaceInLeaderboard.setRaceIdentifier(fleetName, selectedRace);
raceColumnAndFleetNameList.refresh();
}
}
});
@@ -45,7 +45,7 @@ import com.sap.sailing.gwt.ui.client.URLFactory;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
@@ -203,7 +203,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
public String getValue(LeaderboardDTO leaderboard) {
String result = "";
boolean first = true;
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
for (RaceColumnDTO race : leaderboard.getRaceList()) {
if (!first) {
result += "; ";
}
@@ -308,7 +308,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
public String getValue(LeaderboardDTO leaderboard) {
String result = "";
boolean first = true;
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
for (RaceColumnDTO race : leaderboard.getRaceList()) {
if (!first) {
result += "; ";
}
@@ -7,38 +7,47 @@ import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
public class RaceInLeaderboardDialog extends DataEntryDialog<RaceInLeaderboardDTO> {
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
/**
* Fills a {@link RaceColumnDTO} object by setting its {@link RaceColumnDTO#setMedalRace(boolean) medal race} property and its name.
* As {@link RaceColumnDTO#getFleetNames()} fleet, a single default fleet is added.
*
* @author Axel Uhl (D043530)
*
*/
public class RaceColumnDialog extends DataEntryDialog<Pair<RaceColumnDTO, String>> {
private final static String DEFAULT_FLEET_NAME = "Default";
private final TextBox raceNameBox;
private final CheckBox isMedalRace;
private RaceInLeaderboardDTO raceInLeaderboard;
private RaceColumnDTO raceInLeaderboard;
private static class RaceDialogValidator implements Validator<RaceInLeaderboardDTO> {
private static class RaceDialogValidator implements Validator<Pair<RaceColumnDTO, String>> {
private StringMessages stringConstants;
private Collection<RaceInLeaderboardDTO> existingRaces;
private Collection<Pair<RaceColumnDTO, String>> existingRaces;
public RaceDialogValidator(StringMessages stringConstants, Collection<RaceInLeaderboardDTO> existingRaces) {
public RaceDialogValidator(StringMessages stringConstants, Collection<Pair<RaceColumnDTO, String>> existingRaceColumnsAndFleetNames) {
this.stringConstants = stringConstants;
this.existingRaces = existingRaces;
this.existingRaces = existingRaceColumnsAndFleetNames;
}
@Override
public String getErrorMessage(RaceInLeaderboardDTO valueToValidate) {
public String getErrorMessage(Pair<RaceColumnDTO, String> valueToValidate) {
String errorMessage;
String racename = valueToValidate.getRaceColumnName();
Boolean isMedalRace = valueToValidate.isMedalRace();
String racename = valueToValidate.getA().getRaceColumnName();
Boolean isMedalRace = valueToValidate.getA().isMedalRace();
boolean isNameNotEmpty = racename != null & racename != "";
boolean medalRaceNotNull = isMedalRace != null;
boolean unique = true;
for (RaceInLeaderboardDTO dao : existingRaces) {
if (dao.getRaceColumnName().equals(valueToValidate.getRaceColumnName())) {
for (Pair<RaceColumnDTO, String> raceColumnAndFleetName : existingRaces) {
if (raceColumnAndFleetName.getA().getRaceColumnName().equals(valueToValidate.getA().getRaceColumnName())) {
unique = false;
}
}
@@ -57,9 +66,9 @@ public class RaceInLeaderboardDialog extends DataEntryDialog<RaceInLeaderboardDT
}
public RaceInLeaderboardDialog(Collection<RaceInLeaderboardDTO> existingRaces,
RaceInLeaderboardDTO raceInLeaderboard, StringMessages stringConstants,
AsyncCallback<RaceInLeaderboardDTO> callback) {
public RaceColumnDialog(Collection<Pair<RaceColumnDTO, String>> existingRaces,
RaceColumnDTO raceInLeaderboard, StringMessages stringConstants,
AsyncCallback<Pair<RaceColumnDTO, String>> callback) {
super(stringConstants.name(), null, stringConstants.ok(), stringConstants.cancel(),
new RaceDialogValidator(stringConstants, existingRaces), callback);
this.raceInLeaderboard = raceInLeaderboard;
@@ -69,10 +78,11 @@ public class RaceInLeaderboardDialog extends DataEntryDialog<RaceInLeaderboardDT
}
@Override
protected RaceInLeaderboardDTO getResult() {
protected Pair<RaceColumnDTO, String> getResult() {
raceInLeaderboard.setRaceColumnName(raceNameBox.getValue());
raceInLeaderboard.setMedalRace(isMedalRace.getValue());
return raceInLeaderboard;
raceInLeaderboard.addFleetName(DEFAULT_FLEET_NAME);
return new Pair<RaceColumnDTO, String>(raceInLeaderboard, raceInLeaderboard.getFleetNames().iterator().next());
}
@Override
@@ -53,6 +53,7 @@ import com.sap.sailing.gwt.ui.client.RegattaRefresher;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.URLFactory;
import com.sap.sailing.gwt.ui.shared.BoatClassDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
@@ -183,7 +184,8 @@ public class TrackedRacesListComposite extends FormPanel implements RegattaDispl
TextColumn<RaceDTO> deprecatedRegattaNameColumn = new TextColumn<RaceDTO>() {
@Override
public String getValue(RaceDTO raceDTO) {
return raceDTO.getRegatta().boatClass.name;
final BoatClassDTO boatClass = raceDTO.getRegatta().boatClass;
return boatClass == null ? "" : boatClass.name;
}
};
deprecatedRegattaNameColumn.setSortable(true);
@@ -1,6 +1,5 @@
package com.sap.sailing.gwt.ui.client;
import com.sap.sailing.gwt.ui.shared.panels.ClosableWelcomeWidget;
import com.sap.sailing.gwt.ui.shared.panels.SimpleWelcomeWidget;
import com.sap.sailing.gwt.ui.shared.panels.WelcomeWidget;
@@ -14,7 +13,7 @@ public interface HasWelcomeWidget {
/**
* Sets the welcome widget of the component.
* @param welcome The new welcome widget
* @see {@link WelcomeWidget}, {@link SimpleWelcomeWidget}, {@link ClosableWelcomeWidget}, ...
* @see {@link WelcomeWidget}, {@link SimpleWelcomeWidget}
*/
void setWelcomeWidget(WelcomeWidget welcome);
void setWelcomeWidgetVisible(boolean isVisible);
@@ -8,17 +8,16 @@ import java.util.Map;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NoWindException;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.CourseDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
@@ -28,6 +27,7 @@ import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.ReplicationStateDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationDTO;
import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO;
@@ -116,11 +116,11 @@ public interface SailingService extends RemoteService {
void moveLeaderboardColumnDown(String leaderboardName, String columnName);
boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName,
RaceIdentifier raceIdentifier);
String fleetName, RaceIdentifier raceIdentifier);
void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName);
void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName);
Pair<String, String> getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName);
Map<String, RegattaAndRaceIdentifier> getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName);
void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Integer carriedPoints);
@@ -25,7 +25,7 @@ import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
import com.sap.sailing.gwt.ui.shared.MultiCompetitorRaceDataDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.ReplicationStateDTO;
@@ -159,7 +159,7 @@ public interface SailingServiceAsync {
/**
* Creates a {@link LeaderboardDTO} for each leaderboard known by the server and fills in the name, race master data
* in the form of {@link RaceInLeaderboardDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints
* in the form of {@link RaceColumnDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints
* carried points} and the {@link LeaderboardDTO#discardThresholds discarding thresholds} for the leaderboard. No
* data about the points is filled into the result object. No data about the competitor display names is filled in;
* instead, an empty map is used for {@link LeaderboardDTO#competitorDisplayNames}.
@@ -196,16 +196,19 @@ public interface SailingServiceAsync {
void removeLeaderboardColumn(String leaderboardName, String columnName, AsyncCallback<Void> callback);
/**
* @param asyncCallback receives <code>true</code> if connecting was successful
*/
void connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName,
void connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName,
RaceIdentifier raceIdentifier, AsyncCallback<Boolean> asyncCallback);
/**
* The key set of the map returned contains all fleets of the race column identified by the combination of
* <code>leaderboardName</code> and <code>raceColumnName</code>. If a value is <code>null</code>, there is no
* tracked race currently linked to the fleet in the race column; otherwise, the value is the {@link RaceIdentifier}
* of the tracked race currently connected for the fleet whose name is the key. The map returned is never <code>null</code>.
*/
void getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName,
AsyncCallback<Pair<String, String>> callback);
AsyncCallback<Map<String, RegattaAndRaceIdentifier>> callback);
void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName,
void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName,
AsyncCallback<Void> callback);
void updateLeaderboardCarryValue(String leaderboardName, String competitorID, Integer carriedPoints, AsyncCallback<Void> callback);
@@ -239,6 +239,7 @@ public interface StringMessages extends Messages {
String noLeaderboardGroupWithNameFound(String groupName);
String overview();
String welcomeToSailingAnalytics();
String welcomeToSailingAnalyticsBody();
String home();
String clickAndDragToZoomIn();
String windSpeed();
@@ -300,4 +301,5 @@ public interface StringMessages extends Messages {
String replicatingFromMaster(String hostname, int jmsPort, int servletPort);
String showWindSpeedSeries();
String showWindDirectionSeries();
String fleet();
}
@@ -234,6 +234,10 @@ abort=Abort
noLeaderboardGroupWithNameFound=No leaderboard group with the name {0} found
overview=Overview
welcomeToSailingAnalytics=Welcome to SAP Sailing Analytics
welcomeToSailingAnalyticsBody=Understanding what happens out on the race course isn''t always easy. To help solve this challenge and bring the excitement of sailing to the fans, we have developed a leader board based on SAP analytics.\
Through analyzing GPS data together with integrated wind measurements from sensors out on the race course, the leader board displays information such as in-race ranking, average speeds, distance travelled, ETA (estimated time of arrival at the next mark rounding), gaps to leader, gains and losses per leg.\
\
Check out the results for yourself to see who triumphed - and how they did it.
home=Home
clickAndDragToZoomIn=Click and drag in the plot area to zoom in
windSpeed=Wind speed (kts)
@@ -295,3 +299,4 @@ registeredAt=Registered at {0}
replicatingFromMaster=Replicating from master {0}, JMS port {1}, servlet port {2}
showWindSpeedSeries=Show wind speed data
showWindDirectionSeries=Show wind directions data
fleet=Fleet
@@ -235,6 +235,10 @@ abort=Abbrechen
noLeaderboardGroupWithNameFound=Keine Ranglisten-Gruppe mit dem Namen {0} gefunden
overview=Übersicht
welcomeToSailingAnalytics=Willkommen bei SAP Sailing Analytics
welcomeToSailingAnalyticsBody=Understanding what happens out on the race course isn''t always easy. To help solve this challenge and bring the excitement of sailing to the fans, we have developed a leader board based on SAP analytics.\
Through analyzing GPS data together with integrated wind measurements from sensors out on the race course, the leader board displays information such as in-race ranking, average speeds, distance travelled, ETA (estimated time of arrival at the next mark rounding), gaps to leader, gains and losses per leg.\
\
Check out the results for yourself to see who triumphed - and how they did it.
home=Startseite
clickAndDragToZoomIn=Anklicken und ziehen zum Hineinzoomen
windSpeed=Wind speed (sm/h)
@@ -296,3 +300,4 @@ registeredAt=Registriert {0}
replicatingFromMaster=Repliziert von master {0}, JMS Port {1}, Servlet Port {2}
showWindSpeedSeries=Daten für Windgeschwindigkeit zeigen
showWindDirectionSeries=Daten für Windrichtung zeigen
fleet=Flotte
@@ -69,7 +69,7 @@ import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.LegEntryDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.components.Component;
import com.sap.sailing.gwt.ui.shared.components.IsEmbeddableComponent;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialog;
@@ -134,7 +134,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
*/
private final List<DetailType> selectedRaceDetails;
private List<RaceInLeaderboardDTO> selectedRaceColumns;
private List<RaceColumnDTO> selectedRaceColumns;
protected final String RACE_COLUMN_HEADER_STYLE;
@@ -165,7 +165,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
/**
* If this is <code>null</code>, all leaderboard columns added by updating the leaderboard from the server are
* automatically added to the table. Otherwise, only the column whose
* {@link RaceInLeaderboardDTO#getRaceIdentifier() race identifier} matches the value of this attribute will be
* {@link RaceColumnDTO#getRaceIdentifier(String) race identifier} matches the value of this attribute will be
* added.
*/
private final RaceIdentifier preSelectedRace;
@@ -280,7 +280,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
if (newSettings.getNamesOfRaceColumnsToShow() != null) {
selectedRaceColumns.clear();
for (String nameOfRaceColumnToShow : newSettings.getNamesOfRaceColumnsToShow()) {
RaceInLeaderboardDTO raceColumnToShow = getRaceByColumnName(nameOfRaceColumnToShow);
RaceColumnDTO raceColumnToShow = getRaceByColumnName(nameOfRaceColumnToShow);
if (raceColumnToShow != null) {
selectedRaceColumns.add(raceColumnToShow);
}
@@ -288,7 +288,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
} else if (newSettings.getNamesOfRacesToShow() != null) {
selectedRaceColumns.clear();
for (String nameOfRaceToShow : newSettings.getNamesOfRacesToShow()) {
RaceInLeaderboardDTO raceColumnToShow = getRaceByName(nameOfRaceToShow);
RaceColumnDTO raceColumnToShow = getRaceByName(nameOfRaceToShow);
if (raceColumnToShow != null) {
selectedRaceColumns.add(raceColumnToShow);
}
@@ -402,12 +402,12 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
*
*/
protected abstract class RaceColumn<C> extends ExpandableSortableColumn<C> {
private RaceInLeaderboardDTO race;
private RaceColumnDTO race;
private final String headerStyle;
private final String columnStyle;
public RaceColumn(RaceInLeaderboardDTO race, boolean enableExpansion, Cell<C> cell,
public RaceColumn(RaceColumnDTO race, boolean enableExpansion, Cell<C> cell,
String headerStyle, String columnStyle) {
super(LeaderboardPanel.this, enableExpansion, cell, stringMessages, LEG_COLUMN_HEADER_STYLE,
LEG_COLUMN_STYLE, selectedRaceDetails);
@@ -417,7 +417,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
this.columnStyle = columnStyle;
}
public RaceInLeaderboardDTO getRace() {
public RaceColumnDTO getRace() {
return race;
}
@@ -520,7 +520,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
*/
private final List<LegColumn> legColumns;
public TextRaceColumn(RaceInLeaderboardDTO race, boolean expandable, String headerStyle,
public TextRaceColumn(RaceColumnDTO race, boolean expandable, String headerStyle,
String columnStyle) {
super(race, expandable, new TextCell(), headerStyle, columnStyle);
legColumns = new ArrayList<LegColumn>();
@@ -917,7 +917,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
this.stringMessages = stringMessages;
this.selectedLegDetails = new ArrayList<DetailType>();
this.selectedRaceDetails = new ArrayList<DetailType>();
this.selectedRaceColumns = new ArrayList<RaceInLeaderboardDTO>();
this.selectedRaceColumns = new ArrayList<RaceColumnDTO>();
this.selectedManeuverDetails = new ArrayList<DetailType>();
selectedLegDetails.addAll(settings.getLegDetailsToShow());
@@ -1033,20 +1033,23 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
raceNameForDefaultSorting = settings.getNameOfRaceToSort();
}
private RaceInLeaderboardDTO getRaceByName(String raceName) {
private RaceColumnDTO getRaceByName(String raceName) {
if (getLeaderboard() != null) {
for (RaceInLeaderboardDTO race : getLeaderboard().getRaceList()) {
if (race.getRaceIdentifier() != null && raceName.equals(race.getRaceIdentifier().getRaceName())) {
return race;
for (RaceColumnDTO race : getLeaderboard().getRaceList()) {
for (String fleetName : race.getFleetNames()) {
if (race.getRaceIdentifier(fleetName) != null
&& raceName.equals(race.getRaceIdentifier(fleetName).getRaceName())) {
return race;
}
}
}
}
return null;
}
private RaceInLeaderboardDTO getRaceByColumnName(String columnName) {
private RaceColumnDTO getRaceByColumnName(String columnName) {
if (getLeaderboard() != null) {
for (RaceInLeaderboardDTO race : getLeaderboard().getRaceList()) {
for (RaceColumnDTO race : getLeaderboard().getRaceList()) {
if (columnName.equals(race.getRaceColumnName())) {
return race;
}
@@ -1058,9 +1061,14 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private RaceColumn<?> getRaceColumnByRaceName(String raceName) {
for (int i=0; i<getLeaderboardTable().getColumnCount(); i++) {
Column<LeaderboardRowDTO, ?> column = getLeaderboardTable().getColumn(i);
if (column instanceof RaceColumn<?>
&& ((RaceColumn<?>) column).getRace().getRaceIdentifier().getRaceName().equals(raceName)) {
return (RaceColumn<?>) column;
if (column instanceof RaceColumn<?>) {
RaceColumnDTO raceInLeaderboard = ((RaceColumn<?>) column).getRace();
for (String fleetName : raceInLeaderboard.getFleetNames()) {
final RegattaAndRaceIdentifier raceIdentifier = raceInLeaderboard.getRaceIdentifier(fleetName);
if (raceIdentifier != null && raceIdentifier.getRaceName().equals(raceName)) {
return (RaceColumn<?>) column;
}
}
}
}
return null;
@@ -1283,12 +1291,12 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* adds on top of the existing {@link #getLeaderboard() leaderboard} are returned. Otherwise, the column list obtained as described before
* is filtered such that only columns pass whose race identifier equals {@link #preSelectedRace}.
*/
private List<RaceInLeaderboardDTO> getRaceColumnsToAddImplicitly(LeaderboardDTO leaderboard) {
List<RaceInLeaderboardDTO> columnsToAddImplicitly = getRacesAddedNew(getLeaderboard(), leaderboard);
private List<RaceColumnDTO> getRaceColumnsToAddImplicitly(LeaderboardDTO leaderboard) {
List<RaceColumnDTO> columnsToAddImplicitly = getRacesAddedNew(getLeaderboard(), leaderboard);
if (preSelectedRace != null) {
for (Iterator<RaceInLeaderboardDTO> i=columnsToAddImplicitly.iterator(); i.hasNext(); ) {
RaceInLeaderboardDTO next = i.next();
if (!preSelectedRace.equals(next.getRaceIdentifier())) {
for (Iterator<RaceColumnDTO> i=columnsToAddImplicitly.iterator(); i.hasNext(); ) {
RaceColumnDTO next = i.next();
if (!next.containsRace(preSelectedRace)) {
i.remove();
}
}
@@ -1344,9 +1352,9 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
}
private List<RaceInLeaderboardDTO> getRacesAddedNew(LeaderboardDTO oldLeaderboard, LeaderboardDTO newLeaderboard) {
List<RaceInLeaderboardDTO> result = new ArrayList<RaceInLeaderboardDTO>();
for (RaceInLeaderboardDTO s : newLeaderboard.getRaceList()) {
private List<RaceColumnDTO> getRacesAddedNew(LeaderboardDTO oldLeaderboard, LeaderboardDTO newLeaderboard) {
List<RaceColumnDTO> result = new ArrayList<RaceColumnDTO>();
for (RaceColumnDTO s : newLeaderboard.getRaceList()) {
if (oldLeaderboard == null || !leaderboardContainsColumnNamed(oldLeaderboard, s.getRaceColumnName())) {
result.add(s);
}
@@ -1355,7 +1363,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
private boolean leaderboardContainsColumnNamed(LeaderboardDTO leaderboard, String raceColumnName) {
for (RaceInLeaderboardDTO column : leaderboard.getRaceList()) {
for (RaceColumnDTO column : leaderboard.getRaceList()) {
if (column.getRaceColumnName().equals(raceColumnName)) {
return true;
}
@@ -1363,7 +1371,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
return false;
}
private boolean leaderboardTableContainsRace(RaceInLeaderboardDTO race) {
private boolean leaderboardTableContainsRace(RaceColumnDTO race) {
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
if (c instanceof RaceColumn) {
@@ -1384,9 +1392,9 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* the raceColumn to correct.
*/
private void correctColumnData(RaceColumn<?> raceColumn) {
RaceInLeaderboardDTO race = raceColumn.getRace();
RaceColumnDTO race = raceColumn.getRace();
int columnIndex = getRaceColumnPosition(raceColumn);
if (raceColumn.isExpansionEnabled() != race.isTrackedRace()
if (raceColumn.isExpansionEnabled() != race.hasTrackedRaces()
|| race.isMedalRace() != raceColumn.isMedalRace()) {
if (raceColumn.isExpanded()) {
raceColumn.toggleExpansion(); // remove children from table
@@ -1404,7 +1412,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* @param raceName
* The name of the racing column until the table should be cleared.
*/
private void removeRaceColumnFromRaceColumnStartIndexBeforeRace(int raceColumnStartIndex, RaceInLeaderboardDTO race) {
private void removeRaceColumnFromRaceColumnStartIndexBeforeRace(int raceColumnStartIndex, RaceColumnDTO race) {
int counter = 0;
for (int leaderboardposition = 0; leaderboardposition < getLeaderboardTable().getColumnCount(); leaderboardposition++) {
Column<LeaderboardRowDTO, ?> c = getLeaderboardTable().getColumn(leaderboardposition);
@@ -1451,7 +1459,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
* <code>listpos</code>th race in the table or -1 if no such race column was found, e.g., in case
* the column needs to be inserted as the last race in the table
*/
private int getColumnPositionToInsert(RaceInLeaderboardDTO race, int listpos) {
private int getColumnPositionToInsert(RaceColumnDTO race, int listpos) {
int raceColumnCounter = 0;
int noRaceColumnCounter = 0;
boolean raceColumnFound = false;
@@ -1479,9 +1487,9 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
/**
* Removes all Columns of type racecolumns of leaderboardTable
*/
private void removeRaceColumnsNotSelected(List<RaceInLeaderboardDTO> selectedRaceColumns) {
private void removeRaceColumnsNotSelected(List<RaceColumnDTO> selectedRaceColumns) {
Set<String> selectedRaceColumnNames = new HashSet<String>();
for (RaceInLeaderboardDTO selectedRaceColumn : selectedRaceColumns) {
for (RaceColumnDTO selectedRaceColumn : selectedRaceColumns) {
selectedRaceColumnNames.add(selectedRaceColumn.getRaceColumnName());
}
List<Column<LeaderboardRowDTO, ?>> columnsToRemove = new ArrayList<Column<LeaderboardRowDTO, ?>>();
@@ -1503,8 +1511,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
*/
private void createMissingAndAdjustExistingRaceColumns(LeaderboardDTO leaderboard) {
// Correct order of races in selectedRaceColum
List<RaceInLeaderboardDTO> correctedOrderSelectedRaces = new ArrayList<RaceInLeaderboardDTO>();
for (RaceInLeaderboardDTO raceInLeaderboard : leaderboard.getRaceList()) {
List<RaceColumnDTO> correctedOrderSelectedRaces = new ArrayList<RaceColumnDTO>();
for (RaceColumnDTO raceInLeaderboard : leaderboard.getRaceList()) {
if (selectedRaceColumns.contains(raceInLeaderboard)) {
correctedOrderSelectedRaces.add(raceInLeaderboard);
}
@@ -1512,7 +1520,7 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
selectedRaceColumns = correctedOrderSelectedRaces;
removeRaceColumnsNotSelected(selectedRaceColumns);
for (int selectedRaceCount = 0; selectedRaceCount < selectedRaceColumns.size(); selectedRaceCount++) {
RaceInLeaderboardDTO selectedRace = selectedRaceColumns.get(selectedRaceCount);
RaceColumnDTO selectedRace = selectedRaceColumns.get(selectedRaceCount);
if (leaderboardTableContainsRace(selectedRace)) {
// remove all raceColumns, starting at a specific selectedRaceCount, up to but excluding the selected raceName
// with the result that selectedRace is at position selectedRaceCount afterwards
@@ -1530,8 +1538,8 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
}
}
protected RaceColumn<?> createRaceColumn(RaceInLeaderboardDTO raceInLeaderboard) {
TextRaceColumn textRaceColumn = new TextRaceColumn(raceInLeaderboard, raceInLeaderboard.isTrackedRace(), RACE_COLUMN_HEADER_STYLE,
protected RaceColumn<?> createRaceColumn(RaceColumnDTO raceInLeaderboard) {
TextRaceColumn textRaceColumn = new TextRaceColumn(raceInLeaderboard, raceInLeaderboard.hasTrackedRaces(), RACE_COLUMN_HEADER_STYLE,
RACE_COLUMN_STYLE);
return textRaceColumn;
}
@@ -1693,9 +1701,11 @@ public class LeaderboardPanel extends FormPanel implements TimeListener, PlaySta
private List<RegattaAndRaceIdentifier> getTrackedRacesIdentifiers() {
List<RegattaAndRaceIdentifier> result = new ArrayList<RegattaAndRaceIdentifier>();
for (RaceInLeaderboardDTO raceColumn : getLeaderboard().getRaceList()) {
if (raceColumn.getRaceIdentifier() != null) {
result.add(raceColumn.getRaceIdentifier());
for (RaceColumnDTO raceColumn : getLeaderboard().getRaceList()) {
for (String fleetName : raceColumn.getFleetNames()) {
if (raceColumn.getRaceIdentifier(fleetName) != null) {
result.add(raceColumn.getRaceIdentifier(fleetName));
}
}
}
return result;
@@ -17,16 +17,16 @@ import com.sap.sailing.gwt.ui.client.DataEntryDialog;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.Validator;
import com.sap.sailing.gwt.ui.client.DetailTypeFormatter;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
public class LeaderboardSettingsDialogComponent implements SettingsDialogComponent<LeaderboardSettings> {
private final List<RaceInLeaderboardDTO> raceColumnSelection;
private final List<RaceInLeaderboardDTO> raceAllRaceColumns;
private final List<RaceColumnDTO> raceColumnSelection;
private final List<RaceColumnDTO> raceAllRaceColumns;
private final List<DetailType> maneuverDetailSelection;
private final List<DetailType> legDetailSelection;
private final List<DetailType> raceDetailSelection;
private final Map<RaceInLeaderboardDTO, CheckBox> raceColumnCheckboxes;
private final Map<RaceColumnDTO, CheckBox> raceColumnCheckboxes;
private final Map<DetailType, CheckBox> maneuverDetailCheckboxes;
private final Map<DetailType, CheckBox> legDetailCheckboxes;
private final Map<DetailType, CheckBox> raceDetailCheckboxes;
@@ -38,8 +38,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
private final long delayInMilliseconds;
public LeaderboardSettingsDialogComponent(List<DetailType> maneuverDetailSelection,
List<DetailType> legDetailSelection, List<DetailType> raceDetailSelection, List<RaceInLeaderboardDTO> raceAllRaceColumns,
List<RaceInLeaderboardDTO> raceColumnSelection, boolean autoExpandFirstRace, long delayBetweenAutoAdvancesInMilliseconds, long delayInMilliseconds,
List<DetailType> legDetailSelection, List<DetailType> raceDetailSelection, List<RaceColumnDTO> raceAllRaceColumns,
List<RaceColumnDTO> raceColumnSelection, boolean autoExpandFirstRace, long delayBetweenAutoAdvancesInMilliseconds, long delayInMilliseconds,
StringMessages stringConstants) {
this.maneuverDetailSelection = maneuverDetailSelection;
this.raceColumnSelection = raceColumnSelection;
@@ -47,7 +47,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
this.legDetailSelection = legDetailSelection;
this.raceDetailSelection = raceDetailSelection;
this.stringConstants = stringConstants;
raceColumnCheckboxes = new LinkedHashMap<RaceInLeaderboardDTO, CheckBox>();
raceColumnCheckboxes = new LinkedHashMap<RaceColumnDTO, CheckBox>();
maneuverDetailCheckboxes = new LinkedHashMap<DetailType, CheckBox>();
legDetailCheckboxes = new LinkedHashMap<DetailType, CheckBox>();
raceDetailCheckboxes = new LinkedHashMap<DetailType, CheckBox>();
@@ -102,8 +102,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
hp.add(vpLeft);
vpRight.add(new Label(stringConstants.selectedRaces()));
List<RaceInLeaderboardDTO> allColumns = raceAllRaceColumns;
for (RaceInLeaderboardDTO expandableSortableColumn : allColumns) {
List<RaceColumnDTO> allColumns = raceAllRaceColumns;
for (RaceColumnDTO expandableSortableColumn : allColumns) {
CheckBox checkbox = dialog.createCheckbox(expandableSortableColumn.getRaceColumnName());
checkbox.setValue(raceColumnSelection.contains(expandableSortableColumn));
raceColumnCheckboxes.put(expandableSortableColumn, checkbox);
@@ -134,7 +134,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone
}
}
List<String> namesOfRaceColumnsToShow = new ArrayList<String>();
for (Map.Entry<RaceInLeaderboardDTO, CheckBox> entry : raceColumnCheckboxes.entrySet()) {
for (Map.Entry<RaceColumnDTO, CheckBox> entry : raceColumnCheckboxes.entrySet()) {
if(entry.getValue().getValue()){
namesOfRaceColumnsToShow.add(entry.getKey().getRaceColumnName());
}
@@ -28,7 +28,7 @@ import com.sap.sailing.gwt.ui.client.UserAgentChecker.UserAgentTypes;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardPanel;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewModes;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.UserDTO;
@@ -101,11 +101,13 @@ public class TVViewPanel extends SimplePanel implements RaceTimesInfoProviderLis
private void updateRaceTimesInfoProvider() {
boolean providerChanged = false;
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
RaceIdentifier raceIdentifier = race.getRaceIdentifier();
if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) {
raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false);
providerChanged = true;
for (RaceColumnDTO race : leaderboard.getRaceList()) {
for (String fleetName : race.getFleetNames()) {
RaceIdentifier raceIdentifier = race.getRaceIdentifier(fleetName);
if (raceIdentifier != null && !raceTimesInfoProvider.containsRaceIdentifier(raceIdentifier)) {
raceTimesInfoProvider.addRaceIdentifier(raceIdentifier, false);
providerChanged = true;
}
}
}
if (providerChanged) {
@@ -127,7 +129,7 @@ public class TVViewPanel extends SimplePanel implements RaceTimesInfoProviderLis
if (leaderboard != null) {
//Resetting the settings of the leaderboard panel to prevent, that some race columns get lost
List<String> namesOfRaceColumnsToShow = new ArrayList<String>();
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
for (RaceColumnDTO race : leaderboard.getRaceList()) {
namesOfRaceColumnsToShow.add(race.getRaceColumnName());
}
LeaderboardSettings settings = LeaderboardSettingsFactory.getInstance().createNewDefaultSettings(
@@ -220,13 +222,16 @@ public class TVViewPanel extends SimplePanel implements RaceTimesInfoProviderLis
private RegattaAndRaceIdentifier getFirstStartedAndUnfinishedRace() {
RegattaAndRaceIdentifier firstStartedAndUnfinishedRace = null;
Map<RaceIdentifier, RaceTimesInfoDTO> raceTimesInfos = raceTimesInfoProvider.getRaceTimesInfos();
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier();
RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier);
if (raceIdentifier != null && raceTimes != null && raceTimes.startOfTracking != null
&& raceTimes.endOfRace == null) {
firstStartedAndUnfinishedRace = raceIdentifier;
break;
for (RaceColumnDTO race : leaderboard.getRaceList()) {
for (String fleetName : race.getFleetNames()) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier(fleetName);
if (raceIdentifier != null) {
RaceTimesInfoDTO raceTimes = raceTimesInfos.get(raceIdentifier);
if (raceTimes != null && raceTimes.startOfTracking != null && raceTimes.endOfRace == null) {
firstStartedAndUnfinishedRace = raceIdentifier;
break;
}
}
}
}
return firstStartedAndUnfinishedRace;
@@ -30,7 +30,7 @@ import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
/**
* An editable version of the {@link LeaderboardPanel} which allows a user to enter carried / accumulated
@@ -147,7 +147,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
private class EditableRaceColumn extends RaceColumn<LeaderboardRowDTO> implements RowUpdateWhiteboardOwner<LeaderboardRowDTO> {
private RowUpdateWhiteboard<LeaderboardRowDTO> currentRowUpdateWhiteboard;
public EditableRaceColumn(RaceInLeaderboardDTO race, List<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>> cellList) {
public EditableRaceColumn(RaceColumnDTO race, List<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>> cellList) {
super(race,
/* expandable */ false, // we don't want leg expansion when editing scores
new CompositeCellRememberingRenderingContextAndObject(cellList),
@@ -367,11 +367,11 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
}
@Override
protected RaceColumn<?> createRaceColumn(RaceInLeaderboardDTO race) {
protected RaceColumn<?> createRaceColumn(RaceColumnDTO race) {
return new EditableRaceColumn(race, getCellList(race));
}
private List<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>> getCellList(RaceInLeaderboardDTO race) {
private List<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>> getCellList(RaceColumnDTO race) {
List<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>> list =
new ArrayList<RowUpdateWhiteboardProducerThatAlsoHasCell<LeaderboardRowDTO, ?>>();
list.add(new MaxPointsDropDownCellProvider(race.getRaceColumnName()));
@@ -42,7 +42,6 @@ import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettingsFactory;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.UserDTO;
import com.sap.sailing.gwt.ui.shared.charts.AbstractChartPanel;
import com.sap.sailing.gwt.ui.shared.charts.MultiChartPanel;
import com.sap.sailing.gwt.ui.shared.charts.WindChart;
import com.sap.sailing.gwt.ui.shared.charts.WindChartSettings;
@@ -39,6 +39,7 @@ import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Course;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Leg;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.base.Regatta;
@@ -128,7 +129,7 @@ import com.sap.sailing.gwt.ui.shared.PlacemarkOrderDTO;
import com.sap.sailing.gwt.ui.shared.PositionDTO;
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
import com.sap.sailing.gwt.ui.shared.RaceDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
@@ -148,7 +149,7 @@ import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboardGroup;
import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown;
@@ -255,12 +256,17 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
result.name = leaderboard.getName();
result.competitorDisplayNames = new HashMap<CompetitorDTO, String>();
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
RegattaAndRaceIdentifier raceIdentifier = null;
if (raceColumn.getTrackedRace() != null) {
TrackedRace trackedRace = raceColumn.getTrackedRace();
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedEvent().getRegatta().getName(), trackedRace.getRace().getName());
result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace());
for (Fleet fleet : raceColumn.getFleets()) {
RegattaAndRaceIdentifier raceIdentifier = null;
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta()
.getName(), trackedRace.getRace().getName());
}
result.addRace(raceColumn.getName(), fleet.getName(), raceColumn.isMedalRace(),
raceIdentifier, /* StrippedRaceDTO */ null);
}
result.addRace(raceColumn.getName(), raceColumn.isMedalRace(), raceIdentifier, null);
}
result.rows = new HashMap<CompetitorDTO, LeaderboardRowDTO>();
result.hasCarriedPoints = leaderboard.hasCarriedPoints();
@@ -279,7 +285,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
@Override
public LeaderboardEntryDTO call() {
try {
return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(), competitor, timePoint,
return getLeaderboardEntryDTO(entry, raceColumn.getTrackedRace(competitor), competitor, timePoint,
namesOfRaceColumnsForWhichToLoadLegDetails != null
&& namesOfRaceColumnsForWhichToLoadLegDetails.contains(raceColumn.getName()));
} catch (NoWindException e) {
@@ -1144,7 +1150,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
@Override
public LeaderboardDTO createLeaderboard(String leaderboardName, int[] discardThresholds) {
return createStrippedLeaderboardDTO(getService().apply(new CreateLeaderboard(leaderboardName, discardThresholds)), false);
return createStrippedLeaderboardDTO(getService().apply(new CreateFlexibleLeaderboard(leaderboardName, discardThresholds)), false);
}
@Override
@@ -1181,11 +1187,15 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
for (Leaderboard leaderboard : leaderboards.values()) {
Iterable<RaceColumn> races = leaderboard.getRaceColumns();
for (RaceColumn raceInLeaderboard : races) {
TrackedRace trackedRace = raceInLeaderboard.getTrackedRace();
RaceDefinition trackedRaceDef = trackedRace != null ? trackedRace.getRace() : null;
if (trackedRaceDef != null && trackedRaceDef.getName().equals(race.name)) {
results.add(createStrippedLeaderboardDTO(leaderboard, false));
break;
for (Fleet fleet : raceInLeaderboard.getFleets()) {
TrackedRace trackedRace = raceInLeaderboard.getTrackedRace(fleet);
if (trackedRace != null) {
RaceDefinition trackedRaceDef = trackedRace.getRace();
if (trackedRaceDef.getName().equals(race.name)) {
results.add(createStrippedLeaderboardDTO(leaderboard, false));
break;
}
}
}
}
}
@@ -1194,49 +1204,54 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
/**
* Creates a {@link LeaderboardDTO} for <code>leaderboard</code> and fills in the name, race master data
* in the form of {@link RaceInLeaderboardDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints carried points}
* in the form of {@link RaceColumnDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints carried points}
* and the {@link LeaderboardDTO#discardThresholds discarding thresholds} for the leaderboard. No data about the points
* is filled into the result object. No data about the competitor display names is filled in; instead, an empty map
* is used for {@link LeaderboardDTO#competitorDisplayNames}.<br />
* If <code>withAdditionalData</code> is <code>true</code>, additional data (like location and race dates) will be loaded.
*/
private LeaderboardDTO createStrippedLeaderboardDTO(Leaderboard leaderboard, boolean withAdditionalData) {
LeaderboardDTO dto = new LeaderboardDTO();
dto.name = leaderboard.getName();
dto.competitorDisplayNames = new HashMap<CompetitorDTO, String>();
LeaderboardDTO leaderboardDTO = new LeaderboardDTO();
leaderboardDTO.name = leaderboard.getName();
leaderboardDTO.competitorDisplayNames = new HashMap<CompetitorDTO, String>();
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
RegattaAndRaceIdentifier raceIdentifier = null;
StrippedRaceDTO race = null;
if (raceColumn.getTrackedRace() != null) {
TrackedRace trackedRace = raceColumn.getTrackedRace();
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedEvent().getRegatta().getName(), trackedRace.getRace().getName());
if (withAdditionalData) {
//Getting the places of the race
Pair<Placemark, Placemark> startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace);
PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO();
if (startAndFinish.getA() != null) {
racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getA()));
for (Fleet fleet : raceColumn.getFleets()) {
if (raceColumn.getTrackedRace(fleet) != null) {
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta().getName(), trackedRace.getRace().getName());
if (withAdditionalData) {
// Getting the places of the race
PlacemarkOrderDTO racePlaces = getRacePlaces(trackedRace);
// Creating raceDTO and getting the dates
race = new StrippedRaceDTO(trackedRace.getRace().getName(), raceIdentifier, racePlaces);
race.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate();
race.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate();
race.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate();
}
if (startAndFinish.getB() != null) {
racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getB()));
}
if (racePlaces.isEmpty()) {
racePlaces = null;
}
//Creating raceDTO and getting the dates
race = new StrippedRaceDTO(trackedRace.getRace().getName(), raceIdentifier, racePlaces);
race.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate();
race.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace
.getStartOfTracking().asDate();
race.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate();
}
leaderboardDTO.addRace(raceColumn.getName(), fleet.getName(), raceColumn.isMedalRace(), raceIdentifier, race);
}
dto.addRace(raceColumn.getName(), raceColumn.isMedalRace(), raceIdentifier, race);
}
dto.hasCarriedPoints = leaderboard.hasCarriedPoints();
dto.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
return dto;
leaderboardDTO.hasCarriedPoints = leaderboard.hasCarriedPoints();
leaderboardDTO.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
return leaderboardDTO;
}
private PlacemarkOrderDTO getRacePlaces(TrackedRace trackedRace) {
Pair<Placemark, Placemark> startAndFinish = getStartFinishPlacemarksForTrackedRace(trackedRace);
PlacemarkOrderDTO racePlaces = new PlacemarkOrderDTO();
if (startAndFinish.getA() != null) {
racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getA()));
}
if (startAndFinish.getB() != null) {
racePlaces.getPlacemarks().add(convertToPlacemarkDTO(startAndFinish.getB()));
}
if (racePlaces.isEmpty()) {
racePlaces = null;
}
return racePlaces;
}
private Pair<Placemark, Placemark> getStartFinishPlacemarksForTrackedRace(TrackedRace race) {
@@ -1333,23 +1348,24 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, RaceIdentifier raceIdentifier) {
return getService().apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, raceIdentifier));
public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, RaceIdentifier raceIdentifier) {
return getService().apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, fleetName, raceIdentifier));
}
@Override
public Pair<String, String> getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName,
String raceColumnName) {
// TODO method needs to be changed such that the link between RaceColumn+Fleet and the TrackedRace becomes clear to the client
Pair<String, String> result = null;
public Map<String, RegattaAndRaceIdentifier> getEventAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName) {
Map<String, RegattaAndRaceIdentifier> result = new HashMap<String, RegattaAndRaceIdentifier>();
Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName);
if (leaderboard != null) {
RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName);
if (raceColumn != null) {
TrackedRace trackedRace = raceColumn.getTrackedRace();
if (trackedRace != null) {
result = new Pair<String, String>(trackedRace.getTrackedEvent().getRegatta().getName(),
trackedRace.getRace().getName());
for (Fleet fleet : raceColumn.getFleets()) {
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
if (trackedRace != null) {
result.put(fleet.getName(), trackedRace.getRaceIdentifier());
} else {
result.put(fleet.getName(), null);
}
}
}
}
@@ -1357,8 +1373,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
}
@Override
public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName) {
getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName));
public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) {
getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName));
}
@Override
@@ -10,6 +10,7 @@ import java.util.Map;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.impl.Util;
/**
* Captures the serializable properties of a leaderboard which in particular has the competitors, any optional display
@@ -22,7 +23,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
public class LeaderboardDTO implements IsSerializable {
public String name;
public List<CompetitorDTO> competitors;
private List<RaceInLeaderboardDTO> races;
private List<RaceColumnDTO> races;
public Map<CompetitorDTO, String> competitorDisplayNames;
public Map<CompetitorDTO, LeaderboardRowDTO> rows;
public boolean hasCarriedPoints;
@@ -35,7 +36,7 @@ public class LeaderboardDTO implements IsSerializable {
public LeaderboardDTO() {
totalRankingComparator = new TotalRankingComparator();
competitorsOrderedAccordingToTotalRank = false;
races = new ArrayList<RaceInLeaderboardDTO>();
races = new ArrayList<RaceColumnDTO>();
}
public String getDisplayName(CompetitorDTO competitor) {
@@ -74,7 +75,7 @@ public class LeaderboardDTO implements IsSerializable {
*/
public boolean scoredInMedalRace(CompetitorDTO competitor) {
LeaderboardRowDTO row = rows.get(competitor);
for (RaceInLeaderboardDTO race : races) {
for (RaceColumnDTO race : races) {
if (race.isMedalRace() && row.fieldsByRaceName.get(race.getRaceColumnName()).totalPoints > 0) {
return true;
}
@@ -191,7 +192,7 @@ public class LeaderboardDTO implements IsSerializable {
private int getMedalRaceScore(CompetitorDTO competitor) {
int result = 0;
LeaderboardRowDTO row = rows.get(competitor);
for (RaceInLeaderboardDTO race : races) {
for (RaceColumnDTO race : races) {
if (race.isMedalRace() && row.fieldsByRaceName.containsKey(race.getRaceColumnName())) {
result += row.fieldsByRaceName.get(race.getRaceColumnName()).netPoints;
}
@@ -217,7 +218,7 @@ public class LeaderboardDTO implements IsSerializable {
*/
private String getNameOfLastRaceSoFar(CompetitorDTO c1, CompetitorDTO c2) {
String nameOfLastRaceSoFar = null;
for (RaceInLeaderboardDTO race : races) {
for (RaceColumnDTO race : races) {
for (LeaderboardRowDTO row : rows.values()) {
if (row.competitor.equals(c1) || row.competitor.equals(c2)) {
LeaderboardEntryDTO leaderboardEntryDTO = row.fieldsByRaceName.get(race.getRaceColumnName());
@@ -235,7 +236,7 @@ public class LeaderboardDTO implements IsSerializable {
int result = 0;
LeaderboardRowDTO row = rows.get(competitor);
if (row != null) {
for (RaceInLeaderboardDTO race : races) {
for (RaceColumnDTO race : races) {
LeaderboardEntryDTO field = row.fieldsByRaceName.get(race.getRaceColumnName());
if (field != null && field.netPoints == 1) {
result++;
@@ -282,9 +283,13 @@ public class LeaderboardDTO implements IsSerializable {
}
public boolean raceIsTracked(String raceColumnName) {
for (RaceInLeaderboardDTO race : races) {
for (RaceColumnDTO race : races) {
if (race.getRaceColumnName().equals(raceColumnName)) {
return race.isTrackedRace();
for (String fleetName : race.getFleetNames()) {
if (race.isTrackedRace(fleetName)) {
return true;
}
}
}
}
return false;
@@ -295,34 +300,74 @@ public class LeaderboardDTO implements IsSerializable {
return getRaceInLeaderboardByName(raceColumnName).isMedalRace();
}
public void addRace(String raceColumnName, boolean medalRace, RegattaAndRaceIdentifier trackedRaceIdentifier, StrippedRaceDTO race) {
RaceInLeaderboardDTO raceInLeaderboardDTO = new RaceInLeaderboardDTO();
raceInLeaderboardDTO.setRaceColumnName(raceColumnName);
private RaceColumnDTO getOrCreateRaceColumn(String raceColumnName) {
RaceColumnDTO result = getRaceInLeaderboardByName(raceColumnName);
if (result == null) {
result = new RaceColumnDTO();
result.setRaceColumnName(raceColumnName);
races.add(result);
}
return result;
}
/**
* If the {@link RaceColumnDTO} by the name <code>raceColumnName</code> doesn't exist yet within this leaderboard
* DTO, it is created. This method ensures that a fleet named <code>fleetName</code> is present. If it's not present
* yet, it's added to the race column's fleet name list. The <code>trackedRaceIdentifier</code> and
* <code>race</code> are associated with the column for the fleet identified by <code>fleetName</code>.
*
* @param fleetName
* must not be null
*/
public void addRace(String raceColumnName, String fleetName, boolean medalRace, RegattaAndRaceIdentifier trackedRaceIdentifier, StrippedRaceDTO race) {
assert fleetName != null;
RaceColumnDTO raceInLeaderboardDTO = getOrCreateRaceColumn(raceColumnName);
if (!Util.contains(raceInLeaderboardDTO.getFleetNames(), fleetName)) {
raceInLeaderboardDTO.addFleetName(fleetName);
}
raceInLeaderboardDTO.setMedalRace(medalRace);
raceInLeaderboardDTO.setRaceIdentifier(trackedRaceIdentifier);
raceInLeaderboardDTO.setRace(race);
races.add(raceInLeaderboardDTO);
raceInLeaderboardDTO.setRaceIdentifier(fleetName, trackedRaceIdentifier);
raceInLeaderboardDTO.setRace(fleetName, race);
}
public void addRaceAt(String raceColumnName, boolean medalRace, RegattaAndRaceIdentifier trackedRaceIdentifier, int index) {
RaceInLeaderboardDTO raceInLeaderboardDTO = new RaceInLeaderboardDTO();
/**
* A new {@link RaceColumnDTO} by the name <code>raceColumnName</code> is created and added to this leaderboard at
* position <code>index</code>. The single fleet named <code>fleetName</code> is added to the column. The
* <code>trackedRaceIdentifier</code> and <code>race</code> are associated with the column for the fleet identified
* by <code>fleetName</code>.
*
* @param fleetName
* must not be null
*/
public void createRaceColumnAt(String raceColumnName, String fleetName, boolean medalRace,
RegattaAndRaceIdentifier trackedRaceIdentifier, int index) {
assert fleetName != null;
RaceColumnDTO raceInLeaderboardDTO = new RaceColumnDTO();
raceInLeaderboardDTO.setRaceColumnName(raceColumnName);
raceInLeaderboardDTO.setMedalRace(medalRace);
raceInLeaderboardDTO.setRaceIdentifier(trackedRaceIdentifier);
raceInLeaderboardDTO.addFleetName(fleetName);
raceInLeaderboardDTO.setRaceIdentifier(fleetName, trackedRaceIdentifier);
races.add(index, raceInLeaderboardDTO);
}
public void createEmptyRaceColumn(String raceColumnName, boolean medalRace) {
RaceColumnDTO raceInLeaderboardDTO = new RaceColumnDTO();
raceInLeaderboardDTO.setRaceColumnName(raceColumnName);
raceInLeaderboardDTO.setMedalRace(medalRace);
races.add(raceInLeaderboardDTO);
}
public void removeRace(String raceColumnName) {
races.remove(getRaceInLeaderboardByName(raceColumnName));
}
public void renameRace(String oldName, String newName) {
RaceInLeaderboardDTO race = getRaceInLeaderboardByName(oldName);
RaceColumnDTO race = getRaceInLeaderboardByName(oldName);
race.setRaceColumnName(newName);
}
private RaceInLeaderboardDTO getRaceInLeaderboardByName(String raceColumnName) {
for (RaceInLeaderboardDTO race : races) {
private RaceColumnDTO getRaceInLeaderboardByName(String raceColumnName) {
for (RaceColumnDTO race : races) {
if (race.getRaceColumnName().equals(raceColumnName)) {
return race;
}
@@ -330,7 +375,7 @@ public class LeaderboardDTO implements IsSerializable {
return null;
}
public List<RaceInLeaderboardDTO> getRaceList() {
public List<RaceColumnDTO> getRaceList() {
return races;
}
@@ -339,7 +384,7 @@ public class LeaderboardDTO implements IsSerializable {
}
public void moveRaceUp(String raceColumnName) {
RaceInLeaderboardDTO race = getRaceInLeaderboardByName(raceColumnName);
RaceColumnDTO race = getRaceInLeaderboardByName(raceColumnName);
int index = races.indexOf(race);
index--;
if (index >= 0) {
@@ -349,7 +394,7 @@ public class LeaderboardDTO implements IsSerializable {
}
public void moveRaceDown(String raceColumnName) {
RaceInLeaderboardDTO race = getRaceInLeaderboardByName(raceColumnName);
RaceColumnDTO race = getRaceInLeaderboardByName(raceColumnName);
int index = races.indexOf(race);
if (index != -1) {
index++;
@@ -369,13 +414,16 @@ public class LeaderboardDTO implements IsSerializable {
*/
public Date getStartDate() {
Date leaderboardStart = null;
for (RaceInLeaderboardDTO race : getRaceList()) {
Date raceStart = race.getStartDate();
if (raceStart != null) {
if (leaderboardStart == null) {
leaderboardStart = new Date();
for (RaceColumnDTO race : getRaceList()) {
for (String fleetName : race.getFleetNames()) {
Date raceStart = race.getStartDate(fleetName);
if (raceStart != null) {
if (leaderboardStart == null) {
leaderboardStart = new Date();
} else {
leaderboardStart = leaderboardStart.before(raceStart) ? leaderboardStart : raceStart;
}
}
leaderboardStart = leaderboardStart.before(raceStart) ? leaderboardStart : raceStart;
}
}
return leaderboardStart;
@@ -391,7 +439,7 @@ public class LeaderboardDTO implements IsSerializable {
*/
public PlacemarkOrderDTO getPlaces() {
PlacemarkOrderDTO leaderboardPlaces = null;
for (RaceInLeaderboardDTO race : getRaceList()) {
for (RaceColumnDTO race : getRaceList()) {
PlacemarkOrderDTO racePlaces = race.getPlaces();
if (racePlaces != null) {
if (leaderboardPlaces == null) {
@@ -407,7 +455,7 @@ public class LeaderboardDTO implements IsSerializable {
* @return <code>true</code> if the leaderboard contains a race which is live
*/
public boolean containsLiveRace() {
for (RaceInLeaderboardDTO race : getRaceList()) {
for (RaceColumnDTO race : getRaceList()) {
if (race.isLive()) {
return true;
}
@@ -6,6 +6,7 @@ import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
public class LeaderboardGroupDTO extends NamedDTO implements IsSerializable {
@@ -35,10 +36,13 @@ public class LeaderboardGroupDTO extends NamedDTO implements IsSerializable {
boolean containsRace = false;
leaderboardsLoop:
for (LeaderboardDTO leaderboard : leaderboards) {
for (RaceInLeaderboardDTO raceInLeaderboard : leaderboard.getRaceList()) {
if (raceInLeaderboard.getRaceIdentifier() != null && raceInLeaderboard.getRaceIdentifier().equals(race)) {
containsRace = true;
break leaderboardsLoop;
for (RaceColumnDTO raceInLeaderboard : leaderboard.getRaceList()) {
for (String fleetName : raceInLeaderboard.getFleetNames()) {
final RegattaAndRaceIdentifier raceIdentifierForFleet = raceInLeaderboard.getRaceIdentifier(fleetName);
if (raceIdentifierForFleet != null && raceIdentifierForFleet.equals(race)) {
containsRace = true;
break leaderboardsLoop;
}
}
}
}
@@ -135,5 +135,9 @@ public class PlacemarkOrderDTO extends NamedDTO implements IsSerializable {
}
return sb.toString();
}
public void add(PlacemarkOrderDTO places) {
placemarks.addAll(places.getPlacemarks());
}
}
@@ -0,0 +1,183 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
public class RaceColumnDTO implements IsSerializable {
private String raceColumnName;
private boolean medalRace;
private List<String> fleetNames;
private Map<String, RegattaAndRaceIdentifier> trackedRaceIdentifiersPerFleet;
private Map<String, StrippedRaceDTO> racesPerFleet;
public RaceColumnDTO() {
trackedRaceIdentifiersPerFleet = new HashMap<String, RegattaAndRaceIdentifier>();
racesPerFleet = new HashMap<String, StrippedRaceDTO>();
fleetNames = new ArrayList<String>();
}
public String getRaceColumnName() {
return raceColumnName;
}
public void setRaceColumnName(String raceColumnName) {
this.raceColumnName = raceColumnName;
}
public boolean isMedalRace() {
return medalRace;
}
public void setMedalRace(boolean medalRace) {
this.medalRace = medalRace;
}
public boolean isTrackedRace(String fleetName) {
return trackedRaceIdentifiersPerFleet.get(fleetName) != null;
}
public void setRaceIdentifier(String fleetName, RegattaAndRaceIdentifier raceIdentifier) {
this.trackedRaceIdentifiersPerFleet.put(fleetName, raceIdentifier);
}
/**
* @return a non-<code>null</code> race identifier if this column represents a <em>tracked</em> race. Such a race's
* data can be obtained from the server in great detail, as opposed to non-tracked races for which only
* result points may have been entered manually.
*/
public RegattaAndRaceIdentifier getRaceIdentifier(String fleetName) {
return trackedRaceIdentifiersPerFleet.get(fleetName);
}
/**
* Returns an object with data (e.g. start date or places) for the RaceInLeaderboardDTO. Is <code>null</code>, if
* the method {@link RaceColumnDTO#isTrackedRace(String)} returns <code>false</code>.
*
* @return An Object with additional data, or <code>null</code> if the race isn't tracked
*/
public StrippedRaceDTO getRace(String fleetName) {
return racesPerFleet.get(fleetName);
}
public void setRace(String fleetName, StrippedRaceDTO race) {
this.racesPerFleet.put(fleetName, race);
}
public Iterable<String> getFleetNames() {
return fleetNames;
}
/**
* @return The start of race, or the start of tracking if the start of race is <code>null</code>, or
* <code>null</code> if no start date is available.
*/
public Date getStartDate(String fleetName) {
Date start = null;
if (racesPerFleet.get(fleetName) != null) {
start = racesPerFleet.get(fleetName).getStartDate();
}
return start;
}
/**
* @return The {@link PlacemarkOrderDTO places} or <code>null</code>, if no places are available
*/
public PlacemarkOrderDTO getPlaces() {
PlacemarkOrderDTO places = null;
for (StrippedRaceDTO race : racesPerFleet.values()) {
if (places == null) {
places = race.places;
} else {
places.add(race.places);
}
}
return places;
}
/**
* @return <code>true</code> if the startOfTracking is after the current date and there's no end of the race
*/
public boolean isLive() {
for (String fleetName : getFleetNames()) {
final StrippedRaceDTO strippedRaceDTO = racesPerFleet.get(fleetName);
if (trackedRaceIdentifiersPerFleet.get(fleetName) != null
&& strippedRaceDTO != null
&& strippedRaceDTO.endOfRace == null
&& (strippedRaceDTO.startOfTracking != null ? new Date().after(strippedRaceDTO.startOfTracking) : false)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fleetNames == null) ? 0 : fleetNames.hashCode());
result = prime * result + (medalRace ? 1231 : 1237);
result = prime * result + ((raceColumnName == null) ? 0 : raceColumnName.hashCode());
result = prime * result + ((racesPerFleet == null) ? 0 : racesPerFleet.hashCode());
result = prime * result
+ ((trackedRaceIdentifiersPerFleet == null) ? 0 : trackedRaceIdentifiersPerFleet.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RaceColumnDTO other = (RaceColumnDTO) obj;
if (fleetNames == null) {
if (other.fleetNames != null)
return false;
} else if (!fleetNames.equals(other.fleetNames))
return false;
if (medalRace != other.medalRace)
return false;
if (raceColumnName == null) {
if (other.raceColumnName != null)
return false;
} else if (!raceColumnName.equals(other.raceColumnName))
return false;
if (racesPerFleet == null) {
if (other.racesPerFleet != null)
return false;
} else if (!racesPerFleet.equals(other.racesPerFleet))
return false;
if (trackedRaceIdentifiersPerFleet == null) {
if (other.trackedRaceIdentifiersPerFleet != null)
return false;
} else if (!trackedRaceIdentifiersPerFleet.equals(other.trackedRaceIdentifiersPerFleet))
return false;
return true;
}
public boolean containsRace(RaceIdentifier preSelectedRace) {
return trackedRaceIdentifiersPerFleet.values().contains(preSelectedRace);
}
public boolean hasTrackedRaces() {
Set<RegattaAndRaceIdentifier> raceIdentifiers = new HashSet<RegattaAndRaceIdentifier>(trackedRaceIdentifiersPerFleet.values());
raceIdentifiers.remove(null);
return !raceIdentifiers.isEmpty();
}
public void addFleetName(String fleetName) {
fleetNames.add(fleetName);
}
}
@@ -1,128 +0,0 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.Date;
import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
public class RaceInLeaderboardDTO implements IsSerializable {
private String raceColumnName;
private boolean medalRace;
private RegattaAndRaceIdentifier trackedRaceIdentifier;
private StrippedRaceDTO race;
public String getRaceColumnName() {
return raceColumnName;
}
public void setRaceColumnName(String raceColumnName) {
this.raceColumnName = raceColumnName;
}
public boolean isMedalRace() {
return medalRace;
}
public void setMedalRace(boolean medalRace) {
this.medalRace = medalRace;
}
public boolean isTrackedRace() {
return trackedRaceIdentifier != null;
}
public void setRaceIdentifier(RegattaAndRaceIdentifier raceIdentifier) {
this.trackedRaceIdentifier = raceIdentifier;
}
/**
* @return a non-<code>null</code> race identifier if this column represents a <em>tracked</em> race. Such a race's
* data can be obtained from the server in great detail, as opposed to non-tracked races for which only
* result points may have been entered manually.
*/
public RegattaAndRaceIdentifier getRaceIdentifier() {
return trackedRaceIdentifier;
}
/**
* Returns an object with data (e.g. start date or places) for the RaceInLeaderboardDTO. Is <code>null</code>, if
* the method {@link RaceInLeaderboardDTO#isTrackedRace()} returns <code>false</code>.
*
* @return An Object with additional data, or <code>null</code> if the race isn't tracked
*/
public StrippedRaceDTO getRace() {
return race;
}
public void setRace(StrippedRaceDTO race) {
this.race = race;
}
/**
* @return The start of race, or the start of tracking if the start of race is <code>null</code>, or
* <code>null</code> if no start date is available.
*/
public Date getStartDate() {
Date start = null;
if (race != null) {
start = race.getStartDate();
}
return start;
}
/**
* @return The {@link PlacemarkOrderDTO places} or <code>null</code>, if no places are available
*/
public PlacemarkOrderDTO getPlaces() {
PlacemarkOrderDTO places = null;
if (race != null) {
places = race.places;
}
return places;
}
/**
* @return <code>true</code> if the startOfTracking is after the current date and there's no end of the race
*/
public boolean isLive() {
if (trackedRaceIdentifier != null && race != null) {
return race.endOfRace == null && (race.startOfTracking != null ? new Date().after(race.startOfTracking) : false);
} else {
return false;
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (medalRace ? 1231 : 1237);
result = prime * result + ((raceColumnName == null) ? 0 : raceColumnName.hashCode());
result = prime * result + ((trackedRaceIdentifier == null) ? 0 : trackedRaceIdentifier.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RaceInLeaderboardDTO other = (RaceInLeaderboardDTO) obj;
if (medalRace != other.medalRace)
return false;
if (raceColumnName == null) {
if (other.raceColumnName != null)
return false;
} else if (!raceColumnName.equals(other.raceColumnName))
return false;
if (trackedRaceIdentifier == null) {
if (other.trackedRaceIdentifier != null)
return false;
} else if (!trackedRaceIdentifier.equals(other.trackedRaceIdentifier))
return false;
return true;
}
}
@@ -6,6 +6,9 @@ import java.util.List;
import com.google.gwt.user.client.rpc.IsSerializable;
public class RegattaDTO extends NamedDTO implements IsSerializable {
/**
* May be <code>null</code> in case the boat class is not known
*/
public BoatClassDTO boatClass;
public List<RaceDTO> races;
public List<CompetitorDTO> competitors;
@@ -1,54 +0,0 @@
package com.sap.sailing.gwt.ui.shared.panels;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.sap.sailing.gwt.ui.client.StringMessages;
public class ClosableWelcomeWidget extends SimpleWelcomeWidget {
private StringMessages stringConstants;
private boolean closable;
private Button closeButton;
/**
* Creates a new closable welcome widget. It has the same components as the {@link SimpleWelcomeWidget} and a Button
* at the top right corner to close the welcome widget (it sets the whole component visible = <code>false</code>).
*
* @param closable Sets the visibility of the close Button
* @param headerText The text of the header component
* @param welcomeText The text of the component under the header (welcome component)
*/
public ClosableWelcomeWidget(boolean closable, String headerText, String welcomeText, StringMessages stringConstants) {
super(headerText, welcomeText);
this.stringConstants = stringConstants;
this.closable = closable;
closeButton = new Button(this.stringConstants.close());
closeButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
ClosableWelcomeWidget.this.setVisible(false);
}
});
closeButton.setVisible(this.closable);
closeButton.setStyleName(STYLE_NAME_PREFIX + "CloseButton");
mainPanel.insert(closeButton, 0);
}
/**
* @return <code>true</code> if the welcome widget is closable (close button is visible) right now, else returns <code>false</code>
*/
public boolean isClosable() {
return closable;
}
/**
* Sets the visibility of the close button and consequently the ability of the welcome widget to close itself.
*/
public void setIsClosable(boolean isClosable) {
closable = isClosable;
closeButton.setVisible(closable);
}
}
@@ -35,6 +35,7 @@ import com.google.gwt.view.client.NoSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.AnchorCell;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
@@ -43,7 +44,7 @@ import com.sap.sailing.gwt.ui.client.URLFactory;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.PlacemarkOrderDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.components.CollapsablePanel;
/**
@@ -85,9 +86,9 @@ public class LeaderboardGroupOverviewPanel extends FormPanel {
private SingleSelectionModel<LeaderboardDTO> leaderboardsSelectionModel;
private FlowPanel leaderboardDetailsPanel;
private CellTable<RaceInLeaderboardDTO> racesTable;
private NoSelectionModel<RaceInLeaderboardDTO> racesSelectionModel;
private ListDataProvider<RaceInLeaderboardDTO> racesDataProvider;
private CellTable<RaceColumnDTO> racesTable;
private NoSelectionModel<RaceColumnDTO> racesSelectionModel;
private ListDataProvider<RaceColumnDTO> racesDataProvider;
private List<LeaderboardGroupDTO> availableGroups;
@@ -357,7 +358,7 @@ public class LeaderboardGroupOverviewPanel extends FormPanel {
public String getValue(LeaderboardDTO leaderboard) {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
for (RaceColumnDTO race : leaderboard.getRaceList()) {
if (!first) {
sb.append(", ");
}
@@ -410,47 +411,69 @@ public class LeaderboardGroupOverviewPanel extends FormPanel {
leaderboardDetailsLabel.getElement().getStyle().setPadding(5, Unit.PX);
leaderboardDetailsPanel.add(leaderboardDetailsLabel);
TextColumn<RaceInLeaderboardDTO> racesLocationColumn = new TextColumn<RaceInLeaderboardDTO>() {
TextColumn<RaceColumnDTO> racesLocationColumn = new TextColumn<RaceColumnDTO>() {
@Override
public String getValue(RaceInLeaderboardDTO race) {
public String getValue(RaceColumnDTO race) {
PlacemarkOrderDTO racePlaces = race.getPlaces();
return racePlaces == null ? LeaderboardGroupOverviewPanel.this.stringMessages.locationNotAvailable() : racePlaces.placemarksAsString();
}
};
AnchorCell racesNameAnchorCell = new AnchorCell();
Column<RaceInLeaderboardDTO, SafeHtml> racesNameColumn = new Column<RaceInLeaderboardDTO, SafeHtml>(racesNameAnchorCell) {
Column<RaceColumnDTO, SafeHtml> racesNameColumn = new Column<RaceColumnDTO, SafeHtml>(racesNameAnchorCell) {
@Override
public SafeHtml getValue(RaceInLeaderboardDTO race) {
public SafeHtml getValue(RaceColumnDTO race) {
SafeHtml name = null;
if (race.getRaceIdentifier() != null) {
LeaderboardGroupDTO selectedGroup = groupsSelectionModel.getSelectedObject();
LeaderboardDTO selectedLeaderboard = leaderboardsSelectionModel.getSelectedObject();
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier();
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + selectedLeaderboard.name + "&raceName=" + raceId.getRaceName()
+ "&regattaName=" + raceId.getRegattaName() + "&leaderboardGroupName=" + selectedGroup.name + "&root=overview"
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
name = ANCHORTEMPLATE.anchor(link, raceId.getRaceName());
} else {
name = new SafeHtmlBuilder().appendHtmlConstant(race.getRaceColumnName()).toSafeHtml();
Iterable<String> fleetNames = race.getFleetNames();
boolean singleFleet = Util.size(fleetNames) < 2;
for (String fleetName : fleetNames) {
String raceDisplayName;
if (singleFleet) {
raceDisplayName = race.getRaceColumnName();
} else {
raceDisplayName = race.getRaceColumnName() + "("+fleetName+")";
}
if (race.getRaceIdentifier(fleetName) != null) {
LeaderboardGroupDTO selectedGroup = groupsSelectionModel.getSelectedObject();
LeaderboardDTO selectedLeaderboard = leaderboardsSelectionModel.getSelectedObject();
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier(fleetName);
String debugParam = Window.Location.getParameter("gwt.codesvr");
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName="
+ selectedLeaderboard.name + "&raceName=" + raceId.getRaceName() + "&regattaName="
+ raceId.getRegattaName() + "&leaderboardGroupName=" + selectedGroup.name
+ "&root=overview"
+ (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : ""));
name = ANCHORTEMPLATE.anchor(link, raceDisplayName);
} else {
name = new SafeHtmlBuilder().appendHtmlConstant(raceDisplayName).toSafeHtml();
}
}
return name;
}
};
TextColumn<RaceInLeaderboardDTO> racesStartDateColumn = new TextColumn<RaceInLeaderboardDTO>() {
TextColumn<RaceColumnDTO> racesStartDateColumn = new TextColumn<RaceColumnDTO>() {
@Override
public String getValue(RaceInLeaderboardDTO race) {
Date raceStart = race.getStartDate();
return raceStart == null ? LeaderboardGroupOverviewPanel.this.stringMessages.untracked()
: DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).format(raceStart);
public String getValue(RaceColumnDTO race) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (String fleetName : race.getFleetNames()) {
Date raceStart = race.getStartDate(fleetName);
if (first) {
first = false;
} else {
result.append(", ");
}
result.append(raceStart == null ? LeaderboardGroupOverviewPanel.this.stringMessages.untracked()
: DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT).format(raceStart));
}
return result.toString();
}
};
racesTable = new CellTable<RaceInLeaderboardDTO>(200, tableResources);
racesTable = new CellTable<RaceColumnDTO>(200, tableResources);
racesTable.setWidth("100%");
racesSelectionModel = new NoSelectionModel<RaceInLeaderboardDTO>();
racesSelectionModel = new NoSelectionModel<RaceColumnDTO>();
racesTable.setSelectionModel(racesSelectionModel);
racesTable.addColumn(racesLocationColumn, this.stringMessages.location());
@@ -458,7 +481,7 @@ public class LeaderboardGroupOverviewPanel extends FormPanel {
racesTable.addColumn(racesStartDateColumn, this.stringMessages.startDate());
leaderboardDetailsPanel.add(racesTable);
racesDataProvider = new ListDataProvider<RaceInLeaderboardDTO>();
racesDataProvider = new ListDataProvider<RaceColumnDTO>();
racesDataProvider.addDataDisplay(racesTable);
return collapsableDetailsPanel;
@@ -20,6 +20,7 @@ import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.NoSelectionModel;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.AnchorCell;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
@@ -29,7 +30,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.client.URLFactory;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceInLeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.panels.BreadcrumbPanel;
import com.sap.sailing.gwt.ui.shared.panels.WelcomeWidget;
@@ -96,13 +97,13 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
}
private void buildGUI() {
//Create breadcrumb panel
// Create breadcrumb panel
BreadcrumbPanel breadcrumbPanel = createBreadcrumbPanel();
if (breadcrumbPanel != null) {
mainPanel.add(breadcrumbPanel);
}
//Create group details GUI
// Create group details GUI
FlowPanel groupDetailsPanel = new FlowPanel();
groupDetailsPanel.setStyleName(STYLE_NAME_PREFIX + "GroupDetailsPanel");
mainPanel.add(groupDetailsPanel);
@@ -111,12 +112,12 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
groupNameLabel.setStyleName(STYLE_NAME_PREFIX + "GroupName");
groupDetailsPanel.add(groupNameLabel);
//Using HTML to display the line breaks in the description
// Using HTML to display the line breaks in the description
HTML groupDescriptionLabel = new HTML(new SafeHtmlBuilder().appendEscapedLines(group.description).toSafeHtml());
groupDescriptionLabel.setStyleName(STYLE_NAME_PREFIX + "GroupDescription");
groupDetailsPanel.add(groupDescriptionLabel);
//Create group leaderboards GUI
// Create group leaderboards GUI
Label leaderboardsTableLabel = new Label(stringConstants.leaderboards());
leaderboardsTableLabel.setStyleName(STYLE_NAME_PREFIX + "LeaderboardsTableLabel");
mainPanel.add(leaderboardsTableLabel);
@@ -125,20 +126,20 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
LeaderboardGroupFullTableResources tableResources = GWT.create(LeaderboardGroupFullTableResources.class);
CellTable<Integer> leaderboardsTable = new CellTable<Integer>(200, tableResources);
leaderboardsTable.setSelectionModel(new NoSelectionModel<Integer>());
int maxRacesNum = 0;
for (final LeaderboardDTO leaderboard : group.leaderboards) {
SafeHtmlCell leaderboardCell = new SafeHtmlCell();
Column<Integer, SafeHtml> leaderboardColumn = new Column<Integer, SafeHtml>(leaderboardCell) {
@Override
public SafeHtml getValue(Integer raceNum) {
List<RaceInLeaderboardDTO> races = leaderboard.getRaceList();
List<RaceColumnDTO> races = leaderboard.getRaceList();
return raceNum < races.size() ? raceToRaceBoardLink(leaderboard, races.get(raceNum))
: SafeHtmlUtils.fromString("");
}
};
leaderboardsTable.addColumn(leaderboardColumn, leaderboard.name);
leaderboard.addRaceAt(stringConstants.overview(), false, null, 0);
// add an artificial RaceColumn for the "Overview" link at position 0
leaderboard.createRaceColumnAt(stringConstants.overview(), /* fleetName */ "", /* medal race */ false, /* tracked race identifier */ null, 0);
maxRacesNum = maxRacesNum < leaderboard.getRaceList().size() ? leaderboard
.getRaceList().size() : maxRacesNum;
}
@@ -174,19 +175,18 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
LeaderboardGroupCompactTableResources tableResources = GWT.create(LeaderboardGroupCompactTableResources.class);
CellTable<LeaderboardDTO> leaderboardsTable = new CellTable<LeaderboardDTO>(200, tableResources);
leaderboardsTable.setSelectionModel(new NoSelectionModel<LeaderboardDTO>());
leaderboardsTable.addColumn(nameColumn, stringConstants.name());
leaderboardsTable.addColumn(racesColumn, stringConstants.races());
leaderboardsTable.setRowData(group.leaderboards);
mainPanel.add(leaderboardsTable);
}
}
private SafeHtml raceToRaceBoardLink(LeaderboardDTO leaderboard, RaceInLeaderboardDTO race) {
private SafeHtml raceToRaceBoardLink(LeaderboardDTO leaderboard, RaceColumnDTO race) {
String debugParam = Window.Location.getParameter("gwt.codesvr");
SafeHtmlBuilder b = new SafeHtmlBuilder();
String displayName = race.getRaceColumnName();
String raceColumnDisplayName = race.getRaceColumnName();
// special handling for artificial RaceColumn for "Overview" button
if (race.getRaceColumnName().equals(stringConstants.overview())) {
String link = URLFactory.INSTANCE.encode("/gwt/Leaderboard.html?name=" + leaderboard.name
+ "&leaderboardGroupName=" + group.name + "&root=" + root);
@@ -194,19 +194,32 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, displayName, STYLE_NAME_PREFIX + "ActiveLeaderboard"));
b.append(ANCHORTEMPLATE.anchor(link, raceColumnDisplayName, STYLE_NAME_PREFIX + "ActiveLeaderboard"));
} else {
if (race.getRaceIdentifier() != null) {
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier();
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name + "&raceName=" + raceId.getRaceName()
+ "&regattaName=" + raceId.getRegattaName() + "&leaderboardGroupName=" + group.name + "&root=" + root);
if(debugParam != null && !debugParam.isEmpty())
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, displayName, STYLE_NAME_PREFIX + "ActiveRace"));
} else {
b.append(TEXTTEMPLATE.textWithClass(race.getRaceColumnName(), STYLE_NAME_PREFIX + "InactiveRace"));
final Iterable<String> fleetNames = race.getFleetNames();
boolean singleFleet = Util.size(fleetNames) < 2;
for (String fleetName : fleetNames) {
String linkText;
if (singleFleet) {
linkText = raceColumnDisplayName;
} else {
linkText = raceColumnDisplayName +" ("+fleetName+")";
}
if (race.getRaceIdentifier(fleetName) != null) {
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier(fleetName);
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name
+ "&raceName=" + raceId.getRaceName() + "&regattaName=" + raceId.getRegattaName()
+ "&leaderboardGroupName=" + group.name + "&root=" + root);
if (debugParam != null && !debugParam.isEmpty()) {
link += "&gwt.codesvr=" + debugParam;
}
if (viewMode != null && !viewMode.isEmpty()) {
link += "&viewMode=" + viewMode;
}
b.append(ANCHORTEMPLATE.anchor(link, linkText, STYLE_NAME_PREFIX + "ActiveRace"));
} else {
b.append(TEXTTEMPLATE.textWithClass(linkText, STYLE_NAME_PREFIX + "InactiveRace"));
}
}
}
return b.toSafeHtml();
@@ -215,19 +228,31 @@ public class LeaderboardGroupPanel extends FormPanel implements HasWelcomeWidget
private SafeHtml leaderboardRacesToHtml(LeaderboardDTO leaderboard) {
SafeHtmlBuilder b = new SafeHtmlBuilder();
String debugParam = Window.Location.getParameter("gwt.codesvr");
for (RaceInLeaderboardDTO race : leaderboard.getRaceList()) {
if (race.getRaceIdentifier() != null) {
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier();
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name
+ "&raceName=" + raceId.getRaceName() + "&root=" + root + raceId.getRaceName() + "&regattaName="
+ raceId.getRegattaName() + "&leaderboardGroupName=" + group.name);
if(debugParam != null && !debugParam.isEmpty())
link += "&gwt.codesvr=" + debugParam;
if(viewMode != null && !viewMode.isEmpty())
link += "&viewMode=" + viewMode;
b.append(ANCHORTEMPLATE.anchor(link, race.getRaceColumnName(), STYLE_NAME_PREFIX + "ActiveRace"));
} else {
b.append(TEXTTEMPLATE.textWithClass(race.getRaceColumnName(), STYLE_NAME_PREFIX + "InactiveRace"));
for (RaceColumnDTO race : leaderboard.getRaceList()) {
final Iterable<String> fleetNames = race.getFleetNames();
boolean singleFleet = Util.size(fleetNames) < 2;
for (String fleetName : fleetNames) {
String linkText;
if (singleFleet) {
linkText = race.getRaceColumnName();
} else {
linkText = race.getRaceColumnName() + " (" + fleetName + ")";
}
if (race.getRaceIdentifier(fleetName) != null) {
RegattaNameAndRaceName raceId = (RegattaNameAndRaceName) race.getRaceIdentifier(fleetName);
String link = URLFactory.INSTANCE.encode("/gwt/RaceBoard.html?leaderboardName=" + leaderboard.name
+ "&raceName=" + raceId.getRaceName() + "&root=" + root + raceId.getRaceName()
+ "&regattaName=" + raceId.getRegattaName() + "&leaderboardGroupName=" + group.name);
if (debugParam != null && !debugParam.isEmpty()) {
link += "&gwt.codesvr=" + debugParam;
}
if (viewMode != null && !viewMode.isEmpty()) {
link += "&viewMode=" + viewMode;
}
b.append(ANCHORTEMPLATE.anchor(link, linkText, STYLE_NAME_PREFIX + "ActiveRace"));
} else {
b.append(TEXTTEMPLATE.textWithClass(linkText, STYLE_NAME_PREFIX + "InactiveRace"));
}
}
}
return b.toSafeHtml();
@@ -62,14 +62,7 @@ public class SpectatorEntryPoint extends AbstractEntryPoint implements RegattaRe
} else {
LeaderboardGroupPanel groupPanel = new LeaderboardGroupPanel(sailingService, stringMessages, this, groupName, root, viewModeParamValue);
groupPanel.getElement().getStyle().setFloat(Style.Float.LEFT);
groupPanel.setWelcomeWidget(new SimpleWelcomeWidget( stringMessages.welcomeToSailingAnalytics(),
"Understanding what happens out on the race course isn't always easy. To help solve this challenge and" +
" bring the excitement of sailing to the fans, we have developed a leader board based on SAP analytics.\n" +
" Through analyzing GPS data together with integrated wind measurements from sensors out on the race course," +
" the leader board displays information such as in-race ranking, average speeds, distance travelled, ETA" +
" (estimated time of arrival at the next mark rounding), gaps to leader, gains and losses per leg.\n\n" +
"Check out the results for yourself to see who triumphed - and how they did it."));
groupPanel.setWelcomeWidget(new SimpleWelcomeWidget( stringMessages.welcomeToSailingAnalytics(), stringMessages.welcomeToSailingAnalyticsBody()));
SimplePanel feedbackPanel = new SimplePanel();
feedbackPanel.getElement().getStyle().setProperty("clear", "right");
feedbackPanel.addStyleName("feedbackPanel");
@@ -0,0 +1,50 @@
package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import com.sap.sailing.domain.base.CourseArea;
import com.sap.sailing.domain.base.Event;
import com.sap.sailing.domain.base.Venue;
import com.sap.sailing.domain.base.impl.CourseAreaImpl;
import com.sap.sailing.domain.base.impl.EventImpl;
import com.sap.sailing.domain.base.impl.VenueImpl;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
import com.sap.sailing.domain.persistence.MongoFactory;
import com.sap.sailing.domain.persistence.MongoObjectFactory;
import com.sap.sailing.mongodb.MongoDBService;
public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest {
@Test
public void testLoadStoreSimpleEvent() {
final String eventName = "Event Name";
final String venueName = "Venue Name";
final String[] courseAreaNames = new String[] { "Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrott" };
final Venue venue = new VenueImpl(venueName);
for (String courseAreaName : courseAreaNames) {
CourseArea courseArea = new CourseAreaImpl(courseAreaName);
venue.addCourseArea(courseArea);
}
MongoDBService service = MongoDBService.INSTANCE;
service.setConfiguration(getDBConfiguration());
MongoObjectFactory mof = MongoFactory.INSTANCE.getMongoObjectFactory(service);
Event event = new EventImpl(eventName, venue);
mof.storeEvent(event);
DomainObjectFactory dof = MongoFactory.INSTANCE.getDomainObjectFactory(service);
Event loadedEvent = dof.loadEvent(eventName);
assertNotNull(loadedEvent);
assertEquals(eventName, loadedEvent.getName());
final Venue loadedVenue = loadedEvent.getVenue();
assertNotNull(loadedVenue);
assertEquals(venueName, loadedVenue.getName());
assertEquals(courseAreaNames.length, Util.size(loadedVenue.getCourseAreas()));
int i=0;
for (CourseArea loadedCourseArea : loadedVenue.getCourseAreas()) {
assertEquals(courseAreaNames[i++], loadedCourseArea.getName());
}
}
}
@@ -6,13 +6,15 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.RaceIdentifier;
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
@@ -40,16 +42,16 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
final String groupDescription = "A leaderboard group";
final ArrayList<Leaderboard> leaderboards = new ArrayList<>();
Leaderboard leaderboard = new LeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(),
Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
leaderboard = new LeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(),
leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
leaderboard = new LeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(),
leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[2], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
leaderboard = new LeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(),
leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[3], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
@@ -77,10 +79,10 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
final String groupDescription = "A leaderboard group";
final ArrayList<Leaderboard> leaderboards = new ArrayList<>();
Leaderboard leaderboard = new LeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(),
Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
leaderboard = new LeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(),
leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
leaderboards.add(leaderboard);
@@ -90,11 +92,11 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
final String[] ungroupedLeaderboardNames = {"Ungrouped Leaderboard 0", "Ungrouped Leaderboard 1", "Ungrouped Leaderboard 2"};
final Leaderboard[] ungroupedLeaderboards = {
new LeaderboardImpl(ungroupedLeaderboardNames[0], new ScoreCorrectionImpl(),
new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)),
new LeaderboardImpl(ungroupedLeaderboardNames[1], new ScoreCorrectionImpl(),
new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[1], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)),
new LeaderboardImpl(ungroupedLeaderboardNames[2], new ScoreCorrectionImpl(),
new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[2], new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces)) };
mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]);
mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]);
@@ -131,8 +133,9 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
final String groupDescription = "A leaderboard group";
final ArrayList<Leaderboard> leaderboards = new ArrayList<>();
final Leaderboard leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
final RaceColumn race = leaderboard.addRaceColumn(columnName, false);
final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
final Fleet fleet = leaderboard.getFleet(null);
final RaceColumn race = leaderboard.addRaceColumn(columnName, false, fleet);
leaderboards.add(leaderboard);
final LeaderboardGroup group = new LeaderboardGroupImpl(groupName, groupDescription, leaderboards);
@@ -150,17 +153,21 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe
//RaceIdentifier change test
final String regattaName = "Event";
final String raceName = "Race";
leaderboard.getRaceColumnByName(columnName).setRaceIdentifier(new RegattaNameAndRaceName(regattaName, raceName));
leaderboard.getRaceColumnByName(columnName).setRaceIdentifier(fleet, new RegattaNameAndRaceName(regattaName, raceName));
mongoObjectFactory.storeLeaderboard(leaderboard);
//Check if the leaderboard updated correctly
final Leaderboard loadedLeaderboard = domainObjectFactory.loadLeaderboard(leaderboard.getName());
Assert.assertEquals(race.getRaceIdentifier(), loadedLeaderboard.getRaceColumnByName(columnName).getRaceIdentifier());
final RaceColumn loadedRaceColumnByName = loadedLeaderboard.getRaceColumnByName(columnName);
Fleet loadedFleet = loadedRaceColumnByName.getFleetByName(fleet.getName());
Assert.assertEquals(race.getRaceIdentifier(fleet), loadedRaceColumnByName.getRaceIdentifier(loadedFleet));
//Check if the group received the changes
// Check if the group received the changes
loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName);
RaceIdentifier loadedIdentifier = loadedGroup.getLeaderboards().iterator().next().getRaceColumnByName(columnName).getRaceIdentifier();
Assert.assertEquals(race.getRaceIdentifier(), loadedIdentifier);
final RaceColumn loadedRaceColumnFromGroupByName = loadedGroup.getLeaderboards().iterator().next().getRaceColumnByName(columnName);
Fleet loadedGroupFleet = loadedRaceColumnFromGroupByName.getFleetByName(fleet.getName());
RaceIdentifier loadedIdentifier = loadedRaceColumnFromGroupByName.getRaceIdentifier(loadedGroupFleet);
Assert.assertEquals(race.getRaceIdentifier(fleet), loadedIdentifier);
}
}
@@ -18,9 +18,10 @@ import com.sap.sailing.domain.base.impl.PersonImpl;
import com.sap.sailing.domain.base.impl.TeamImpl;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.persistence.impl.DomainObjectFactoryImpl;
@@ -33,7 +34,7 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
public void testStoreAndRetrieveSimpleLeaderboard() {
final String leaderboardName = "TestLeaderboard";
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
LeaderboardImpl leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
@@ -48,16 +49,16 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
final String raceColumnName = "My First Race";
final int carriedPointsForWolfgangHunger = 3;
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
LeaderboardImpl leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
Competitor competitor = createCompetitor();
TrackedRace raceWithOneCompetitor = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true);
leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false);
leaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace */ false, leaderboard.getFleet(null));
leaderboard.setCarriedPoints(competitor, carriedPointsForWolfgangHunger);
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
// attach tracked race to leaderboard to ensure that competitor object is assigned properly
loadedLeaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace, ignored */ false);
loadedLeaderboard.addRace(raceWithOneCompetitor, raceColumnName, /* medalRace, ignored */ false, leaderboard.getFleet(null));
assertEquals(leaderboardName, loadedLeaderboard.getName());
assertTrue(Arrays.equals(discardIndexResultsStartingWithHowManyRaces, loadedLeaderboard.getResultDiscardingRule()
.getDiscardIndexResultsStartingWithHowManyRaces()));
@@ -73,19 +74,19 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
final String raceColumnName2 = "My First Race 2";
final int correctedPoints = 2;
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
LeaderboardImpl leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
Competitor competitor = createCompetitor();
TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true);
TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false);
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null));
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true, leaderboard.getFleet(null));
leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints);
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
// attach tracked race to leaderboard to ensure that competitor object is assigned properly
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false);
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false);
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false, leaderboard.getFleet(null));
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null));
assertEquals(leaderboardName, loadedLeaderboard.getName());
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1));
assertEquals(correctedPoints, (int) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1));
@@ -99,19 +100,19 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
final String raceColumnName2 = "My First Race 2";
final MaxPointsReason maxPointsReason = MaxPointsReason.DNF;
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
LeaderboardImpl leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
Competitor competitor = createCompetitor();
TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true);
TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false);
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null));
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true, leaderboard.getFleet(null));
leaderboard.getScoreCorrection().setMaxPointsReason(competitor, leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason);
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
// attach tracked race to leaderboard to ensure that competitor object is assigned properly
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false);
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false);
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false, leaderboard.getFleet(null));
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null));
assertEquals(leaderboardName, loadedLeaderboard.getName());
assertFalse(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1));
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn2));
@@ -126,20 +127,20 @@ public class TestStoringAndRetrievingLeaderboards extends AbstractMongoDBTest {
final int correctedPoints = 2;
final MaxPointsReason maxPointsReason = MaxPointsReason.DNF;
final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 };
LeaderboardImpl leaderboard = new LeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
FlexibleLeaderboardImpl leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ScoreCorrectionImpl(),
new ResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces));
Competitor competitor = createCompetitor();
TrackedRace raceWithOneCompetitor1 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 1, /* started */ true);
TrackedRace raceWithOneCompetitor2 = new MockedTrackedRaceWithFixedRank(competitor, /* rank */ 2, /* started */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false);
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true);
leaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace */ false, leaderboard.getFleet(null));
leaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace */ true, leaderboard.getFleet(null));
leaderboard.getScoreCorrection().correctScore(competitor, leaderboard.getRaceColumnByName(raceColumnName1), correctedPoints);
leaderboard.getScoreCorrection().setMaxPointsReason(competitor, leaderboard.getRaceColumnByName(raceColumnName2), maxPointsReason);
new MongoObjectFactoryImpl(db).storeLeaderboard(leaderboard);
Leaderboard loadedLeaderboard = new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
FlexibleLeaderboard loadedLeaderboard = (FlexibleLeaderboard) new DomainObjectFactoryImpl(db).loadLeaderboard(leaderboardName);
// attach tracked race to leaderboard to ensure that competitor object is assigned properly
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false);
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false);
RaceColumn loadedColumn1 = loadedLeaderboard.addRace(raceWithOneCompetitor1, raceColumnName1, /* medalRace, ignored */ false, leaderboard.getFleet(null));
RaceColumn loadedColumn2 = loadedLeaderboard.addRace(raceWithOneCompetitor2, raceColumnName2, /* medalRace, ignored */ false, leaderboard.getFleet(null));
assertEquals(leaderboardName, loadedLeaderboard.getName());
assertTrue(loadedLeaderboard.getScoreCorrection().isScoreCorrected(competitor, loadedColumn1));
assertEquals(correctedPoints, (int) loadedLeaderboard.getScoreCorrection().getExplicitScoreCorrection(competitor, loadedColumn1));
@@ -26,7 +26,7 @@ import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.server.operationaltransformation.AddRegatta;
import com.sap.sailing.server.operationaltransformation.AddRaceDefinition;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard;
public class ServerReplicationTest extends AbstractServerReplicationTest {
@@ -45,7 +45,7 @@ public class ServerReplicationTest extends AbstractServerReplicationTest {
final String leaderboardName = "My new leaderboard";
assertNull(replica.getLeaderboardByName(leaderboardName));
final int[] discardThresholds = new int[] { 17, 23 };
CreateLeaderboard createTestLeaderboard = new CreateLeaderboard(leaderboardName, discardThresholds);
CreateFlexibleLeaderboard createTestLeaderboard = new CreateFlexibleLeaderboard(leaderboardName, discardThresholds);
assertNull(master.getLeaderboardByName(leaderboardName));
master.apply(createTestLeaderboard);
final Leaderboard masterLeaderboard = master.getLeaderboardByName(leaderboardName);
@@ -17,6 +17,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
import com.sap.sailing.domain.common.DefaultLeaderboardName;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
@@ -36,7 +37,7 @@ import com.sap.sailing.server.OperationExecutionListener;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateTrackedRace;
public class TrackRaceReplicationTest extends AbstractServerReplicationTest {
@@ -106,19 +107,20 @@ public class TrackRaceReplicationTest extends AbstractServerReplicationTest {
Leaderboard replicaDefaultLeaderboard = replica.getLeaderboardByName(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME);
RaceColumn column = replicaDefaultLeaderboard.getRaceColumnByName(replicaTrackedRace.getRace().getName());
assertNotNull(column);
assertSame(replicaTrackedRace, column.getTrackedRace());
assertSame(replicaTrackedRace, column.getTrackedRace(replicaDefaultLeaderboard.getFleet(null)));
}
@Test
public void testReassignmentToLeaderboardReplication() throws Exception {
final String leaderboardName = "Test Leaderboard";
master.apply(new CreateLeaderboard(leaderboardName, new int[0]));
Leaderboard masterLeaderboard = master.apply(new CreateFlexibleLeaderboard(leaderboardName, new int[0]));
final String columnName = "R1";
RaceColumn masterColumn = master.apply(new AddColumnToLeaderboard(columnName, leaderboardName, /* medalRace */ false));
master.apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, columnName, new RegattaNameAndRaceName(
"Academy Tracking 2011 (STG)", "weym470may122011")));
final Fleet defaultFleet = masterLeaderboard.getFleet(null);
master.apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, columnName, defaultFleet.getName(),
new RegattaNameAndRaceName("Academy Tracking 2011 (STG)", "weym470may122011")));
startTracking();
assertNotNull(masterColumn.getTrackedRace()); // ensure the re-assignment worked on the master
assertNotNull(masterColumn.getTrackedRace(defaultFleet)); // ensure the re-assignment worked on the master
Thread.sleep(1000);
TrackedRace replicaTrackedRace = replica.getTrackedRace(raceIdentifier);
assertNotNull(replicaTrackedRace);
@@ -129,7 +131,7 @@ public class TrackRaceReplicationTest extends AbstractServerReplicationTest {
assertNotNull(replicaLeaderboard);
RaceColumn column = replicaLeaderboard.getRaceColumnByName(columnName);
assertNotNull(column);
assertSame(replicaTrackedRace, column.getTrackedRace());
assertSame(replicaTrackedRace, column.getTrackedRace(defaultFleet));
}
@Test
@@ -25,7 +25,7 @@ public class LeaderboardDiscardingRulesTest {
@Test
public void testDiscardingRoules() {
racingEventService.removeLeaderboard(LEADERBOARDNAME);
racingEventService.addLeaderboard(LEADERBOARDNAME, new int[] { 1, 4 });
racingEventService.addFlexibleLeaderboard(LEADERBOARDNAME, new int[] { 1, 4 });
Leaderboard leaderboard = racingEventService.getLeaderboardByName(LEADERBOARDNAME);
assertNotNull(leaderboard);
int[] discardingRoulesNew = new int[] { 1, 5 };
@@ -20,7 +20,7 @@ import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
import com.sap.sailing.server.impl.RacingEventServiceImpl;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnUp;
import com.sap.sailing.server.operationaltransformation.OperationalTransformer;
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard;
@@ -49,7 +49,7 @@ public class OperationalTransformationTest {
@Test
public void testAddLeaderboard() {
RacingEventServiceOperation<Leaderboard> addLeaderboardOp = new CreateLeaderboard(LEADERBOARDNAME, new int[] { 5 });
RacingEventServiceOperation<Leaderboard> addLeaderboardOp = new CreateFlexibleLeaderboard(LEADERBOARDNAME, new int[] { 5 });
server.apply(addLeaderboardOp);
server.waitForNotRunning();
replica.waitForNotRunning();
@@ -91,17 +91,17 @@ public class RaceTrackerTest {
Set<RaceDefinition> races = raceHandle.getRaces();
assertNotNull(races);
assertFalse(races.isEmpty());
assertNotNull(getTrackedRace(raceHandle.getTrackedEvent()));
assertNotNull(getTrackedRace(raceHandle.getTrackedRegatta()));
}
@Test
public void testStopTracking() throws Exception {
TrackedRegatta oldTrackedEvent = raceHandle.getTrackedEvent();
TrackedRegatta oldTrackedEvent = raceHandle.getTrackedRegatta();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedEvent);
RaceDefinition oldRaceDefinition = oldTrackedRace.getRace();
service.removeEvent(raceHandle.getRegatta());
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
TrackedRegatta newTrackedEvent = myRaceHandle.getTrackedEvent();
TrackedRegatta newTrackedEvent = myRaceHandle.getTrackedRegatta();
assertNotSame(oldTrackedEvent, newTrackedEvent);
TrackedRace newTrackedRace = getTrackedRace(newTrackedEvent);
// expecting a new tracked race to be created when starting over with tracking
@@ -120,10 +120,10 @@ public class RaceTrackerTest {
*/
@Test
public void testTrackingSameRaceWithoutStopping() throws Exception {
TrackedRegatta oldTrackedRegatta = raceHandle.getTrackedEvent();
TrackedRegatta oldTrackedRegatta = raceHandle.getTrackedRegatta();
TrackedRace oldTrackedRace = getTrackedRace(oldTrackedRegatta);
RacesHandle myRaceHandle = service.addTracTracRace(paramUrl, liveUri, storedUri, EmptyWindStore.INSTANCE, /* timeoutInMilliseconds */ 60000);
TrackedRegatta newTrackedEvent = myRaceHandle.getTrackedEvent();
TrackedRegatta newTrackedEvent = myRaceHandle.getTrackedRegatta();
TrackedRace newTrackedRace = getTrackedRace(newTrackedEvent);
// expecting a new tracked race to be created when starting over with tracking
try {
@@ -25,6 +25,6 @@
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="yk-options" value="&#13;&#10;additional-options2=onexit\=snapshot&#13;&#10;"/>
</launchConfiguration>
@@ -25,6 +25,6 @@
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,com.tractrac.resultapi@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.osgi@default:default,com.googlecode.java-diff-utils@default:default,com.mongodb.driver@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.mongodb@default:default,com.sap.sailing.operationaltransformation@default:default,com.sap.sailing.server.replication@default:default,com.sap.sailing.server@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.www.events@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xcelsiusadapter@default:default,com.tractrac.clientmodule@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default"/>
<stringAttribute key="yk-options" value="&#13;&#10;additional-options2=onexit\=snapshot&#13;&#10;"/>
</launchConfiguration>
@@ -15,6 +15,7 @@ import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RaceDefinition;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
@@ -168,7 +169,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
*
* The <code>race</code> will be also removed from all leaderboards containing a column that has <code>race</code>'s
* {@link #getTrackedRace(Regatta, RaceDefinition) corresponding} {@link TrackedRace} as its
* {@link RaceColumn#getTrackedRace()}.
* {@link RaceColumn#getTrackedRace(Fleet)}.
*
* @param regatta
* the event to remove
@@ -230,7 +231,7 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch
*
* @return the leaderboard created
*/
Leaderboard addLeaderboard(String name, int[] discardThresholds);
Leaderboard addFlexibleLeaderboard(String name, int[] discardThresholds);
void removeLeaderboard(String leaderboardName);
@@ -5,7 +5,7 @@ import java.io.Serializable;
import com.sap.sailing.operationaltransformation.Operation;
import com.sap.sailing.operationaltransformation.Transformer;
import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateLeaderboard;
import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown;
import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnUp;
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard;
@@ -56,9 +56,9 @@ public interface RacingEventServiceOperation<ResultType> extends Operation<Racin
RacingEventServiceOperation<?> transformRenameLeaderboardColumnServerOp(RenameLeaderboardColumn renameLeaderboardColumnServerOp);
RacingEventServiceOperation<?> transformAddLeaderboardClientOp(CreateLeaderboard addLeaderboard);
RacingEventServiceOperation<?> transformAddLeaderboardClientOp(CreateFlexibleLeaderboard addLeaderboard);
RacingEventServiceOperation<?> transformAddLeaderboardServerOp(CreateLeaderboard addLeaderboard);
RacingEventServiceOperation<?> transformAddLeaderboardServerOp(CreateFlexibleLeaderboard addLeaderboard);
RacingEventServiceOperation<?> transformRemoveLeaderboardClientOp(RemoveLeaderboard removeLeaderboard);
@@ -29,6 +29,7 @@ import java.util.logging.Logger;
import com.sap.sailing.domain.base.Buoy;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.ControlPoint;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.RegattaListener;
import com.sap.sailing.domain.base.RaceDefinition;
@@ -44,11 +45,12 @@ import com.sap.sailing.domain.common.WindSource;
import com.sap.sailing.domain.common.impl.Util;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard;
import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.domain.leaderboard.RaceColumn;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl;
import com.sap.sailing.domain.leaderboard.impl.LeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl;
import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl;
import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl;
import com.sap.sailing.domain.persistence.DomainObjectFactory;
@@ -173,7 +175,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
courseListeners = new HashMap<RaceDefinition, CourseChangeReplicator>();
// Add one default leaderboard that aggregates all races currently tracked by this service.
// This is more for debugging purposes than for anything else.
addLeaderboard(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME, new int[] { 5, 8 });
addFlexibleLeaderboard(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME, new int[] { 5, 8 });
loadStoredLeaderboardsAndGroups();
}
@@ -196,8 +198,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
@Override
public Leaderboard addLeaderboard(String name, int[] discardThresholds) {
Leaderboard result = new LeaderboardImpl(name, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
public Leaderboard addFlexibleLeaderboard(String name, int[] discardThresholds) {
Leaderboard result = new FlexibleLeaderboardImpl(name, new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl(
discardThresholds));
synchronized (leaderboardsByName) {
if (leaderboardsByName.containsKey(name)) {
@@ -212,8 +214,9 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) {
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
if (leaderboard != null) {
RaceColumn result = leaderboard.addRaceColumn(columnName, medalRace);
if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) {
// uses the default fleet as the single fleet for the new column
RaceColumn result = ((FlexibleLeaderboard) leaderboard).addRaceColumn(columnName, medalRace, leaderboard.getFleet(null));
updateStoredLeaderboard(leaderboard);
return result;
} else {
@@ -224,8 +227,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public void moveLeaderboardColumnUp(String leaderboardName, String columnName) {
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
if (leaderboard != null) {
leaderboard.moveRaceColumnUp(columnName);
if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) {
((FlexibleLeaderboard) leaderboard).moveRaceColumnUp(columnName);
updateStoredLeaderboard(leaderboard);
} else {
throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found");
@@ -235,8 +238,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public void moveLeaderboardColumnDown(String leaderboardName, String columnName) {
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
if (leaderboard != null) {
leaderboard.moveRaceColumnDown(columnName);
if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) {
((FlexibleLeaderboard) leaderboard).moveRaceColumnDown(columnName);
updateStoredLeaderboard(leaderboard);
} else {
throw new IllegalArgumentException("Leaderboard named " + leaderboardName + " not found");
@@ -246,8 +249,8 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
@Override
public void removeLeaderboardColumn(String leaderboardName, String columnName) {
Leaderboard leaderboard = getLeaderboardByName(leaderboardName);
if (leaderboard != null) {
leaderboard.removeRaceColumn(columnName);
if (leaderboard != null && leaderboard instanceof FlexibleLeaderboard) {
((FlexibleLeaderboard) leaderboard).removeRaceColumn(columnName);
updateStoredLeaderboard(leaderboard);
} else {
throw new IllegalArgumentException("Leaderboard named "+leaderboardName+" not found");
@@ -599,8 +602,9 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
trackedRace.getMillisecondsOverWhichToAverageWind(), trackedRace.getMillisecondsOverWhichToAverageSpeed());
replicate(op);
linkRaceToConfiguredLeaderboardColumns(trackedRace);
leaderboardsByName.get(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME).addRace(trackedRace,
trackedRace.getRace().getName(), /* medalRace */false);
final FlexibleLeaderboard defaultLeaderboard = (FlexibleLeaderboard) leaderboardsByName.get(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME);
defaultLeaderboard.addRace(trackedRace,
trackedRace.getRace().getName(), /* medalRace */false, defaultLeaderboard.getFleet(null));
TrackedRaceReplicator trackedRaceReplicator = new TrackedRaceReplicator(trackedRace);
trackedRaceReplicators.put(trackedRace, trackedRaceReplicator);
trackedRace.addListener(trackedRaceReplicator);
@@ -668,18 +672,21 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
/**
* Based on the <code>trackedRace</code>'s {@link TrackedRace#getRaceIdentifier() race identifier}, the tracked race
* is (re-)associated to all {@link RaceColumn race columns} that currently have no
* {@link RaceColumn#getTrackedRace() tracked race assigned} and whose
* {@link RaceColumn#getRaceIdentifier() race identifier} equals that of <code>trackedRace</code>.
* {@link RaceColumn#getTrackedRace(Fleet) tracked race assigned} and whose
* {@link RaceColumn#getRaceIdentifier(Fleet) race identifier} equals that of <code>trackedRace</code>.
*/
private void linkRaceToConfiguredLeaderboardColumns(TrackedRace trackedRace) {
boolean leaderboardHasChanged = false;
RaceIdentifier trackedRaceIdentifier = trackedRace.getRaceIdentifier();
for (Leaderboard leaderboard : getLeaderboards().values()) {
for (RaceColumn column : leaderboard.getRaceColumns()) {
if (trackedRaceIdentifier.equals(column.getRaceIdentifier()) && column.getTrackedRace() == null) {
column.setTrackedRace(trackedRace);
leaderboardHasChanged = true;
replicate(new ConnectTrackedRaceToLeaderboardColumn(leaderboard.getName(), column.getName(), trackedRaceIdentifier));
for (Fleet fleet : column.getFleets()) {
if (trackedRaceIdentifier.equals(column.getRaceIdentifier(fleet)) && column.getTrackedRace(fleet) == null) {
column.setTrackedRace(fleet, trackedRace);
leaderboardHasChanged = true;
replicate(new ConnectTrackedRaceToLeaderboardColumn(leaderboard.getName(), column.getName(),
fleet.getName(), trackedRaceIdentifier));
}
}
}
if (leaderboardHasChanged) {
@@ -714,7 +721,7 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
for (RaceDefinition race : regatta.getAllRaces()) {
stopTrackingWind(regatta, race);
// remove from default leaderboard
Leaderboard defaultLeaderboard = getLeaderboardByName(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME);
FlexibleLeaderboard defaultLeaderboard = (FlexibleLeaderboard) getLeaderboardByName(DefaultLeaderboardName.DEFAULT_LEADERBOARD_NAME);
defaultLeaderboard.removeRaceColumn(race.getName());
}
}
@@ -807,9 +814,11 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
for (Leaderboard leaderboard : getLeaderboards().values()) {
boolean changed = false;
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
if (raceColumn.getTrackedRace() == trackedRace) {
raceColumn.releaseTrackedRace(); // but leave the RaceIdentifier on the race column untouched, e.g., for later re-load
changed = true;
for (Fleet fleet : raceColumn.getFleets()) {
if (raceColumn.getTrackedRace(fleet) == trackedRace) {
raceColumn.releaseTrackedRace(fleet); // but leave the RaceIdentifier on the race column
changed = true; // untouched, e.g., for later re-load
}
}
}
if (changed) {
@@ -48,12 +48,12 @@ public abstract class AbstractRacingEventServiceOperation<ResultType> implements
}
@Override
public RacingEventServiceOperation<?> transformAddLeaderboardClientOp(CreateLeaderboard addLeaderboard) {
public RacingEventServiceOperation<?> transformAddLeaderboardClientOp(CreateFlexibleLeaderboard addLeaderboard) {
return addLeaderboard;
}
@Override
public RacingEventServiceOperation<?> transformAddLeaderboardServerOp(CreateLeaderboard addLeaderboard) {
public RacingEventServiceOperation<?> transformAddLeaderboardServerOp(CreateFlexibleLeaderboard addLeaderboard) {
return addLeaderboard;
}
@@ -10,10 +10,12 @@ import com.sap.sailing.server.RacingEventServiceOperation;
public class ConnectTrackedRaceToLeaderboardColumn extends AbstractLeaderboardColumnOperation<Boolean> {
private static final long serialVersionUID = -1336511401516212508L;
private final RaceIdentifier raceToConnect;
private final String fleetName;
public ConnectTrackedRaceToLeaderboardColumn(String leaderboardName, String columnName, RaceIdentifier raceToConnect) {
public ConnectTrackedRaceToLeaderboardColumn(String leaderboardName, String columnName, String fleetName, RaceIdentifier raceToConnect) {
super(leaderboardName, columnName);
this.raceToConnect = raceToConnect;
this.fleetName = fleetName;
}
@Override
@@ -37,7 +39,9 @@ public class ConnectTrackedRaceToLeaderboardColumn extends AbstractLeaderboardCo
if (raceColumn != null) {
TrackedRace trackedRace = toState.getExistingTrackedRace(raceToConnect);
if (trackedRace != null) {
raceColumn.setTrackedRace(trackedRace);
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), trackedRace);
} else {
raceColumn.setRaceIdentifier(raceColumn.getFleetByName(fleetName), raceToConnect);
}
}
success = true;
@@ -4,18 +4,18 @@ import com.sap.sailing.domain.leaderboard.Leaderboard;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class CreateLeaderboard extends AbstractLeaderboardOperation<Leaderboard> {
public class CreateFlexibleLeaderboard extends AbstractLeaderboardOperation<Leaderboard> {
private static final long serialVersionUID = 891352705068098580L;
private final int[] discardThresholds;
public CreateLeaderboard(String leaderboardName, int[] discardThresholds) {
public CreateFlexibleLeaderboard(String leaderboardName, int[] discardThresholds) {
super(leaderboardName);
this.discardThresholds = discardThresholds;
}
@Override
public Leaderboard internalApplyTo(RacingEventService toState) {
return toState.addLeaderboard(getLeaderboardName(), discardThresholds);
return toState.addFlexibleLeaderboard(getLeaderboardName(), discardThresholds);
}
@Override
@@ -8,10 +8,11 @@ import com.sap.sailing.server.RacingEventServiceOperation;
public class DisconnectLeaderboardColumnFromTrackedRace extends AbstractLeaderboardColumnOperation<Void> {
private static final long serialVersionUID = -5822713961135743309L;
private final String fleetName;
public DisconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String columnName) {
public DisconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String columnName, String fleetName) {
super(leaderboardName, columnName);
// TODO Auto-generated constructor stub
this.fleetName = fleetName;
}
@Override
@@ -20,7 +21,7 @@ public class DisconnectLeaderboardColumnFromTrackedRace extends AbstractLeaderbo
if (leaderboard != null) {
RaceColumn raceColumn = leaderboard.getRaceColumnByName(getColumnName());
if (raceColumn != null) {
raceColumn.setTrackedRace(null);
raceColumn.setTrackedRace(raceColumn.getFleetByName(fleetName), null);
toState.updateStoredLeaderboard(leaderboard);
} else {
throw new IllegalArgumentException("Didn't find race "+getColumnName()+" in leaderboard "+getLeaderboardName());