diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DelayedLeaderboardCorrectionsImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DelayedLeaderboardCorrectionsImpl.java index 15981e2a3f9..d445b359113 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DelayedLeaderboardCorrectionsImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DelayedLeaderboardCorrectionsImpl.java @@ -16,7 +16,7 @@ import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.leaderboard.DelayedLeaderboardCorrections; import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.tracking.TrackedRace; @@ -401,7 +401,7 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { } @Override diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index fe20a1b22bb..da3d9973d81 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -83,7 +83,7 @@ import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.persistence.DomainObjectFactory; @@ -238,7 +238,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } if (result == null) { SettableScoreCorrection scoreCorrection = new ScoreCorrectionImpl(); - ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard); + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbLeaderboard, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); String regattaName = (String) dbLeaderboard.get(FieldNames.REGATTA_NAME.name()); if (groupForMetaLeaderboard != null) { result = new LeaderboardGroupMetaLeaderboard(groupForMetaLeaderboard, loadScoringScheme(dbLeaderboard), resultDiscardingRule); @@ -314,17 +314,16 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } /** - * @param dbLeaderboard expects to find a field named {@link FieldNames#LEADERBOARD_DISCARDING_THRESHOLDS} + * @param dbObject expects to find a field identified by field which holds a {@link BasicDBList} */ - private ThresholdBasedResultDiscardingRule loadResultDiscardingRule(DBObject dbLeaderboard) { - BasicDBList dbDiscardIndexResultsStartingWithHowManyRaces = (BasicDBList) dbLeaderboard - .get(FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS.name()); + private ThresholdBasedResultDiscardingRule loadResultDiscardingRule(DBObject dbObject, FieldNames field) { + BasicDBList dbDiscardIndexResultsStartingWithHowManyRaces = (BasicDBList) dbObject.get(field.name()); int[] discardIndexResultsStartingWithHowManyRaces = new int[dbDiscardIndexResultsStartingWithHowManyRaces.size()]; int i = 0; for (Object discardingThresholdAsObject : dbDiscardIndexResultsStartingWithHowManyRaces) { discardIndexResultsStartingWithHowManyRaces[i++] = (Integer) discardingThresholdAsObject; } - ThresholdBasedResultDiscardingRule resultDiscardingRule = new ResultDiscardingRuleImpl( + ThresholdBasedResultDiscardingRule resultDiscardingRule = new ThresholdBasedResultDiscardingRuleImpl( discardIndexResultsStartingWithHowManyRaces); return resultDiscardingRule; } @@ -917,6 +916,10 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { fleetsByName.values(), raceColumnNames, trackedRegattaRegistry); + if (dbSeries.get(FieldNames.SERIES_DISCARDING_THRESHOLDS.name()) != null) { + ThresholdBasedResultDiscardingRule resultDiscardingRule = loadResultDiscardingRule(dbSeries, FieldNames.SERIES_DISCARDING_THRESHOLDS); + series.setResultDiscardingRule(resultDiscardingRule); + } loadRaceColumnRaceLinks(dbRaceColumns, series); return series; } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java index 02807f1736f..915625b5116 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/FieldNames.java @@ -22,6 +22,7 @@ public enum FieldNames { SERIES_IS_MEDAL, SERIES_FLEETS, SERIES_RACE_COLUMNS, + SERIES_DISCARDING_THRESHOLDS, FLEET_NAME, FLEET_ORDERING, FLEET_COLOR, diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index af0b4dc3707..95af524041c 100755 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -41,6 +41,7 @@ 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.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.persistence.MongoObjectFactory; @@ -237,8 +238,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { BasicDBObject dbScoreCorrections = new BasicDBObject(); storeScoreCorrections(leaderboard, dbScoreCorrections); dbLeaderboard.put(FieldNames.LEADERBOARD_SCORE_CORRECTIONS.name(), dbScoreCorrections); - final ThresholdBasedResultDiscardingRule resultDiscardingRule = leaderboard.getResultDiscardingRule(); - storeResultDiscardingRule(dbLeaderboard, resultDiscardingRule); + final ResultDiscardingRule resultDiscardingRule = leaderboard.getResultDiscardingRule(); + storeResultDiscardingRule(dbLeaderboard, resultDiscardingRule, FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS); BasicDBList competitorDisplayNames = new BasicDBList(); for (Competitor competitor : leaderboard.getCompetitors()) { String displayNameForCompetitor = leaderboard.getDisplayName(competitor); @@ -252,13 +253,20 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbLeaderboard.put(FieldNames.LEADERBOARD_COMPETITOR_DISPLAY_NAMES.name(), competitorDisplayNames); } - private void storeResultDiscardingRule(BasicDBObject dbLeaderboard, - final ThresholdBasedResultDiscardingRule resultDiscardingRule) { - BasicDBList dbResultDiscardingThresholds = new BasicDBList(); - for (int threshold : resultDiscardingRule.getDiscardIndexResultsStartingWithHowManyRaces()) { - dbResultDiscardingThresholds.add(threshold); + /** + * Stores the result discarding rule to dbObject's field identified by field if the result discarding + * rule is not null and is of type {@link ThresholdBasedResultDiscardingRule}. Otherwise, it is assumed that the + * result discarding rule is otherwise implicitly obtained, e.g., from a definition of a regatta with its series, stored elsewhere. + */ + private void storeResultDiscardingRule(DBObject dbObject, + final ResultDiscardingRule resultDiscardingRule, FieldNames field) { + if (resultDiscardingRule != null && resultDiscardingRule instanceof ThresholdBasedResultDiscardingRule) { + BasicDBList dbResultDiscardingThresholds = new BasicDBList(); + for (int threshold : ((ThresholdBasedResultDiscardingRule) resultDiscardingRule).getDiscardIndexResultsStartingWithHowManyRaces()) { + dbResultDiscardingThresholds.add(threshold); + } + dbObject.put(field.name(), dbResultDiscardingThresholds); } - dbLeaderboard.put(FieldNames.LEADERBOARD_DISCARDING_THRESHOLDS.name(), dbResultDiscardingThresholds); } private BasicDBObject storeRaceColumn(RaceColumn raceColumn) { @@ -478,6 +486,9 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbRaceColumns.add(storeRaceColumn(raceColumn)); } dbSeries.put(FieldNames.SERIES_RACE_COLUMNS.name(), dbRaceColumns); + if (s.getResultDiscardingRule() != null) { + storeResultDiscardingRule(dbSeries, s.getResultDiscardingRule(), FieldNames.SERIES_DISCARDING_THRESHOLDS); + } return dbSeries; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java index a5917d0586a..5613aa65226 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardForKielWeekTest.java @@ -21,7 +21,7 @@ import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.tracking.impl.WindImpl; import com.sap.sailing.domain.tractracadapter.ReceiverType; @@ -37,7 +37,7 @@ public class LeaderboardForKielWeekTest extends OnlineTracTracBasedTest { @Test public void leaderboardWithOneRaceTest() throws URISyntaxException, NoWindException, IOException, InterruptedException { leaderboard = new FlexibleLeaderboardImpl("Kiel Week 2011 505s", new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); + new ThresholdBasedResultDiscardingRuleImpl(new int[] { 3, 6 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); MillisecondsTimePoint now = MillisecondsTimePoint.now(); loadRace("357c700a-9d9a-11e0-85be-406186cbf87c"); // 505 Race 2 diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java index b2a12be2795..e8cc3d74568 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardOfflineTest.java @@ -37,7 +37,7 @@ import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.impl.FlexibleLeaderboardImpl; import com.sap.sailing.domain.leaderboard.impl.LowPoint; -import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRank; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithFixedRankAndManyCompetitors; @@ -100,7 +100,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void ensureMedalRaceParamIsIgnoredIfRaceColumnAlreadyExists() { - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( new int[] { 5, 8 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); final String columnName = "abc"; @@ -113,7 +113,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { @Test public void testRepeatedLeaderboardDTOCacheInvalidation() throws NoWindException, InterruptedException, ExecutionException { - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( new int[] { 5, 8 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); final String columnName = "abc"; @@ -169,7 +169,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { testRaces.add(r); // hash set should take care of more or less randomly permuting the races } ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( new int[] { 1 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; @@ -203,7 +203,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { testRace.addCompetitor(c2); testRace.addCompetitor(c3); // this makes maxPoints==4 ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); leaderboard.addRace(testRace, "R1", /* medalRace */ false, defaultFleet); @@ -232,7 +232,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { testRace.addCompetitor(c2); testRace.addCompetitor(c3); // this makes maxPoints==4 ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( new int[] { 2 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); RaceColumn r1 = leaderboard.addRace(testRace, "R1", /* medalRace */ false, defaultFleet); @@ -260,7 +260,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { testRaces.add(r); // hash set should take care of more or less randomly permuting the races } ScoreCorrectionImpl scoreCorrection = new ScoreCorrectionImpl(); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", scoreCorrection, new ThresholdBasedResultDiscardingRuleImpl( new int[] { 1 }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; @@ -287,7 +287,7 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest { protected void testLeaderboard(int numberOfStartedRaces, int numberOfNotStartedRaces, int firstDiscardingThreshold, int secondDiscardingThreshold, Integer carry, boolean addOneMedalRace, int numberOfUntrackedRaces) throws NoWindException { setupRaces(numberOfStartedRaces, numberOfNotStartedRaces); - FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ResultDiscardingRuleImpl( + FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl("Test Leaderboard", new ScoreCorrectionImpl(), new ThresholdBasedResultDiscardingRuleImpl( new int[] { firstDiscardingThreshold, secondDiscardingThreshold }), new LowPoint(), null); Fleet defaultFleet = leaderboard.getFleet(null); int i=0; diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java index bbf4f98a83f..2f3857080d1 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/LeaderboardScoringAndRankingTest.java @@ -45,7 +45,7 @@ import com.sap.sailing.domain.leaderboard.impl.HighPoint; import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall; import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.impl.RegattaLeaderboardImpl; -import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; import com.sap.sailing.domain.leaderboard.impl.ScoreCorrectionImpl; import com.sap.sailing.domain.leaderboard.meta.LeaderboardGroupMetaLeaderboard; import com.sap.sailing.domain.test.mock.MockedTrackedRaceWithStartTimeAndRanks; @@ -60,7 +60,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { private Leaderboard createLeaderboard(Regatta regatta, int[] discardingThresholds) { ScoreCorrectionImpl scoreCorrections = new ScoreCorrectionImpl(); - ResultDiscardingRuleImpl discardingRules = new ResultDiscardingRuleImpl(discardingThresholds); + ThresholdBasedResultDiscardingRuleImpl discardingRules = new ThresholdBasedResultDiscardingRuleImpl(discardingThresholds); return new RegattaLeaderboardImpl(regatta, scoreCorrections, discardingRules); } @@ -801,7 +801,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { TimePoint now = MillisecondsTimePoint.now(); TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000); FlexibleLeaderboard leaderboard1 = new FlexibleLeaderboardImpl("Leaderboard 1", new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); leaderboard1.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f1)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard1.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f2)), "R2", /* medalRace */ false, @@ -809,7 +809,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertTrue(leaderboard1.getScoringScheme().getScoreComparator(/* nullScoresAreBetter */ false).compare( leaderboard1.getTotalPoints(c[0], later), leaderboard1.getTotalPoints(c[3], later)) < 0); // c0 better than c3 FlexibleLeaderboard leaderboard2 = new FlexibleLeaderboardImpl("Leaderboard 3", new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); leaderboard2.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f3)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard2.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f4)), "R2", /* medalRace */ false, @@ -817,7 +817,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { assertTrue(leaderboard2.getScoringScheme().getScoreComparator(/* nullScoresAreBetter */ false).compare( leaderboard2.getTotalPoints(c[3], later), leaderboard2.getTotalPoints(c[0], later)) < 0); // c3 better than c0 FlexibleLeaderboard leaderboard3 = new FlexibleLeaderboardImpl("Leaderboard 3", new ScoreCorrectionImpl(), - new ResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); + new ThresholdBasedResultDiscardingRuleImpl(/* discarding thresholds */ new int[0]), new HighPoint(), null); leaderboard3.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f5)), "R1", /* medalRace */ false, leaderboard1.getFleet(null)); leaderboard3.addRace(new MockedTrackedRaceWithStartTimeAndRanks(now, Arrays.asList(f6)), "R2", /* medalRace */ false, @@ -827,7 +827,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest { LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl("Leaderboard Group", "Leaderboard Group", false, Arrays.asList(leaderboard1, leaderboard2, leaderboard3)); leaderboardGroup.setOverallLeaderboard(new LeaderboardGroupMetaLeaderboard(leaderboardGroup, new HighPointExtremeSailingSeriesOverall(), - new ResultDiscardingRuleImpl(new int[0]))); + new ThresholdBasedResultDiscardingRuleImpl(new int[0]))); leaderboardGroup.getOverallLeaderboard().setSuppressed(c[1], true); leaderboardGroup.getOverallLeaderboard().setSuppressed(c[2], true); List rankedCompetitors = leaderboardGroup.getOverallLeaderboard().getCompetitorsFromBestToWorst(later); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java index 38937b02c0a..d52445f78f3 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OfflineSerializationTest.java @@ -25,7 +25,7 @@ import com.sap.sailing.domain.base.impl.DomainFactoryImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.common.impl.Util.Pair; -import com.sap.sailing.domain.leaderboard.impl.ResultDiscardingRuleImpl; +import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl; public class OfflineSerializationTest extends AbstractSerializationTest { /** @@ -81,8 +81,8 @@ public class OfflineSerializationTest extends AbstractSerializationTest { @Test public void testSerializingResultDiscardingRuleImpl() throws ClassNotFoundException, IOException { DomainFactory receiverDomainFactory = new DomainFactoryImpl(); - ResultDiscardingRuleImpl rdri = new ResultDiscardingRuleImpl(new int[] { 5, 8 }); - ResultDiscardingRuleImpl clone = cloneBySerialization(rdri, receiverDomainFactory); + ThresholdBasedResultDiscardingRuleImpl rdri = new ThresholdBasedResultDiscardingRuleImpl(new int[] { 5, 8 }); + ThresholdBasedResultDiscardingRuleImpl clone = cloneBySerialization(rdri, receiverDomainFactory); assertTrue(Arrays.equals(rdri.getDiscardIndexResultsStartingWithHowManyRaces(), clone.getDiscardIndexResultsStartingWithHowManyRaces())); } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index 77fad2de45a..f664e869081 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -405,6 +405,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { public void setDefaultCourseArea(CourseArea newCourseArea) { // TODO Auto-generated method stub } + + @Override + public boolean definesSeriesDiscardThresholds() { + // TODO Auto-generated method stub + return false; + } }; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java index 3b5a5760c37..179ad2a790e 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/RaceColumnListener.java @@ -2,7 +2,7 @@ package com.sap.sailing.domain.base; import java.io.Serializable; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.tracking.TrackedRace; @@ -26,7 +26,7 @@ public interface RaceColumnListener extends Serializable { void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName); - void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, ThresholdBasedResultDiscardingRule newDiscardingRule); + void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule); void raceLogEventAdded(RaceColumn raceColumn, RaceLogIdentifier raceLogIdentifier, RaceLogEvent event); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java index 72923863dfe..c2db52b48ae 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Regatta.java @@ -93,4 +93,11 @@ public interface Regatta extends Named, WithID { void addRaceColumnListener(RaceColumnListener listener); void removeRaceColumnListener(RaceColumnListener listener); + + /** + * @return whether this regatta defines its local per-series result discarding rules; if so, any leaderboard based + * on the regatta has to respect this and has to use a result discarding rule implementation that + * keeps discards local to each series rather than spreading them across the entire leaderboard. + */ + boolean definesSeriesDiscardThresholds(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java index cb5305a094f..039faf76289 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java @@ -1,17 +1,23 @@ package com.sap.sailing.domain.base; +import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.domain.tracking.TrackedRegattaRegistry; /** - * A series is a part of a {@link Regatta}. Rounds are ordered within the regatta, and rules for who is assigned to + * A series is a part of a {@link Regatta}. Series are ordered within the regatta, and rules for who is assigned to * which series may exist on the regatta. For example, a regatta may have a qualification series, a final series, and a * medal "series" with usually only a single medal race. Each series has one or more fleets, deciding how many races per * race column have to be run in this round. For example, if the 49er regatta has so many competitors that they cannot - * all start in one race, the qualification round can be split into two {@link Fleet}s, "Yellow" and "Blue," each - * getting their separate races. Fleet assignment may or may not vary. This usually depends on the round's + * all start in one race, the qualification series can be split into two {@link Fleet}s, "Yellow" and "Blue," each + * getting their separate races. Fleet assignment may or may not vary. This usually depends on the series' * characteristics of having ordered or unordered fleets.

* + * A series may define its result discarding scheme. If it does, a regatta leaderboard for the containing regatta + * has to adhere to this and may not define its own cross-cutting result discarding scheme. If one or more series + * in the regatta choose to define their own result discarding scheme, discards are determined per series and not + * per leaderboard.

+ * * To receive notifications when {@link TrackedRace tracked races} are linked to or unlinked from any of this series' * columns, {@link RaceColumnListener}s can be added / removed. * @@ -42,6 +48,14 @@ public interface Series extends SeriesBase { void removeRaceColumn(String raceColumnName); + /** + * If not null, a containing regatta's leaderboard must obey this rule and in particular cannot define + * a "cross-cutting" result discarding rule where discards may be arbitrarily distributed across series. + */ + ThresholdBasedResultDiscardingRule getResultDiscardingRule(); + + void setResultDiscardingRule(ThresholdBasedResultDiscardingRule resultDiscardingRule); + Regatta getRegatta(); /** @@ -52,4 +66,11 @@ public interface Series extends SeriesBase { void addRaceColumnListener(RaceColumnListener listener); void removeRaceColumnListener(RaceColumnListener listener); + + /** + * @return whether this series defines its local result discarding rule; if so, any leaderboard based on the + * enclosing regatta has to respect this and has to use a result discarding rule implementation that keeps + * discards local to each series rather than spreading them across the entire leaderboard. + */ + boolean definesSeriesDiscardThresholds(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index c03cd4b8e3c..f166a7bd2c4 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -9,7 +9,6 @@ import java.util.HashSet; import java.util.Set; import java.util.logging.Logger; - import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CourseArea; @@ -24,8 +23,8 @@ import com.sap.sailing.domain.common.LeaderboardNameConstants; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.RegattaName; import com.sap.sailing.domain.common.impl.NamedImpl; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; @@ -302,8 +301,7 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { raceColumnListeners.notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); } @@ -342,4 +340,19 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene this.defaultCourseArea = newCourseArea; } + /** + * @return whether this regatta defines its local per-series result discarding rules; if so, any leaderboard based + * on the regatta has to respect this and has to use a result discarding rule implementation that + * keeps discards local to each series rather than spreading them across the entire leaderboard. + */ + @Override + public boolean definesSeriesDiscardThresholds() { + for (Series s : series) { + if (s.definesSeriesDiscardThresholds()) { + return true; + } + } + return false; + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java index eec7fe7c3c2..2dd9edf5531 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java @@ -16,6 +16,7 @@ import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.common.impl.NamedImpl; import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -32,6 +33,7 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener private boolean isMedal; private Regatta regatta; private final RaceColumnListeners raceColumnListeners; + private ThresholdBasedResultDiscardingRule resultDiscardingRule; /** * @param fleets @@ -245,8 +247,7 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { raceColumnListeners.notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); } @@ -259,4 +260,20 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener public boolean isTransient() { return false; } + + @Override + public ThresholdBasedResultDiscardingRule getResultDiscardingRule() { + return resultDiscardingRule; + } + + @Override + public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule resultDiscardingRule) { + this.resultDiscardingRule = resultDiscardingRule; + } + + @Override + public boolean definesSeriesDiscardThresholds() { + return getResultDiscardingRule() != null; + } + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java index e86364bbe2f..682769686e9 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/Leaderboard.java @@ -282,8 +282,6 @@ public interface Leaderboard extends Named { SettableScoreCorrection getScoreCorrection(); - ThresholdBasedResultDiscardingRule getResultDiscardingRule(); - Competitor getCompetitorByName(String competitorName); void setDisplayName(Competitor competitor, String displayName); @@ -314,7 +312,19 @@ public interface Leaderboard extends Named { */ boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint); - public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule); + /** + * Returns the result discarding rule for this leaderboard. This may be an explicit rule set for the entire leaderboard, + * or it may be an implicit rule that relies on other data such as a regatta's series-specific result discarding rules. + */ + ResultDiscardingRule getResultDiscardingRule(); + + /** + * Trying to set a cross-leaderboard result discarding rule may fail with an exception if the leaderboard obtains + * its result discarding rule in another way. For example, if the leaderboard is a {@link RegattaLeaderboard} and the + * regatta's series define their own result discarding rules, the regatta leaderboard will use a composite + * result discarding rule that considers all series-specific result discarding rules. + */ + public void setCrossLeaderboardResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule); Competitor getCompetitorByIdAsString(String idAsString); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index dccab7703f0..bac500eaee8 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -254,8 +254,7 @@ public class LeaderboardCacheManager { } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { removeFromCache(leaderboard); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java index 24793dc6424..3e58f451118 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractSimpleLeaderboardImpl.java @@ -61,6 +61,7 @@ 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.NumberOfCompetitorsInLeaderboardFetcher; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoreCorrection.Result; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; @@ -100,7 +101,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race private final SettableScoreCorrection scoreCorrection; - private ThresholdBasedResultDiscardingRule resultDiscardingRule; + private ThresholdBasedResultDiscardingRule crossLeaderboardResultDiscardingRule; /** * The optional display name mappings for competitors. This allows a user to override the tracking-provided @@ -330,7 +331,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race this.carriedPoints = new HashMap(); this.scoreCorrection = scoreCorrection; this.displayNames = new HashMap(); - this.resultDiscardingRule = resultDiscardingRule; + this.crossLeaderboardResultDiscardingRule = resultDiscardingRule; this.suppressedCompetitors = Collections.synchronizedSet(new HashSet()); this.raceColumnListeners = new RaceColumnListeners(); this.raceDetailsAtEndOfTrackingCache = new HashMap, RunnableFuture>(); @@ -383,8 +384,8 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } @Override - public ThresholdBasedResultDiscardingRule getResultDiscardingRule() { - return resultDiscardingRule; + public ResultDiscardingRule getResultDiscardingRule() { + return crossLeaderboardResultDiscardingRule; } @Override @@ -423,9 +424,9 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } @Override - public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) { - ThresholdBasedResultDiscardingRule oldDiscardingRule = getResultDiscardingRule(); - this.resultDiscardingRule = discardingRule; + public void setCrossLeaderboardResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule) { + ResultDiscardingRule oldDiscardingRule = getResultDiscardingRule(); + this.crossLeaderboardResultDiscardingRule = discardingRule; getRaceColumnListeners().notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, discardingRule); } @@ -735,8 +736,7 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { getRaceColumnListeners().notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); } @@ -1021,7 +1021,11 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race result.setDelayToLiveInMillisForLatestRace(this.getDelayToLiveInMillis()); result.rows = new HashMap(); result.hasCarriedPoints = this.hasCarriedPoints(); - result.discardThresholds = this.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces(); + if (this.getResultDiscardingRule() instanceof ThresholdBasedResultDiscardingRule) { + result.discardThresholds = ((ThresholdBasedResultDiscardingRule) this.getResultDiscardingRule()).getDiscardIndexResultsStartingWithHowManyRaces(); + } else { + result.discardThresholds = null; + } // Computing the competitor leg ranks is expensive, especially in live mode, in case new events keep invalidating // the ranks cache in TrackedLegImpl. Then problem then is that the sorting based on wind data is repeated for each // competitor, leading to square effort. We therefore need to compute the leg ranks for those race where leg details diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java new file mode 100755 index 00000000000..5b3c2522762 --- /dev/null +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/PerSeriesResultDiscardingRuleImpl.java @@ -0,0 +1,55 @@ +package com.sap.sailing.domain.leaderboard.impl; + +import java.util.HashSet; +import java.util.Set; + +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.common.TimePoint; +import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; + +/** + * A result discarding rule that is used when one or more of a {@link Regatta}'s {@link Series} define their own + * result discarding rule. In this case, discards are decided per series and not per regatta or leaderboard. + * + * @author Axel Uhl (d043530) + * + */ +public class PerSeriesResultDiscardingRuleImpl implements ResultDiscardingRule { + private static final long serialVersionUID = 4596442640424592181L; + + private final Regatta regatta; + + public PerSeriesResultDiscardingRuleImpl(Regatta regatta) { + super(); + this.regatta = regatta; + } + + @Override + public Set getDiscardedRaceColumns(Competitor competitor, Leaderboard leaderboard, + Iterable raceColumnsToConsider, TimePoint timePoint) { + Set result = new HashSet<>(); + for (Series s : regatta.getSeries()) { + if (s.getResultDiscardingRule() != null) { + Iterable columnsToConsiderInSeries = getColumnsToConsiderInSeries(s, raceColumnsToConsider); + result.addAll(s.getResultDiscardingRule().getDiscardedRaceColumns(competitor, leaderboard, columnsToConsiderInSeries, timePoint)); + } + } + return result; + } + + private Iterable getColumnsToConsiderInSeries(Series series, Iterable allRaceColumnsToConsider) { + Set result = new HashSet<>(); + for (RaceColumn seriesColumn : series.getRaceColumns()) { + if (Util.contains(allRaceColumnsToConsider, seriesColumn)) { + result.add(seriesColumn); + } + } + return result; + } + +} diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index 8e3725f45ea..02439785dd1 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -12,6 +12,7 @@ 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.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.leaderboard.ScoringScheme; import com.sap.sailing.domain.leaderboard.SettableScoreCorrection; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; @@ -81,4 +82,21 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R return regatta.getDefaultCourseArea(); } + /** + * If the regatta' series {@link Regatta#definesSeriesDiscardThresholds() define} their own result discarding rules, this leaderboard uses + * a composite result discarding rule of type {@link PerSeriesResultDiscardingRuleImpl} that contains discards within each series according + * to the series' discarding rules. Otherwise, the default cross-leaderboard result discarding rule is obtained from the super class + * implementation. + */ + @Override + public ResultDiscardingRule getResultDiscardingRule() { + if (regatta.definesSeriesDiscardThresholds()) { + return new PerSeriesResultDiscardingRuleImpl(regatta); + } else { + return super.getResultDiscardingRule(); + } + } + + + } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ResultDiscardingRuleImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java similarity index 94% rename from java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ResultDiscardingRuleImpl.java rename to java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java index 71947814eef..68b0c137171 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ResultDiscardingRuleImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/ThresholdBasedResultDiscardingRuleImpl.java @@ -30,11 +30,11 @@ import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; * @author Axel Uhl (d043530) * */ -public class ResultDiscardingRuleImpl implements ThresholdBasedResultDiscardingRule { +public class ThresholdBasedResultDiscardingRuleImpl implements ThresholdBasedResultDiscardingRule { private static final long serialVersionUID = 386341628517357988L; private final int[] discardIndexResultsStartingWithHowManyRaces; - public ResultDiscardingRuleImpl(int[] discardIndexResultsStartingWithHowManyRaces) { + public ThresholdBasedResultDiscardingRuleImpl(int[] discardIndexResultsStartingWithHowManyRaces) { super(); this.discardIndexResultsStartingWithHowManyRaces = new int[discardIndexResultsStartingWithHowManyRaces.length]; System.arraycopy(discardIndexResultsStartingWithHowManyRaces, 0, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 379c7482274..1318168f910 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -9,7 +9,7 @@ import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.impl.SimpleAbstractRaceColumn; import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.leaderboard.Leaderboard; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLog; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; @@ -152,8 +152,7 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R } @Override - public void resultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void resultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, ResultDiscardingRule newDiscardingRule) { getRaceColumnListeners().notifyListenersAboutResultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java index e1d8137e277..ffb08c1d681 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/util/impl/RaceColumnListeners.java @@ -11,7 +11,7 @@ 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.RaceColumnListener; -import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; +import com.sap.sailing.domain.leaderboard.ResultDiscardingRule; import com.sap.sailing.domain.racelog.RaceLogEvent; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.tracking.TrackedRace; @@ -126,8 +126,8 @@ public class RaceColumnListeners implements Serializable { } } - public void notifyListenersAboutResultDiscardingRuleChanged(ThresholdBasedResultDiscardingRule oldDiscardingRule, - ThresholdBasedResultDiscardingRule newDiscardingRule) { + public void notifyListenersAboutResultDiscardingRuleChanged(ResultDiscardingRule oldDiscardingRule, + ResultDiscardingRule newDiscardingRule) { for (RaceColumnListener listener : getRaceColumnListeners()) { listener.resultDiscardingRuleChanged(oldDiscardingRule, newDiscardingRule); } diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java index 0297d62bc68..3c2bfb860a5 100644 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java @@ -406,6 +406,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { // TODO Auto-generated method stub } + + @Override + public boolean definesSeriesDiscardThresholds() { + // TODO Auto-generated method stub + return false; + } }; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java index 58550481ecd..401a98dc781 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java @@ -1,10 +1,6 @@ package com.sap.sailing.gwt.ui.adminconsole; -import java.util.ArrayList; -import java.util.List; - import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.LongBox; import com.google.gwt.user.client.ui.TextBox; import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.gwt.ui.client.DataEntryDialog; @@ -17,73 +13,30 @@ public abstract class AbstractLeaderboardDialog extends DataEntryDialog validator, DialogCallback callback) { - super(title, null, stringConstants.ok(), stringConstants.cancel(), validator, callback); - this.stringMessages = stringConstants; + super(title, null, stringMessages.ok(), stringMessages.cancel(), validator, callback); + this.stringMessages = stringMessages; this.leaderboardDescriptor = leaderboardDescriptor; } @Override protected LeaderboardDescriptor getResult() { - int[] discardThresholdsBoxContents = getDiscardThresholds(discardThresholdBoxes); leaderboardDescriptor.setName(nameTextBox.getValue()); leaderboardDescriptor.setDisplayName(displayNameTextBox.getValue().trim().isEmpty() ? null : displayNameTextBox.getValue()); - leaderboardDescriptor.setDiscardThresholds(discardThresholdsBoxContents); + leaderboardDescriptor.setDiscardThresholds(discardThresholdBoxes==null?null:discardThresholdBoxes.getDiscardThresholds()); return leaderboardDescriptor; } - protected static int[] getDiscardThresholds(LongBox[] discardThresholdBoxes) { - List discardThresholds = new ArrayList(); - // go backwards; starting from first non-zero element, add them; take over leading zeroes which validator shall discard - for (int i = discardThresholdBoxes.length-1; i>=0; i--) { - if ((discardThresholdBoxes[i].getValue() != null - && discardThresholdBoxes[i].getValue().toString().length() > 0) || !discardThresholds.isEmpty()) { - if (discardThresholdBoxes[i].getValue() == null) { - discardThresholds.add(0, 0); - } else { - discardThresholds.add(0, discardThresholdBoxes[i].getValue().intValue()); - } - } - } - int[] discardThresholdsBoxContents = new int[discardThresholds.size()]; - for (int i = 0; i < discardThresholds.size(); i++) { - discardThresholdsBoxContents[i] = discardThresholds.get(i); - } - return discardThresholdsBoxContents; - } - @Override public void show() { super.show(); nameTextBox.setFocus(true); } - protected static LongBox[] initEmptyDiscardThresholdBoxes(DataEntryDialog dialog) { - LongBox[] result = new LongBox[MAX_NUMBER_OF_DISCARDED_RESULTS]; - for (int i = 0; i < result.length; i++) { - result[i] = dialog.createLongBoxWithOptionalValue(null, 2); - result[i].setVisibleLength(2); - } - return result; - } - - protected static LongBox[] initPrefilledDiscardThresholdBoxes(int[] valuesToShow, DataEntryDialog dialog) { - LongBox[] result = new LongBox[MAX_NUMBER_OF_DISCARDED_RESULTS]; - for (int i = 0; i < result.length; i++) { - if (i < valuesToShow.length) { - result[i] = dialog.createLongBox(valuesToShow[i], 2); - } else { - result[i] = dialog.createLongBoxWithOptionalValue(null, 2); - } - result[i].setVisibleLength(2); - } - return result; - } - protected static ListBox createScoringSchemeListBox(DataEntryDialog dialog, StringMessages stringMessages) { ListBox scoringSchemeListBox2 = dialog.createListBox(false); for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DiscardThresholdBoxes.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DiscardThresholdBoxes.java new file mode 100755 index 00000000000..0e6b3730115 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DiscardThresholdBoxes.java @@ -0,0 +1,116 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.LongBox; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.gwt.ui.client.DataEntryDialog; +import com.sap.sailing.gwt.ui.client.StringMessages; + +/** + * For a result discarding rule based on thresholds that tell after how many races the next discard kicks in, an instance of + * this class offers the UI components and validation rules that help in composing a UI that, among other things, allows a user + * to configure the discarding thresholds.

+ * + * TODO produce error messages during validation + * + * @author Axel Uhl (d043530) + * + */ +public class DiscardThresholdBoxes { + private static final int MAX_NUMBER_OF_DISCARDED_RESULTS = 4; + + private final LongBox[] discardThresholdBoxes; + private final DataEntryDialog parent; + + /** + * The widget used to represent the UI + */ + private final Widget widget; + + public DiscardThresholdBoxes(DataEntryDialog parent, StringMessages stringMessages) { + this(parent, /* values to show */ new int[0], stringMessages); + } + + public DiscardThresholdBoxes(DataEntryDialog parent, int[] initialDiscardThresholds, StringMessages stringMessages) { + this.parent = parent; + discardThresholdBoxes = new LongBox[MAX_NUMBER_OF_DISCARDED_RESULTS]; + for (int i = 0; i < discardThresholdBoxes.length; i++) { + if (initialDiscardThresholds != null && i < initialDiscardThresholds.length) { + discardThresholdBoxes[i] = parent.createLongBox(initialDiscardThresholds[i], 2); + } else { + discardThresholdBoxes[i] = parent.createLongBoxWithOptionalValue(null, 2); + } + discardThresholdBoxes[i].setVisibleLength(2); + } + widget = createDiscardThresholdBoxesPanel(stringMessages); + } + + /** + * @return the widget that can be added to the parent dialog passed to the constructor to visualize and edit the + * result discarding thresholds. The result returned from this object remains the same across this object's + * life time. + */ + public Widget getWidget() { + return widget; + } + + public int[] getDiscardThresholds() { + List discardThresholds = new ArrayList(); + // go backwards; starting from first non-zero element, add them; take over leading zeroes which validator shall discard + for (int i = discardThresholdBoxes.length-1; i>=0; i--) { + if ((discardThresholdBoxes[i].getValue() != null + && discardThresholdBoxes[i].getValue().toString().length() > 0) || !discardThresholds.isEmpty()) { + if (discardThresholdBoxes[i].getValue() == null) { + discardThresholds.add(0, 0); + } else { + discardThresholds.add(0, discardThresholdBoxes[i].getValue().intValue()); + } + } + } + int[] discardThresholdsBoxContents = new int[discardThresholds.size()]; + for (int i = 0; i < discardThresholds.size(); i++) { + discardThresholdsBoxContents[i] = discardThresholds.get(i); + } + return discardThresholdsBoxContents; + } + + private Widget createDiscardThresholdBoxesPanel(StringMessages stringMessages) { + assert discardThresholdBoxes != null && discardThresholdBoxes.length == MAX_NUMBER_OF_DISCARDED_RESULTS; + VerticalPanel vp = new VerticalPanel(); + vp.add(new Label(stringMessages.discardRacesFromHowManyStartedRacesOn())); + HorizontalPanel hp = new HorizontalPanel(); + vp.add(hp); + hp.setSpacing(3); + for (int i = 0; i < discardThresholdBoxes.length; i++) { + hp.add(new Label("" + (i + 1) + ".")); + hp.add(discardThresholdBoxes[i]); + } + parent.alignAllPanelWidgetsVertically(hp, HasVerticalAlignment.ALIGN_MIDDLE); + return vp; + } + + public static String getErrorMessage(int[] discardThresholds, StringMessages stringMessages) { + String errorMessage = null; + if (discardThresholds != null) { + boolean discardThresholdsAscending = true; + for (int i = 1; i < discardThresholds.length; i++) { + if (0 < discardThresholds.length) { + discardThresholdsAscending = discardThresholdsAscending + && discardThresholds[i - 1] < discardThresholds[i] + // and if one box is empty, all subsequent boxes need to be empty too + && (discardThresholds[i] == 0 || discardThresholds[i - 1] > 0); + } + } + if (!discardThresholdsAscending) { + errorMessage = stringMessages.discardThresholdsMustBeAscending(); + } + } + return errorMessage; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java index 88d89470fbd..dbf454bfae2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java @@ -11,7 +11,8 @@ public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog { public FlexibleLeaderboardCreateDialog(Collection existingLeaderboards, StringMessages stringMessages, Collection existingEvents, ErrorReporter errorReporter, DialogCallback callback) { - super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); + super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, existingEvents, + errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); nameTextBox = createTextBox(null); nameTextBox.ensureDebugId("LeaderboardNameField"); displayNameTextBox = createTextBox(null); @@ -20,6 +21,6 @@ public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog { scoringSchemeListBox = createScoringSchemeListBox(this, stringMessages); sailingEventsListBox = createSailingEventListBox(); - discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this); + discardThresholdBoxes = new DiscardThresholdBoxes(this, stringMessages); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java index 0ba615592d0..d55ad914d4f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardDialog.java @@ -6,8 +6,6 @@ import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HasVerticalAlignment; -import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Widget; @@ -24,12 +22,12 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo protected ListBox courseAreaListBox; protected static class LeaderboardParameterValidator implements Validator { - protected final StringMessages stringConstants; + protected final StringMessages stringMessages; protected final Collection existingLeaderboards; - public LeaderboardParameterValidator(StringMessages stringConstants, Collection existingLeaderboards){ + public LeaderboardParameterValidator(StringMessages stringConstants, Collection existingLeaderboards) { super(); - this.stringConstants = stringConstants; + this.stringMessages = stringConstants; this.existingLeaderboards = existingLeaderboards; } @@ -37,33 +35,23 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo public String getErrorMessage(LeaderboardDescriptor leaderboardToValidate) { String errorMessage; boolean nonEmpty = leaderboardToValidate.getName() != null && leaderboardToValidate.getName().length() > 0; - - boolean discardThresholdsAscending = true; - for (int i = 1; i < leaderboardToValidate.getDiscardThresholds().length; i++) { - // TODO what are correct values for discarding Thresholds? - if (0 < leaderboardToValidate.getDiscardThresholds().length){ - discardThresholdsAscending = discardThresholdsAscending - && leaderboardToValidate.getDiscardThresholds()[i - 1] < leaderboardToValidate.getDiscardThresholds()[i] - // and if one box is empty, all subsequent boxes need to be empty too - && (leaderboardToValidate.getDiscardThresholds()[i] == 0 || leaderboardToValidate.getDiscardThresholds()[i-1] > 0); - } - } - boolean unique = true; for (StrippedLeaderboardDTO dao : existingLeaderboards) { if(dao.name.equals(leaderboardToValidate.getName())){ unique = false; } } - if (!nonEmpty) { - errorMessage = stringConstants.pleaseEnterAName(); + errorMessage = stringMessages.pleaseEnterAName(); } else if(!unique){ - errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists(); - } else if (!discardThresholdsAscending) { - errorMessage = stringConstants.discardThresholdsMustBeAscending(); + errorMessage = stringMessages.leaderboardWithThisNameAlreadyExists(); } else { - errorMessage = null; + String discardThresholdErrorMessage = DiscardThresholdBoxes.getErrorMessage(leaderboardToValidate.getDiscardThresholds(), stringMessages); + if (discardThresholdErrorMessage != null) { + errorMessage = discardThresholdErrorMessage; + } else { + errorMessage = null; + } } return errorMessage; } @@ -112,15 +100,7 @@ public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialo formGrid.setWidget(4, 0, new Label(stringMessages.courseArea() + ":")); formGrid.setWidget(4, 1, courseAreaListBox); mainPanel.add(formGrid); - mainPanel.add(new Label(stringMessages.discardRacesFromHowManyStartedRacesOn())); - HorizontalPanel hp = new HorizontalPanel(); - hp.setSpacing(3); - for (int i = 0; i < discardThresholdBoxes.length; i++) { - hp.add(new Label("" + (i + 1) + ".")); - hp.add(discardThresholdBoxes[i]); - } - alignAllPanelWidgetsVertically(hp, HasVerticalAlignment.ALIGN_MIDDLE); - mainPanel.add(hp); + mainPanel.add(discardThresholdBoxes.getWidget()); return mainPanel; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java index 20c717f4416..f182de91b50 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java @@ -14,10 +14,10 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog { public FlexibleLeaderboardEditDialog(Collection otherExistingLeaderboards, - LeaderboardDescriptor leaderboard, StringMessages stringConstants, List existingEvents, ErrorReporter errorReporter, + LeaderboardDescriptor leaderboard, StringMessages stringMessages, List existingEvents, ErrorReporter errorReporter, DialogCallback callback) { - super(stringConstants.editFlexibleLeaderboard(), leaderboard, stringConstants, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator( - stringConstants, otherExistingLeaderboards), callback); + super(stringMessages.editFlexibleLeaderboard(), leaderboard, stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator( + stringMessages, otherExistingLeaderboards), callback); nameTextBox = createTextBox(leaderboard.getName()); displayNameTextBox = createTextBox(leaderboard.getDisplayName()); @@ -27,7 +27,7 @@ public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog { int j = 0; for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) { - scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants)); + scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringMessages)); if(leaderboard.getScoringScheme() == scoringSchemeType) { scoringSchemeListBox.setSelectedIndex(j); } @@ -48,6 +48,6 @@ public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog { } } } - discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboard.getDiscardThresholds(), this); + discardThresholdBoxes = new DiscardThresholdBoxes(this, leaderboard.getDiscardThresholds(), stringMessages); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java index 43b8d0c0841..c5976537bb7 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -269,8 +269,10 @@ public class LeaderboardConfigPanel extends FormPanel implements SelectedLeaderb Window.alert("This is a meta leaderboard. It can't be changed here."); } else { if (leaderboardDTO.isRegattaLeaderboard) { - LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, - leaderboardDTO.displayName, null, leaderboardDTO.discardThresholds, leaderboardDTO.regattaName, leaderboardDTO.defaultCourseAreaIdAsString); + LeaderboardDescriptor descriptor = new LeaderboardDescriptor(leaderboardDTO.name, + leaderboardDTO.displayName, /* scoring scheme provided by regatta */ null, + leaderboardDTO.discardThresholds, leaderboardDTO.regattaName, + leaderboardDTO.defaultCourseAreaIdAsString); AbstractLeaderboardDialog dialog = new RegattaLeaderboardEditDialog(Collections .unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas), descriptor, stringMessages, errorReporter, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java index dcd8816e882..1acdb0ce128 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java @@ -3,9 +3,10 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.sap.sailing.domain.common.ScoringSchemeType; /** - * A descriptor class for creating and editing basic data of a leaderboard + * A descriptor class for creating and editing basic data of a leaderboard. + * * @author Frank - * + * */ public class LeaderboardDescriptor { private String name; @@ -27,6 +28,9 @@ public class LeaderboardDescriptor { this.courseAreaIdAsString = courseAreaIdAsString; } + /** + * Leaves the {@link #regattaName} null, representing a flexible leaderboard, not a regatta leaderboard + */ public LeaderboardDescriptor(String name, String displayName, ScoringSchemeType scoringScheme, int[] discardThresholds, String courseAreaIdAsString) { this.name = name; this.displayName = displayName; @@ -51,6 +55,11 @@ public class LeaderboardDescriptor { this.scoringScheme = scoringScheme; } + /** + * @return null, in case the leaderboard does not explicitly define result discarding thresholds itself + * (e.g., a regatta leaderboard that obtains its result discarding rules from the underlying regatta's + * series definitions); a valid but possibly empty array otherwise + */ public int[] getDiscardThresholds() { return discardThresholds; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java index 93e0b2003a5..b1a3e74fd20 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupDialog.java @@ -10,10 +10,8 @@ import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; -import com.google.gwt.user.client.ui.LongBox; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.TextBox; @@ -32,7 +30,7 @@ public class LeaderboardGroupDialog extends DataEntryDialog callback, Collection existingLeaderboardGroups) { super(stringMessages.leaderboardGroup(), null, stringMessages.ok(), stringMessages.cancel(), @@ -140,20 +134,12 @@ public class LeaderboardGroupDialog extends DataEntryDialog(); seriesSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @@ -96,11 +88,9 @@ public class RegattaDetailsComposite extends Composite { } }); seriesTable.setSelectionModel(seriesSelectionModel); - seriesListDataProvider = new ListDataProvider(); seriesListDataProvider.addDataDisplay(seriesTable); vPanel.add(seriesTable); - initWidget(mainPanel); } @@ -161,6 +151,29 @@ public class RegattaDetailsComposite extends Composite { } }; + TextColumn discardsColumn = new TextColumn() { + @Override + public String getValue(SeriesDTO series) { + final String result; + if (series.getDiscardThresholds() == null) { + result = stringMessages.no(); + } else { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (int threshold : series.getDiscardThresholds()) { + if (first) { + first = false; + } else { + sb.append(", "); + } + sb.append(threshold); + } + result = sb.toString(); + } + return result; + } + }; + ImagesBarColumn seriesActionColumn = new ImagesBarColumn( new SeriesConfigImagesBarCell(stringMessages)); seriesActionColumn.setFieldUpdater(new FieldUpdater() { @@ -179,6 +192,7 @@ public class RegattaDetailsComposite extends Composite { table.addColumn(isMedalSeriesColumn, stringMessages.medalSeries()); table.addColumn(racesColumn, stringMessages.races()); table.addColumn(fleetsColumn, stringMessages.fleets()); + table.addColumn(discardsColumn, stringMessages.discarding()); table.addColumn(seriesActionColumn, stringMessages.actions()); return table; @@ -194,21 +208,26 @@ public class RegattaDetailsComposite extends Composite { } private void editRacesOfRegattaSeries(final RegattaDTO regatta, final SeriesDTO series) { - RaceColumnInRegattaSeriesDialog raceDialog = new RaceColumnInRegattaSeriesDialog(regatta, series, stringMessages, - new DialogCallback>>() { + SeriesEditDialog raceDialog = new SeriesEditDialog(regatta, series, stringMessages, + new DialogCallback() { @Override public void cancel() { } @Override - public void ok(final Pair> result) { - updateRacesOfRegattaSeries(regatta, result.getA(), result.getB()); + public void ok(final SeriesDescriptor result) { + updateRacesOfRegattaSeries(regatta, result); } }); raceDialog.show(); } - private void updateRacesOfRegattaSeries(final RegattaDTO regatta, final SeriesDTO series, List newRaceColumns) { + private void updateRacesOfRegattaSeries(final RegattaDTO regatta, final SeriesDescriptor seriesDescriptor) { + final SeriesDTO series = seriesDescriptor.getSeries(); + final List newRaceColumns = seriesDescriptor.getRaces(); + final boolean isMedalChanged = series.isMedal() != seriesDescriptor.isMedal(); + final boolean seriesResultDiscardingThresholdsChanged = !Arrays.equals(series.getDiscardThresholds(), + seriesDescriptor.getResultDiscardingThresholds()); final RegattaIdentifier regattaIdentifier = new RegattaName(regatta.name); List existingRaceColumns = series.getRaceColumns(); final List raceColumnsToAdd = new ArrayList(); @@ -224,7 +243,6 @@ public class RegattaDetailsComposite extends Composite { raceColumnsToRemove.add(existingRaceColumn.name); } } - sailingService.addRaceColumnsToSeries(regattaIdentifier, series.name, raceColumnsToAdd, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -246,7 +264,6 @@ public class RegattaDetailsComposite extends Composite { errorReporter.reportError("Error trying to remove race columns " + raceColumnsToAdd + " from series " + series.name + ": " + caught.getMessage()); - } @Override @@ -254,6 +271,22 @@ public class RegattaDetailsComposite extends Composite { regattaRefresher.fillRegattas(); } }); + if (isMedalChanged || seriesResultDiscardingThresholdsChanged) { + sailingService.updateSeries(regattaIdentifier, series.name, seriesDescriptor.isMedal(), + seriesDescriptor.getResultDiscardingThresholds(), new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to remove race columns " + + raceColumnsToAdd + " from series " + series.name + + ": " + caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + regattaRefresher.fillRegattas(); + } + }); + } } private void updateRegattaDetails() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java index ccb46a445da..49dbfcf9637 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java @@ -11,9 +11,9 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog { - public RegattaLeaderboardCreateDialog(Collection existingLeaderboards, Collection existingRegattas, StringMessages stringConstants, + public RegattaLeaderboardCreateDialog(Collection existingLeaderboards, Collection existingRegattas, StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback callback) { - super(stringConstants.createRegattaLeaderboard(), new LeaderboardDescriptor(), existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringConstants, existingLeaderboards), callback); + super(stringMessages.createRegattaLeaderboard(), new LeaderboardDescriptor(), existingRegattas, stringMessages, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); nameTextBox = createTextBox(null); displayNameTextBox = createTextBox(null); @@ -30,11 +30,10 @@ public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog { if (selectedIndex > 0) { nameTextBox.setText(regattaListBox.getValue(selectedIndex)); } + adjustVisibilityOfResultDiscardingRuleComponent(); } }); - - - discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this); + discardThresholdBoxes = new DiscardThresholdBoxes(this, stringMessages); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java index df98cb6930c..095d844acbb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java @@ -6,8 +6,6 @@ import java.util.Collections; import java.util.List; import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HasVerticalAlignment; -import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; @@ -21,58 +19,62 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog { protected ListBox regattaListBox; protected Collection existingRegattas; + private Label regattaDefinesDiscardsLabel; protected static class LeaderboardParameterValidator implements Validator { - protected final StringMessages stringConstants; + protected final StringMessages stringMessages; protected final Collection existingLeaderboards; - public LeaderboardParameterValidator(StringMessages stringConstants, Collection existingLeaderboards){ + public LeaderboardParameterValidator(StringMessages stringMessages, Collection existingLeaderboards){ super(); - this.stringConstants = stringConstants; + this.stringMessages = stringMessages; this.existingLeaderboards = existingLeaderboards; } @Override public String getErrorMessage(LeaderboardDescriptor leaderboardToValidate) { String errorMessage; - - boolean discardThresholdsAscending = true; - for (int i = 1; i < leaderboardToValidate.getDiscardThresholds().length; i++) { - // TODO what are correct values for discarding Thresholds? - if (0 < leaderboardToValidate.getDiscardThresholds().length){ - discardThresholdsAscending = discardThresholdsAscending - && leaderboardToValidate.getDiscardThresholds()[i - 1] < leaderboardToValidate.getDiscardThresholds()[i] - // and if one box is empty, all subsequent boxes need to be empty too - && (leaderboardToValidate.getDiscardThresholds()[i] == 0 || leaderboardToValidate.getDiscardThresholds()[i-1] > 0); - } - } - boolean unique = true; for (StrippedLeaderboardDTO dao : existingLeaderboards) { if(dao.name.equals(leaderboardToValidate.getRegattaName())){ unique = false; } } - boolean regattaSelected = leaderboardToValidate.getRegattaName() != null ? true : false; if(!regattaSelected){ - errorMessage = stringConstants.pleaseSelectARegatta(); + errorMessage = stringMessages.pleaseSelectARegatta(); } else if(!unique){ - errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists(); - } else if (!discardThresholdsAscending) { - errorMessage = stringConstants.discardThresholdsMustBeAscending(); + errorMessage = stringMessages.leaderboardWithThisNameAlreadyExists(); } else { - errorMessage = null; + String discardThresholdErrorMessage = DiscardThresholdBoxes.getErrorMessage( + leaderboardToValidate.getDiscardThresholds(), stringMessages); + if (discardThresholdErrorMessage != null) { + errorMessage = discardThresholdErrorMessage; + } else { + errorMessage = null; + } } return errorMessage; } } - public RegattaLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, Collection existingRegattas, StringMessages stringConstants, + public RegattaLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, Collection existingRegattas, StringMessages stringMessages, ErrorReporter errorReporter, LeaderboardParameterValidator validator, DialogCallback callback) { - super(title, leaderboardDTO, stringConstants, validator, callback); + super(title, leaderboardDTO, stringMessages, validator, callback); this.existingRegattas = existingRegattas; + regattaDefinesDiscardsLabel = new Label(stringMessages.regattaDefinesResultDiscardingRules()); + } + + + protected void adjustVisibilityOfResultDiscardingRuleComponent() { + if (getSelectedRegatta().definesSeriesDiscardThresholds()) { + discardThresholdBoxes.getWidget().setVisible(false); + regattaDefinesDiscardsLabel.setVisible(true); + } else { + discardThresholdBoxes.getWidget().setVisible(true); + regattaDefinesDiscardsLabel.setVisible(false); + } } protected ListBox createSortedRegattaListBox(Collection regattas, String preSelectedRegattaName) { @@ -107,7 +109,6 @@ public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog @Override protected Widget getAdditionalWidget() { VerticalPanel mainPanel = new VerticalPanel(); - Grid formGrid = new Grid(3,3); formGrid.setCellSpacing(3); formGrid.setWidget(0, 0, createLabel(stringMessages.regatta())); @@ -116,28 +117,22 @@ public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog formGrid.setWidget(1, 1, nameTextBox); formGrid.setWidget(2, 0, createLabel(stringMessages.displayName())); formGrid.setWidget(2, 1, displayNameTextBox); - mainPanel.add(formGrid); - - mainPanel.add(new Label(stringMessages.discardRacesFromHowManyStartedRacesOn())); - HorizontalPanel hp = new HorizontalPanel(); - hp.setSpacing(3); - for (int i = 0; i < discardThresholdBoxes.length; i++) { - hp.add(new Label("" + (i + 1) + ".")); - hp.add(discardThresholdBoxes[i]); + mainPanel.add(regattaDefinesDiscardsLabel); + if (discardThresholdBoxes != null) { + mainPanel.add(discardThresholdBoxes.getWidget()); + regattaDefinesDiscardsLabel.setVisible(false); } - alignAllPanelWidgetsVertically(hp, HasVerticalAlignment.ALIGN_MIDDLE); - mainPanel.add(hp); return mainPanel; } public RegattaDTO getSelectedRegatta() { RegattaDTO result = null; int selIndex = regattaListBox.getSelectedIndex(); - if(selIndex > 0) { // the zero index represents the 'no selection' text + if (selIndex > 0) { // the zero index represents the 'no selection' text String itemText = regattaListBox.getItemText(selIndex); - for(RegattaDTO regattaDTO: existingRegattas) { - if(regattaDTO.name.equals(itemText)) { + for (RegattaDTO regattaDTO : existingRegattas) { + if (regattaDTO.name.equals(itemText)) { result = regattaDTO; break; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java index febb739b0cd..777d720a0cc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java @@ -23,6 +23,9 @@ public class RegattaLeaderboardEditDialog extends RegattaLeaderboardDialog { regattaListBox = createSortedRegattaListBox(existingRegattas, leaderboardDescriptor.getRegattaName()); regattaListBox.setEnabled(false); - discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboardDescriptor.getDiscardThresholds(), this); + if (leaderboardDescriptor.getDiscardThresholds() != null) { + discardThresholdBoxes = new DiscardThresholdBoxes(this, leaderboardDescriptor.getDiscardThresholds(), stringMessages); + } // else, the regatta leaderboard obtains its result discarding rule implicitly from the underlying regatta + adjustVisibilityOfResultDiscardingRuleComponent(); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaStructureManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaStructureManagementPanel.java index aed0e230fe2..c220309a350 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaStructureManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaStructureManagementPanel.java @@ -18,7 +18,6 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.Color; import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.impl.Util.Pair; import com.sap.sailing.domain.common.impl.Util.Triple; import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback; import com.sap.sailing.gwt.ui.client.ErrorReporter; @@ -118,15 +117,16 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega } private void createNewRegatta(final RegattaDTO newRegatta) { - LinkedHashMap>, Boolean>> seriesStructure = - new LinkedHashMap>, Boolean>>(); + LinkedHashMap>, Boolean, int[]>> seriesStructure = + new LinkedHashMap>,Boolean,int[]>>(); for (SeriesDTO seriesDTO : newRegatta.series) { List> fleets = new ArrayList>(); for(FleetDTO fleetDTO : seriesDTO.getFleets()) { Triple fleetTriple = new Triple(fleetDTO.name, fleetDTO.getOrderNo(), fleetDTO.getColor()); fleets.add(fleetTriple); } - Pair>, Boolean> seriesPair = new Pair>, Boolean>(fleets, seriesDTO.isMedal()); + Triple>, Boolean, int[]> seriesPair = new Triple>, Boolean, int[]>( + fleets, seriesDTO.isMedal(), seriesDTO.getDiscardThresholds()); seriesStructure.put(seriesDTO.name, seriesPair); } sailingService.createRegatta(newRegatta.name, newRegatta.boatClass==null?null:newRegatta.boatClass.name, seriesStructure, true, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java index ab3a553843d..e040ca2c8c9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsCreateDialog.java @@ -106,7 +106,7 @@ public class RegattaWithSeriesAndFleetsCreateDialog extends RegattaWithSeriesAnd protected void setupAdditionalWidgetsOnPanel(final VerticalPanel panel) { panel.add(createHeadlineLabel(stringMessages.series())); panel.add(seriesGrid); - Button addSeriesButton = new Button("Add series"); + Button addSeriesButton = new Button(stringMessages.addSeries()); addSeriesButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java index f9d51abb9a6..476c49a0440 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaWithSeriesAndFleetsEditDialog.java @@ -17,7 +17,6 @@ public class RegattaWithSeriesAndFleetsEditDialog extends RegattaWithSeriesAndFl nameEntryField.setEnabled(false); boatClassEntryField.setEnabled(false); scoringSchemeListBox.setEnabled(false); - sailingEventsListBox.setEnabled(true); courseAreaListBox.setEnabled(true); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesDescriptor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesDescriptor.java new file mode 100755 index 00000000000..d587eadaf09 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesDescriptor.java @@ -0,0 +1,43 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import java.util.List; + +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.gwt.ui.shared.SeriesDTO; + +/** + * Used by {@link SeriesEditDialog} to capture the result of the user's configuration changes, + * including the race columns that the series shall define, the medal status and the discarding rules, if any. + * + * @author Axel Uhl (d043530) + * + */ +public class SeriesDescriptor { + private final SeriesDTO series; + private final List races; + private final boolean isMedal; + private final int[] resultDiscardingThresholds; + + public SeriesDescriptor(SeriesDTO series, List races, boolean isMedal, int[] resultDiscardingThresholds) { + this.series = series; + this.races = races; + this.isMedal = isMedal; + this.resultDiscardingThresholds = resultDiscardingThresholds; + } + + public SeriesDTO getSeries() { + return series; + } + + public List getRaces() { + return races; + } + + public boolean isMedal() { + return isMedal; + } + + public int[] getResultDiscardingThresholds() { + return resultDiscardingThresholds; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceColumnInRegattaSeriesDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java similarity index 75% rename from java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceColumnInRegattaSeriesDialog.java rename to java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java index e7ab75edb60..1421e728d56 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceColumnInRegattaSeriesDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SeriesEditDialog.java @@ -7,8 +7,11 @@ import java.util.Set; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.logical.shared.ValueChangeEvent; +import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; @@ -17,15 +20,16 @@ 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.dto.RaceColumnDTO; -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.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SeriesDTO; -public class RaceColumnInRegattaSeriesDialog extends DataEntryDialog>> { +public class SeriesEditDialog extends DataEntryDialog { private final ListBox addRacesListBox; private Button addRacesBtn; + private CheckBox isMedalCheckbox; + private CheckBox useSeriesResultDiscardingThresholdsCheckbox; private final List raceNameEntryFields; private final List