removed isOrderedFleets() from Series; fleet ordering now by making Fleet extend Comparable<Fleet>

This commit is contained in:
Axel Uhl committed 2012-05-23 20:58:52 +02:00
1 parent da71b1cffe
commit 0fc25d3834
14 files changed
+98 -115

No files matched your search

@@ -450,13 +450,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private Series loadSeries(DBObject dbSeries) {
String name = (String) dbSeries.get(FieldNames.SERIES_NAME.name());
boolean isFleetsOrdered = (Boolean) dbSeries.get(FieldNames.SERIES_IS_FLEETS_ORDERED.name());
boolean isMedal = (Boolean) dbSeries.get(FieldNames.SERIES_IS_MEDAL.name());
final BasicDBList dbFleets = (BasicDBList) dbSeries.get(FieldNames.SERIES_FLEETS.name());
Map<String, Fleet> fleetsByName = loadFleets(dbFleets);
BasicDBList dbRaceColumns = (BasicDBList) dbSeries.get(FieldNames.SERIES_RACE_COLUMNS.name());
Iterable<String> raceColumnNames = loadRaceColumnNames(dbRaceColumns, fleetsByName);
Series series = new SeriesImpl(name, isFleetsOrdered, isMedal, fleetsByName.values(), raceColumnNames);
Series series = new SeriesImpl(name, isMedal, fleetsByName.values(), raceColumnNames);
loadRaceColumnRaceLinks(dbRaceColumns, series);
return series;
}
@@ -502,7 +501,13 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
private Fleet loadFleet(DBObject dbFleet) {
String name = (String) dbFleet.get(FieldNames.FLEET_NAME.name());
Fleet result = new FleetImpl(name);
Integer ordering = (Integer) dbFleet.get(FieldNames.FLEET_ORDERING.name());
Fleet result;
if (ordering != null) {
result = new FleetImpl(name, ordering);
} else {
result = new FleetImpl(name);
}
return result;
}
@@ -16,10 +16,10 @@ public enum FieldNames {
REGATTA_SERIES,
SERIES_NAME,
SERIES_IS_MEDAL,
SERIES_IS_FLEETS_ORDERED,
SERIES_FLEETS,
SERIES_RACE_COLUMNS,
FLEET_NAME,
FLEET_ORDERING,
RACE_NAME,
@@ -20,6 +20,7 @@ import com.sap.sailing.domain.base.Series;
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.base.impl.FleetImpl;
import com.sap.sailing.domain.common.Bearing;
import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.RaceIdentifier;
@@ -316,7 +317,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
private DBObject storeSeries(Series s) {
DBObject dbSeries = new BasicDBObject();
dbSeries.put(FieldNames.SERIES_NAME.name(), s.getName());
dbSeries.put(FieldNames.SERIES_IS_FLEETS_ORDERED.name(), s.isFleetsOrdered());
dbSeries.put(FieldNames.SERIES_IS_MEDAL.name(), s.isMedal());
BasicDBList dbFleets = new BasicDBList();
for (Fleet fleet : s.getFleets()) {
@@ -333,6 +333,9 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
private DBObject storeFleet(Fleet fleet) {
DBObject dbFleet = new BasicDBObject(FieldNames.FLEET_NAME.name(), fleet.getName());
if (fleet instanceof FleetImpl) {
dbFleet.put(FieldNames.FLEET_ORDERING.name(), ((FleetImpl) fleet).getOrdering());
}
return dbFleet;
}
@@ -3,13 +3,18 @@ package com.sap.sailing.domain.base;
import com.sap.sailing.domain.common.Named;
/**
* For each fleet in a {@link Series} there is one {@link RaceDefinition race} per "race column." Competitor to fleet assignment
* may vary per race in case of the fleets being unordered in their {@link Series}, or may be fixed in case the fleets are
* ordered in their {@link Series}, as usually the case in finals and medal series.
* For each fleet in a {@link Series} there is one {@link RaceDefinition race} per "race column." Competitor to fleet
* assignment may vary per race in case of the fleets being unordered in their {@link Series}, or may be fixed in case
* the fleets are ordered in their {@link Series}, as usually the case in finals and medal series.
* <p>
*
* Fleets within the same {@link Series} as well as all fleets within the same {@link RaceColumn#getFleets() RaceColumn}
* can be mutually compared to each other. Comparing fleets from different series produces undefined results. For a
* {@link Series}, either all distinct fleets compare different (a series with ordered fleets such as Gold, Silver), or
* all distinct fleets compare equal (e.g., for a qualifying series with fleets Yellow and Blue).
*
* @author Axel Uhl (D043530)
*
*
*/
public interface Fleet extends Named {
public interface Fleet extends Named, Comparable<Fleet> {
}
@@ -27,13 +27,6 @@ public interface Series extends Named {
RaceColumn getRaceColumnByName(String columnName);
/**
* Tells whether the fleets returned by {@link #getFleets()} have a relevant ordering. This is the case particularly
* for final series with fleets such as "Gold" and "Silver" but usually not for qualification series with fleets such
* as "Yellow" and "Blue" which don't have an ordering, particularly for ranking considerations.
*/
boolean isFleetsOrdered();
/**
* Tells whether this is the "last" / "medal" race series, usually having only one race. This may have implications
* on the scoring scheme (usually, medal races scores are doubled and cannot be discarded).
@@ -3,10 +3,39 @@ package com.sap.sailing.domain.base.impl;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.common.impl.NamedImpl;
/**
* The comparability is implemented by an integer field. For fleets of a series to compare equal, the constructor
* without this ordering criterion should be chosen (implicitly setting it to 0).
*
* @author Axel Uhl (D043530)
*
*/
public class FleetImpl extends NamedImpl implements Fleet {
private static final long serialVersionUID = 7560417723293278246L;
private final int ordering;
public FleetImpl(String name) {
super(name);
this(name, 0);
}
/**
* @param ordering
* a lesser value for <code>ordering</code> means "better"; for example, use 1 for the Gold fleet and 2
* for the Silver fleet.
*/
public FleetImpl(String name, int ordering) {
super(name);
this.ordering = ordering;
}
@Override
public int compareTo(Fleet o) {
return this.ordering - ((FleetImpl) o).ordering;
}
public int getOrdering() {
return ordering;
}
}
@@ -30,8 +30,8 @@ public class RegattaImpl extends NamedImpl implements Regatta {
* Constructs a regatta with a single default series with empty race column list, and a single default fleet.
*/
public RegattaImpl(String baseName, BoatClass boatClass) {
this(baseName, boatClass, Collections.singletonList(new SeriesImpl("Default", /* isFleetsOrdered */true,
/* isMedal */ false, Collections.singletonList(new FleetImpl("Default")), /* race column names */ new ArrayList<String>())));
this(baseName, boatClass, Collections.singletonList(new SeriesImpl("Default", /* isMedal */ false,
Collections.singletonList(new FleetImpl("Default")), /* race column names */ new ArrayList<String>())));
}
public RegattaImpl(String baseName, BoatClass boatClass, Iterable<? extends Series> series) {
@@ -12,14 +12,12 @@ import com.sap.sailing.domain.common.impl.NamedImpl;
public class SeriesImpl extends NamedImpl implements Series {
private static final long serialVersionUID = -1640404303144907381L;
private final boolean isFleetsOrdered;
private final Map<String, Fleet> fleetsByName;
private final Iterable<RaceColumnInSeriesImpl> raceColumns;
private boolean isMedal;
public SeriesImpl(String name, boolean isFleetsOrdered, boolean isMedal, Iterable<? extends Fleet> fleets, Iterable<String> raceColumnNames) {
public SeriesImpl(String name, boolean isMedal, Iterable<? extends Fleet> fleets, Iterable<String> raceColumnNames) {
super(name);
this.isFleetsOrdered = isFleetsOrdered;
this.fleetsByName = new HashMap<String, Fleet>();
for (Fleet fleet : fleets) {
this.fleetsByName.put(fleet.getName(), fleet);
@@ -33,10 +31,6 @@ public class SeriesImpl extends NamedImpl implements Series {
this.isMedal = isMedal;
}
public boolean isFleetsOrdered() {
return isFleetsOrdered;
}
public Iterable<? extends Fleet> getFleets() {
return fleetsByName.values();
}
@@ -137,7 +137,7 @@ public interface Leaderboard extends Named {
* <p>
*
* The sorting order considers this leaderboard's scoring scheme including the semantics of
* {@link Series#isFleetsOrdered() ordered fleets} and {@link RaceColumn#isMedalRace() medal races}. The ordering
* {@link Fleet#compareTo(Fleet) ordered fleets} and {@link RaceColumn#isMedalRace() medal races}. The ordering
* does not consider result discarding because when sorting for a race column it is of interest how the competitor
* performed in that race and not how the score affected the overall regatta score. Therefore, it is based on
* {@link #getNetPoints(Competitor, RaceColumn, TimePoint)} and not on
@@ -32,7 +32,9 @@ public interface ScoreCorrection extends Serializable {
* Note, though, that {@link MaxPointsReason#NONE} can also be the reason for an explicit score correction, e.g., if
* the tracking results were overruled by the jury. Clients may use
* {@link #isScoreCorrected(Competitor, TrackedRace)} to detect the difference.
* @param numberOfCompetitors TODO
*
* @param numberOfCompetitors
* the number of competitors to use as the basis for penalty score calculation ("max points")
*/
Result getCorrectedScore(int uncorrectedScore, Competitor competitor, RaceColumn raceColumn, TimePoint timePoint, int numberOfCompetitors);
@@ -322,16 +322,20 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard {
this.resultDiscardingRule = discardingRule;
}
protected List<Competitor> getCompetitorsFromBestToWorst(final RaceColumn raceColumn, TimePoint timePoint, final boolean isFleetsOrdered) throws NoWindException {
final Map<Competitor, Pair<Integer, Integer>> netPointsAndFleetIndex = new HashMap<Competitor, Pair<Integer, Integer>>();
/**
* All competitors with non-zero net points are added to the result which is then sorted by net points in ascending
* order. The fleet is the primary ordering criterion, followed by the net points.
*/
@Override
public List<Competitor> getCompetitorsFromBestToWorst(final RaceColumn raceColumn, TimePoint timePoint) throws NoWindException {
final Map<Competitor, Pair<Integer, Fleet>> netPointsAndFleet = new HashMap<Competitor, Pair<Integer, Fleet>>();
for (Competitor competitor : getCompetitors()) {
int netPoints = getNetPoints(competitor, raceColumn, timePoint);
if (netPoints != 0) {
netPointsAndFleetIndex.put(competitor, new Pair<Integer, Integer>(netPoints,
Util.indexOf(raceColumn.getFleets(), raceColumn.getFleetOfCompetitor(competitor))));
netPointsAndFleet.put(competitor, new Pair<Integer, Fleet>(netPoints, raceColumn.getFleetOfCompetitor(competitor)));
}
}
List<Competitor> result = new ArrayList<Competitor>(netPointsAndFleetIndex.keySet());
List<Competitor> result = new ArrayList<Competitor>(netPointsAndFleet.keySet());
Collections.sort(result, new Comparator<Competitor>() {
@Override
public int compare(Competitor o1, Competitor o2) {
@@ -339,12 +343,9 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard {
if (o1 == o2) {
comparisonResult = 0;
} else {
comparisonResult = 0;
if (isFleetsOrdered) {
comparisonResult = netPointsAndFleetIndex.get(o1).getB() - netPointsAndFleetIndex.get(o2).getB();
}
comparisonResult = netPointsAndFleet.get(o1).getB().compareTo(netPointsAndFleet.get(o2).getB());
if (comparisonResult == 0) {
comparisonResult = netPointsAndFleetIndex.get(o1).getA() - netPointsAndFleetIndex.get(o2).getA();
comparisonResult = netPointsAndFleet.get(o1).getA() - netPointsAndFleet.get(o2).getA();
}
}
return comparisonResult;
@@ -353,4 +354,21 @@ public abstract class AbstractLeaderboardImpl implements Leaderboard {
return result;
}
@Override
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) {
Map<Competitor, List<Integer>> scores;
for (RaceColumn raceColumn : getRaceColumns()) {
if (hasScoreCorrectionForAllUntrackedFleets(raceColumn)) {
// the column counts for sorting
}
}
return null;
}
private boolean hasScoreCorrectionForAllUntrackedFleets(RaceColumn raceColumn) {
// TODO Auto-generated method stub
return false;
}
}
@@ -180,12 +180,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements
@Override
public List<Competitor> getCompetitorsFromBestToWorst(RaceColumn raceColumn, TimePoint timePoint)
throws NoWindException {
return getCompetitorsFromBestToWorst(raceColumn, timePoint, /* isFleetsOrdered */ false);
return getCompetitorsFromBestToWorst(raceColumn, timePoint);
}
@Override
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) {
// TODO Auto-generated method stub
return null;
}
}
@@ -1,23 +1,14 @@
package com.sap.sailing.domain.leaderboard.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnInSeries;
import com.sap.sailing.domain.base.Regatta;
import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.impl.RaceColumnInSeriesImpl;
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.SettableScoreCorrection;
import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule;
@@ -61,55 +52,4 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl {
return (RaceColumnInSeriesImpl) super.getRaceColumnByName(columnName);
}
protected List<Competitor> getCompetitorsFromBestToWorst(final RaceColumn raceColumn, TimePoint timePoint, final boolean isFleetsOrdered) throws NoWindException {
final Map<Competitor, Pair<Integer, Integer>> netPointsAndFleetIndex = new HashMap<Competitor, Pair<Integer, Integer>>();
for (Competitor competitor : getCompetitors()) {
int netPoints = getNetPoints(competitor, raceColumn, timePoint);
if (netPoints != 0) {
netPointsAndFleetIndex.put(competitor, new Pair<Integer, Integer>(netPoints,
Util.indexOf(raceColumn.getFleets(), raceColumn.getFleetOfCompetitor(competitor))));
}
}
List<Competitor> result = new ArrayList<Competitor>(netPointsAndFleetIndex.keySet());
Collections.sort(result, new Comparator<Competitor>() {
@Override
public int compare(Competitor o1, Competitor o2) {
int comparisonResult;
if (o1 == o2) {
comparisonResult = 0;
} else {
comparisonResult = 0;
if (isFleetsOrdered) {
comparisonResult = netPointsAndFleetIndex.get(o1).getB() - netPointsAndFleetIndex.get(o2).getB();
}
if (comparisonResult == 0) {
comparisonResult = netPointsAndFleetIndex.get(o1).getA() - netPointsAndFleetIndex.get(o2).getA();
}
}
return comparisonResult;
}
});
return result;
}
/**
* If the column has {@link Series#isFleetsOrdered() unordered fleets}, all competitors with non-zero net points
* are added to the result which is then sorted by net points in ascending order. For ordered fleets, the fleet
* is the primary ordering criterion, followed by the net points.
*/
@Override
public List<Competitor> getCompetitorsFromBestToWorst(final RaceColumn raceColumn, TimePoint timePoint) throws NoWindException {
assert raceColumn instanceof RaceColumnInSeries;
final RaceColumnInSeries raceColumnInSeries = (RaceColumnInSeries) raceColumn;
return getCompetitorsFromBestToWorst(raceColumnInSeries, timePoint, raceColumnInSeries.getSeries().isFleetsOrdered());
}
@Override
public List<Competitor> getCompetitorsFromBestToWorst(TimePoint timePoint) {
// TODO how to count columns where only some but not all fleets have a tracked race? Probably check if there are score corrections for the untracked fleets?
// TODO Auto-generated method stub
return null;
}
}
@@ -1,7 +1,6 @@
package com.sap.sailing.mongodb.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
@@ -80,11 +79,11 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
assertEquals(regattaBaseName, loadedRegatta.getBaseName());
Iterator<? extends Series> seriesIter = loadedRegatta.getSeries().iterator();
Series loadedQualifyingSeries = seriesIter.next();
assertFalse(loadedQualifyingSeries.isFleetsOrdered());
assertEquals(numberOfQualifyingRaces, Util.size(loadedQualifyingSeries.getRaceColumns()));
assertEquals(0, loadedQualifyingSeries.getFleetByName("Yellow").compareTo(loadedQualifyingSeries.getFleetByName("Blue")));
Series loadedFinalSeries = seriesIter.next();
assertTrue(loadedFinalSeries.isFleetsOrdered());
assertEquals(numberOfFinalRaces, Util.size(loadedFinalSeries.getRaceColumns()));
assertTrue(loadedFinalSeries.getFleetByName("Silver").compareTo(loadedFinalSeries.getFleetByName("Gold")) > 0);
Series loadedMedalSeries = seriesIter.next();
assertEquals(1, Util.size(loadedMedalSeries.getRaceColumns()));
}
@@ -164,19 +163,19 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
for (int i=1; i<=numberOfQualifyingRaces; i++) {
qualifyingRaceColumnNames.add("Q"+i);
}
Series qualifyingSeries = new SeriesImpl("Qualifying", /* isFleetsOrdered */false, /* isMedal */false,
qualifyingFleets, qualifyingRaceColumnNames);
Series qualifyingSeries = new SeriesImpl("Qualifying", /* isMedal */false, qualifyingFleets,
qualifyingRaceColumnNames);
series.add(qualifyingSeries);
// -------- final series ------------
List<Fleet> finalFleets = new ArrayList<Fleet>();
finalFleets.add(new FleetImpl("Gold"));
finalFleets.add(new FleetImpl("Silver"));
finalFleets.add(new FleetImpl("Gold", 1));
finalFleets.add(new FleetImpl("Silver", 2));
List<String> finalRaceColumnNames = new ArrayList<String>();
for (int i=1; i<=numberOfFinalRaces; i++) {
finalRaceColumnNames.add("F"+i);
}
Series finalSeries = new SeriesImpl("Final", /* isFleetsOrdered */ true, /* isMedal */ false, finalFleets, finalRaceColumnNames);
Series finalSeries = new SeriesImpl("Final", /* isMedal */ false, finalFleets, finalRaceColumnNames);
series.add(finalSeries);
// ------------ medal --------------
@@ -184,7 +183,7 @@ public class TestStoringAndLoadingEventsAndRegattas extends AbstractMongoDBTest
medalFleets.add(new FleetImpl("Medal"));
List<String> medalRaceColumnNames = new ArrayList<String>();
medalRaceColumnNames.add("M");
Series medalSeries = new SeriesImpl("Medal", /* isFleetsOrdered */ true, /* isMedal */ true, medalFleets, medalRaceColumnNames);
Series medalSeries = new SeriesImpl("Medal", /* isMedal */ true, medalFleets, medalRaceColumnNames);
series.add(medalSeries);
Regatta regatta = new RegattaImpl(regattaBaseName, boatClass, series);