mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-30 09:26:44 +00:00
Merge remote-tracking branch 'origin/master' into jspsupport
This commit is contained in:
Binary file not shown.
+1
-1
@@ -1,5 +1,5 @@
|
||||
package com.sap.sailing.domain.common;
|
||||
|
||||
public enum ScoringSchemeType {
|
||||
LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL
|
||||
LOW_POINT, HIGH_POINT, HIGH_POINT_ESS_OVERALL, HIGH_POINT_LAST_BREAKS_TIE
|
||||
}
|
||||
|
||||
+5
@@ -185,6 +185,11 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
|
||||
public void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
}
|
||||
|
||||
+10
-4
@@ -22,11 +22,12 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.Course;
|
||||
import com.sap.sailing.domain.base.CourseListener;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Leg;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.BuoyImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseImpl;
|
||||
import com.sap.sailing.domain.base.impl.WaypointImpl;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
@@ -235,9 +236,14 @@ public class CourseUpdateTest extends AbstractTracTracLiveTest {
|
||||
System.out.println("waypointRemoved " + zeroBasedIndex + " / " + waypointThatGotRemoved);
|
||||
}
|
||||
});
|
||||
domainFactory.updateCourseWaypoints(course, controlPoints);
|
||||
assertTrue(result[0]);
|
||||
testLegStructure(3);
|
||||
((CourseImpl) course).lockForWrite(); // without the lock it's possible that another race course update removes the additional waypoint again
|
||||
try {
|
||||
domainFactory.updateCourseWaypoints(course, controlPoints);
|
||||
assertTrue(result[0]);
|
||||
testLegStructure(3);
|
||||
} finally {
|
||||
((CourseImpl) course).unlockAfterWrite();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+8
-5
@@ -250,16 +250,19 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
}
|
||||
List<Integer> ranksOfNonMedalStartedRaces = new ArrayList<Integer>();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
int numberOfRacesToCompareToDiscardThresholds = 0;
|
||||
for (RaceColumn column : raceColumnsInLeaderboard.values()) {
|
||||
if (!column.isMedalRace() && column.getTrackedRace(defaultFleet) != null && column.getTrackedRace(defaultFleet).hasStarted(now)) {
|
||||
ranksOfNonMedalStartedRaces.add(column.getTrackedRace(defaultFleet).getRank(competitor, now));
|
||||
if (column.getTrackedRace(defaultFleet) != null && column.getTrackedRace(defaultFleet).hasStarted(now)) {
|
||||
numberOfRacesToCompareToDiscardThresholds++;
|
||||
if (!column.isMedalRace()) {
|
||||
ranksOfNonMedalStartedRaces.add(column.getTrackedRace(defaultFleet).getRank(competitor, now));
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(ranksOfNonMedalStartedRaces);
|
||||
int carryInt = (carry == null ? 0 : carry);
|
||||
int totalPoints = carryInt;
|
||||
int medalRacePoints = getMedalRacePoints(competitor, now, defaultFleet);
|
||||
int numberOfRacesFromWhichToDiscard = ranksOfNonMedalStartedRaces.size();
|
||||
for (TrackedRace race : testRaces) {
|
||||
RaceColumn raceColumn = raceColumnsInLeaderboard.get(race);
|
||||
Pair<Competitor, RaceColumn> key = new Pair<Competitor, RaceColumn>(competitor, raceColumn);
|
||||
@@ -274,8 +277,8 @@ public class LeaderboardOfflineTest extends AbstractLeaderboardTest {
|
||||
// One race is discarded because four races were started, and for [3-6) one race can be discarded.
|
||||
// The discarded race is the worst of those started, so the one with rank 4.
|
||||
int expectedNumberOfDiscardedRaces =
|
||||
numberOfRacesFromWhichToDiscard < firstDiscardingThreshold ? 0 :
|
||||
numberOfRacesFromWhichToDiscard < secondDiscardingThreshold ? 1 : 2;
|
||||
numberOfRacesToCompareToDiscardThresholds < firstDiscardingThreshold ? 0 :
|
||||
numberOfRacesToCompareToDiscardThresholds < secondDiscardingThreshold ? 1 : 2;
|
||||
boolean discarded = ranksOfNonMedalStartedRaces.indexOf(rank) >= ranksOfNonMedalStartedRaces.size()-expectedNumberOfDiscardedRaces;
|
||||
int expected = discarded ? 0 : rank==medalRacePoints?2*rank:rank;
|
||||
assertEquals(expected, leaderboard.getTotalPoints(competitor, raceColumn, now), 0.000000001);
|
||||
|
||||
+234
-2
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -107,6 +108,209 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regarding bug 961, test scoring in a leaderboard that has a qualification series with two unordered groups where for one
|
||||
* column only one group has raced (expressed by a mocked TrackedRace attached to the column). Ensure that the column doesn't
|
||||
* count for neither the total points sum nor the competitor ordering.
|
||||
*/
|
||||
@Test
|
||||
public void testUnorderedGroupsWithOneGroupNotHavingRacedInAColumn() throws NoWindException {
|
||||
List<Competitor> competitors = createCompetitors(10);
|
||||
Regatta regatta = createRegatta(/* qualifying */ 2, new String[] { "Yellow", "Blue" }, /* final */0,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, "testUnorderedGroupsWithOneGroupNotHavingRacedInAcolumn",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true),
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
Series qualificationSeries;
|
||||
Iterator<? extends Series> seriesIter = regatta.getSeries().iterator();
|
||||
qualificationSeries = seriesIter.next();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace q1Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(0, 5));
|
||||
TrackedRace q1Blue = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(5, 10));
|
||||
RaceColumn q1Column = qualificationSeries.getRaceColumnByName("Q1");
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Yellow"), q1Yellow);
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Blue"), q1Blue);
|
||||
List<Competitor> rankedCompetitors = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertTrue(competitors.get(i) == rankedCompetitors.get(2*i) || competitors.get(i) == rankedCompetitors.get(2*i+1));
|
||||
assertTrue(competitors.get(i+5) == rankedCompetitors.get(2*i) || competitors.get(i+5) == rankedCompetitors.get(2*i+1));
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i), later), 0.000000001);
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i+5), later), 0.0000000001);
|
||||
}
|
||||
// now add one race for yellow fleet and test that it doesn't count because blue fleet is still missing its race for Q2
|
||||
TrackedRace q2Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(3, 8));
|
||||
RaceColumn q2Column = qualificationSeries.getRaceColumnByName("Q2");
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Yellow"), q2Yellow);
|
||||
List<Competitor> rankedCompetitorsWithOneRaceMissingInQ2 = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertTrue(competitors.get(i) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i) ||
|
||||
competitors.get(i) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i+1));
|
||||
assertTrue(competitors.get(i+5) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i) ||
|
||||
competitors.get(i+5) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i+1));
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i), later), 0.000000001);
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i+5), later), 0.0000000001);
|
||||
}
|
||||
// now add a tracked race for the blue fleet for Q2 and assert that the Q2 scores count for the total points sum
|
||||
TrackedRace q2Blue = new MockedTrackedRaceWithStartTimeAndRanks(now,
|
||||
Arrays.asList(new Competitor[] { competitors.get(0), competitors.get(1), competitors.get(2),
|
||||
competitors.get(8), competitors.get(9) }));
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Blue"), q2Blue);
|
||||
// the new order in Q2 expected to be { (0, 3), (1, 4), (2, 5), (8, 6), (9, 7) }
|
||||
// therefore the new total points, in ascending order, are expected to be:
|
||||
// { 0: 1+1=2; 5: 1+3=4; 1: 2+2=4; 3: 4+1=5; 2: 3+3=6; 6: 2+4=6; 4: 5+2=7; 7: 3+5=8; 8: 4+4=8; 9: 5+5=10 }
|
||||
double[] expectedTotalPoints = new double[] { 2, 4, 6, 5, 7, 4, 6, 8, 8, 10 };
|
||||
int[] expectedOrderAfterTwoFullRacesPlusMinusOne = new int[] { 0, 5, 1, 3, 2, 6, 4, 7, 8, 9 };
|
||||
List<Competitor> rankedCompetitorsWithAllRacesInQ2 = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertTrue(competitors.get(expectedOrderAfterTwoFullRacesPlusMinusOne[2*i]) == rankedCompetitorsWithAllRacesInQ2.get(2*i) ||
|
||||
competitors.get(expectedOrderAfterTwoFullRacesPlusMinusOne[2*i]) == rankedCompetitorsWithAllRacesInQ2.get(2*i+1));
|
||||
assertTrue(competitors.get(expectedOrderAfterTwoFullRacesPlusMinusOne[2*i+1]) == rankedCompetitorsWithAllRacesInQ2.get(2*i) ||
|
||||
competitors.get(expectedOrderAfterTwoFullRacesPlusMinusOne[2*i+1]) == rankedCompetitorsWithAllRacesInQ2.get(2*i+1));
|
||||
assertEquals(expectedTotalPoints[2*i], leaderboard.getTotalPoints(competitors.get(2*i), later), 0.000000001);
|
||||
assertEquals(expectedTotalPoints[2*i+1], leaderboard.getTotalPoints(competitors.get(2*i+1), later), 0.000000001);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Regarding bug 961, test scoring in a leaderboard that has a qualification series with two unordered groups where for one
|
||||
* column only one group has raced (expressed by a mocked TrackedRace attached to the column). Then add the second tracked
|
||||
* race for the second column but such that it hasn't started yet at the time point of the query. Then add a score correction,
|
||||
* simulating the use of a proxy race (that doesn't ever start) and a manual score entry.
|
||||
*/
|
||||
@Test
|
||||
public void testUnorderedGroupsWithOneGroupNotHavingStartedRacedInAcolumnAndThenCorrectingScore() throws NoWindException {
|
||||
List<Competitor> competitors = createCompetitors(10);
|
||||
Regatta regatta = createRegatta(/* qualifying */ 2, new String[] { "Yellow", "Blue" }, /* final */0,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, "testUnorderedGroupsWithOneGroupNotHavingRacedInAcolumn",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true),
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
Series qualificationSeries;
|
||||
Iterator<? extends Series> seriesIter = regatta.getSeries().iterator();
|
||||
qualificationSeries = seriesIter.next();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace q1Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(0, 5));
|
||||
TrackedRace q1Blue = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(5, 10));
|
||||
RaceColumn q1Column = qualificationSeries.getRaceColumnByName("Q1");
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Yellow"), q1Yellow);
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Blue"), q1Blue);
|
||||
// now add one race for yellow fleet and test that it doesn't count because blue fleet is still missing its race for Q2
|
||||
TrackedRace q2Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(3, 8));
|
||||
RaceColumn q2Column = qualificationSeries.getRaceColumnByName("Q2");
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Yellow"), q2Yellow);
|
||||
// now add a tracked race for the blue fleet for Q2 that hasn't started yet and assert that the Q2 scores still don't count for the total points sum
|
||||
TimePoint muchLater = later.plus(10000000000l);
|
||||
TrackedRace q2Blue = new MockedTrackedRaceWithStartTimeAndRanks(muchLater,
|
||||
Arrays.asList(new Competitor[] { competitors.get(0), competitors.get(1), competitors.get(2),
|
||||
competitors.get(8), competitors.get(9) }));
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Blue"), q2Blue);
|
||||
List<Competitor> rankedCompetitorsWithOneRaceMissingInQ2 = leaderboard.getCompetitorsFromBestToWorst(later);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertTrue(competitors.get(i) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i) ||
|
||||
competitors.get(i) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i+1));
|
||||
assertTrue(competitors.get(i+5) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i) ||
|
||||
competitors.get(i+5) == rankedCompetitorsWithOneRaceMissingInQ2.get(2*i+1));
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i), later), 0.000000001);
|
||||
assertEquals((double) (i+1), leaderboard.getTotalPoints(competitors.get(i+5), later), 0.0000000001);
|
||||
}
|
||||
assertFalse(leaderboard.getScoringScheme().isValidInTotalScore(leaderboard, q2Column, later));
|
||||
// now add a score correction for Q2/Blue to make it count:
|
||||
leaderboard.getScoreCorrection().correctScore(competitors.get(9), q2Column, 42.);
|
||||
assertTrue(leaderboard.getScoringScheme().isValidInTotalScore(leaderboard, q2Column, later));
|
||||
// the new order in Q2 expected to be { (9, 3), ... } (we don't know about any competitor in q2Blue but #9
|
||||
// therefore the new total points for #9 are
|
||||
// { 9: 5+42=47 }
|
||||
assertEquals(47.0, leaderboard.getTotalPoints(competitors.get(9), later), 0.00000001);
|
||||
}
|
||||
|
||||
/**
|
||||
* Regarding bug 961, test scoring in a leaderboard that has a qualification series with two unordered groups where for one
|
||||
* column only one group has raced (expressed by a mocked TrackedRace attached to the column). Ensure that the column doesn't
|
||||
* count for computing the number of discards.
|
||||
*/
|
||||
@Test
|
||||
public void testDiscardsForUnorderedGroupsWithOneGroupNotHavingRacedInAColumn() throws NoWindException {
|
||||
List<Competitor> competitors = createCompetitors(10);
|
||||
Regatta regatta = createRegatta(/* qualifying */ 2, new String[] { "Yellow", "Blue" }, /* final */0,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, "testDiscardsForUnorderedGroupsWithOneGroupNotHavingRacedInAColumn",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true),
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[]{2}); // one discard for two or more races
|
||||
Series qualificationSeries;
|
||||
Iterator<? extends Series> seriesIter = regatta.getSeries().iterator();
|
||||
qualificationSeries = seriesIter.next();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace q1Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(0, 5));
|
||||
TrackedRace q1Blue = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(5, 10));
|
||||
RaceColumn q1Column = qualificationSeries.getRaceColumnByName("Q1");
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Yellow"), q1Yellow);
|
||||
q1Column.setTrackedRace(q1Column.getFleetByName("Blue"), q1Blue);
|
||||
// now add one race for yellow fleet and test that there are no discards still because blue fleet is still missing its race for Q2
|
||||
TrackedRace q2Yellow = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(3, 8));
|
||||
RaceColumn q2Column = qualificationSeries.getRaceColumnByName("Q2");
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Yellow"), q2Yellow);
|
||||
for (Competitor competitor : competitors) {
|
||||
assertFalse("Competitor "+competitor+" has a discard in Q1 but shouldn't", leaderboard.isDiscarded(competitor, q1Column, later));
|
||||
assertFalse("Competitor "+competitor+" has a discard in Q2 but shouldn't", leaderboard.isDiscarded(competitor, q2Column, later));
|
||||
}
|
||||
// now add a tracked race for the blue fleet for Q2 and assert that all competitors have one discard
|
||||
TrackedRace q2Blue = new MockedTrackedRaceWithStartTimeAndRanks(now,
|
||||
Arrays.asList(new Competitor[] { competitors.get(0), competitors.get(1), competitors.get(2),
|
||||
competitors.get(8), competitors.get(9) }));
|
||||
q2Column.setTrackedRace(q2Column.getFleetByName("Blue"), q2Blue);
|
||||
for (Competitor competitor : competitors) {
|
||||
assertTrue("Competitor "+competitor+" has no discard but should",
|
||||
leaderboard.isDiscarded(competitor, q1Column, later) || leaderboard.isDiscarded(competitor, q2Column, later));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regarding bug 961, test scoring in a leaderboard that has a qualification series with two ordered groups where for one
|
||||
* column only one group has raced (expressed by a mocked TrackedRace attached to the column). Ensure that the competitors in
|
||||
* that column get their discard.
|
||||
*/
|
||||
@Test
|
||||
public void testDiscardsForOrderedGroupsWithOneGroupNotHavingRacedInAColumn() throws NoWindException {
|
||||
List<Competitor> competitors = createCompetitors(10);
|
||||
Regatta regatta = createRegatta(/* qualifying */ 0, new String[] { "Default" }, /* final */2,
|
||||
new String[] { "Gold", "Silver" },
|
||||
/* medal */false, "testDiscardsForOrderedGroupsWithOneGroupNotHavingRacedInAColumn",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true),
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[]{2}); // one discard for two or more races
|
||||
Series finalSeries;
|
||||
Iterator<? extends Series> seriesIter = regatta.getSeries().iterator();
|
||||
seriesIter.next();
|
||||
finalSeries = seriesIter.next();
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
TrackedRace f1Gold = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(0, 5));
|
||||
TrackedRace f1Silver = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(5, 10));
|
||||
RaceColumn f1Column = finalSeries.getRaceColumnByName("F1");
|
||||
f1Column.setTrackedRace(f1Column.getFleetByName("Gold"), f1Gold);
|
||||
f1Column.setTrackedRace(f1Column.getFleetByName("Silver"), f1Silver);
|
||||
// now add one race for yellow fleet and test that there are no discards still because blue fleet is still missing its race for Q2
|
||||
TrackedRace f2Gold = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors.subList(0, 5));
|
||||
RaceColumn f2Column = finalSeries.getRaceColumnByName("F2");
|
||||
f2Column.setTrackedRace(f2Column.getFleetByName("Gold"), f2Gold);
|
||||
for (int i=0; i<5; i++) {
|
||||
assertTrue("Competitor "+competitors.get(i)+" has no discard in F1 or F2 but should",
|
||||
leaderboard.isDiscarded(competitors.get(i), f1Column, later) ||
|
||||
leaderboard.isDiscarded(competitors.get(i), f2Column, later));
|
||||
}
|
||||
for (int i=5; i<10; i++) {
|
||||
assertFalse("Competitor "+competitors.get(i)+" has a discard in F1 or F2 but shouldn't",
|
||||
leaderboard.isDiscarded(competitors.get(i), f1Column, later) ||
|
||||
leaderboard.isDiscarded(competitors.get(i), f2Column, later));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the competitors ranking worse than the disqualified competitor advance by one in the
|
||||
@@ -118,7 +322,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
List<Competitor> competitors = createCompetitors(10);
|
||||
Regatta regatta = createRegatta(/* qualifying */0, new String[] { "Default" }, /* final */1,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, "testOneStartedRaceWithDifferentScores",
|
||||
/* medal */false, "testOneStartedRaceWithDifferentScoresAndDisqualification",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
Series finalSeries;
|
||||
@@ -157,7 +361,7 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
}
|
||||
Regatta regatta = createRegatta(/* qualifying */1, new String[] { "Yellow", "Blue" }, /* final */0,
|
||||
new String[] { "Default" },
|
||||
/* medal */false, "testAllTrackedAndStartedWithDifferentScores",
|
||||
/* medal */false, "testDistributionAcrossQualifyingFleetsWithDifferentScores",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */true), DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.LOW_POINT));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
@@ -280,6 +484,34 @@ public class LeaderboardScoringAndRankingTest extends AbstractLeaderboardTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLastRaceTakesPrecedenceWithHighPointLastBreaksTieScheme() throws NoWindException {
|
||||
List<Competitor> competitors = createCompetitors(20);
|
||||
Regatta regatta = createRegatta(/* qualifying */ 0, new String[] { "Default" }, /* final */ 2, new String[] { "Default" },
|
||||
/* medal */ false, "testLastRaceTakesPrecedenceWithHighPointLastBreaksTieScheme",
|
||||
DomainFactory.INSTANCE.getOrCreateBoatClass("49er", /* typicallyStartsUpwind */ true),
|
||||
DomainFactory.INSTANCE.createScoringScheme(ScoringSchemeType.HIGH_POINT_LAST_BREAKS_TIE));
|
||||
Leaderboard leaderboard = createLeaderboard(regatta, /* discarding thresholds */ new int[0]);
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint later = new MillisecondsTimePoint(now.asMillis()+1000);
|
||||
RaceColumn f1Column = series.get(1).getRaceColumnByName("F1");
|
||||
TrackedRace f1Default = new MockedTrackedRaceWithStartTimeAndRanks(now, competitors);
|
||||
f1Column.setTrackedRace(f1Column.getFleetByName("Default"), f1Default);
|
||||
List<Competitor> reversedCompetitors = new ArrayList<Competitor>(competitors);
|
||||
Collections.reverse(reversedCompetitors);
|
||||
RaceColumn f2Column = series.get(1).getRaceColumnByName("F2");
|
||||
TrackedRace f2Default = new MockedTrackedRaceWithStartTimeAndRanks(now, reversedCompetitors);
|
||||
f2Column.setTrackedRace(f2Column.getFleetByName("Default"), f2Default);
|
||||
|
||||
// assert that all competitors have equal points now
|
||||
Competitor firstCompetitor = competitors.iterator().next();
|
||||
for (Competitor competitor : competitors) {
|
||||
assertEquals(leaderboard.getTotalPoints(firstCompetitor, later), leaderboard.getTotalPoints(competitor, later));
|
||||
}
|
||||
// assert that the ordering of competitors equals that of the last race
|
||||
assertEquals(reversedCompetitors, leaderboard.getCompetitorsFromBestToWorst(later));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTieBreakWithTwoVersusOneWins() throws NoWindException {
|
||||
Competitor[] c = createCompetitors(3).toArray(new Competitor[0]);
|
||||
|
||||
+93
-2
@@ -1,17 +1,108 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
|
||||
|
||||
public class LockTraceTest {
|
||||
private static class LockingThread extends Thread {
|
||||
private boolean ownsLock;
|
||||
|
||||
public LockingThread(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public synchronized boolean ownsLock() {
|
||||
return ownsLock;
|
||||
}
|
||||
|
||||
public synchronized void obtainLockAndWait(Lock lock) throws InterruptedException {
|
||||
lock.lock();
|
||||
ownsLock = true;
|
||||
notifyAll();
|
||||
wait();
|
||||
}
|
||||
|
||||
public synchronized void waitUntilLockIsObtained() throws InterruptedException {
|
||||
while (!ownsLock()) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testLockTrace() throws InterruptedException {
|
||||
public void testLockTraceForMultipleReaders() throws InterruptedException {
|
||||
NamedReentrantReadWriteLock lock1 = new NamedReentrantReadWriteLock("Lock1", /* fair */ true);
|
||||
lock1.readLock().lock();
|
||||
boolean itWorked = lock1.writeLock().tryLock(10, TimeUnit.MILLISECONDS);
|
||||
Object o = createAndStartLockingThreadReturningObjectToNotifyInOrderToReleaseLockAndTerminateThread(lock1.readLock());
|
||||
lock1.writeLock().lock();
|
||||
boolean itWorked = lock1.writeLock().tryLock(1000000000000000000l, TimeUnit.MILLISECONDS);
|
||||
System.out.println(itWorked);
|
||||
lock1.readLock().unlock();
|
||||
synchronized (o) {
|
||||
o.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testDeadlockDetectionWithJMX() throws InterruptedException {
|
||||
NamedReentrantReadWriteLock lock1 = new NamedReentrantReadWriteLock("Lock1", /* fair */ true);
|
||||
NamedReentrantReadWriteLock lock2 = new NamedReentrantReadWriteLock("Lock2", /* fair */ true);
|
||||
lock1.readLock().lock();
|
||||
// let other thread get write lock on lock2
|
||||
LockingThread o = createAndStartLockingThreadReturningObjectToNotifyInOrderToCauseDeadlock(lock2.writeLock(), lock1.writeLock());
|
||||
o.waitUntilLockIsObtained();
|
||||
// now let other thread continue so it tries to obtain the write lock on lock1 which it can't get because we own the read lock
|
||||
synchronized (o) {
|
||||
o.notifyAll();
|
||||
}
|
||||
// and complete the deadlock by asking lock2's read lock
|
||||
lock2.readLock().lock();
|
||||
lock1.readLock().unlock();
|
||||
lock2.readLock().unlock();
|
||||
}
|
||||
|
||||
private Object createAndStartLockingThreadReturningObjectToNotifyInOrderToReleaseLockAndTerminateThread(final Lock lock) {
|
||||
final Thread thread = new Thread("Thread to lock "+lock) {
|
||||
public void run() {
|
||||
lock.lock();
|
||||
synchronized (Thread.currentThread()) {
|
||||
try {
|
||||
Thread.currentThread().wait();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
return thread;
|
||||
}
|
||||
|
||||
private LockingThread createAndStartLockingThreadReturningObjectToNotifyInOrderToCauseDeadlock(final Lock lock1, final Lock lock2) {
|
||||
final LockingThread thread = new LockingThread("Thread to lock "+lock1+" and then "+lock2) {
|
||||
public void run() {
|
||||
try {
|
||||
obtainLockAndWait(lock1);
|
||||
} catch (InterruptedException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
lock2.lock();
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
return thread;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
new LockTraceTest().testDeadlockDetectionWithJMX();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -482,7 +483,8 @@ public class TrackTest {
|
||||
GPSFix outlier = new GPSFixImpl(outlierPosition, timePointForOutlier);
|
||||
track.addGPSFix(outlier);
|
||||
assertEquals(1, invalidationCalls.size());
|
||||
assertEquals(timePointForOutlier, invalidationCalls.iterator().next()); // outlier doesn't turn its preceding element into an outlier
|
||||
TimePoint timePointOfLastFixBeforeOutlier = track.getLastFixBefore(timePointForOutlier).getTimePoint();
|
||||
assertTrue(invalidationCalls.iterator().next().after(timePointOfLastFixBeforeOutlier)); // outlier doesn't turn its preceding element into an outlier
|
||||
assertNull(distanceCache.getEarliestFromAndDistanceAtOrAfterFrom(now, start)); // no more entry for "to"-value start in cache
|
||||
invalidationCalls.clear();
|
||||
final TimePoint timePointOfLastOriginalFix = track.getLastRawFix().getTimePoint();
|
||||
@@ -498,7 +500,8 @@ public class TrackTest {
|
||||
GPSFix lateOutlier = new GPSFixImpl(lateOutlierPosition, timePointForLateOutlier);
|
||||
track.addGPSFix(lateOutlier);
|
||||
assertEquals(1, invalidationCalls.size());
|
||||
assertEquals(timePointForLateOutlier, invalidationCalls.iterator().next());
|
||||
TimePoint timePointOfLastFixBeforeLateOutlier = track.getLastFixBefore(timePointForLateOutlier).getTimePoint();
|
||||
assertTrue(invalidationCalls.iterator().next().after(timePointOfLastFixBeforeLateOutlier));
|
||||
invalidationCalls.clear();
|
||||
// expect the invalidation to have started after the single cache entry, so the cache entry still has to be there:
|
||||
final Pair<TimePoint, Pair<TimePoint, Distance>> stillPresentFullIntervalCacheEntry = distanceCache
|
||||
@@ -539,6 +542,57 @@ public class TrackTest {
|
||||
assertEquals(speed.getMetersPerSecond()*steps, track.getDistanceTraveled(now, start).getMeters(), 0.01);
|
||||
}
|
||||
|
||||
/**
|
||||
* A test case for bug 968. If distances are requested for time intervals ending after the last GPS fix, the position
|
||||
* is estimated to be at the last fix known. When another fix arrives, the positions for these time points can now be
|
||||
* interpolated, leading to different results and hence to a cache inconsistency in case the cache isn't flushed for the
|
||||
* interval between the last and the newest fix. This test case adds a few fixes, then asks a distance traveled for an
|
||||
* interval ending after the last fix, then adds another fix at a later time point and asks the distance again.
|
||||
*/
|
||||
@Test
|
||||
public void testMoreFrequentDistanceComputationThanGPSFixReception() {
|
||||
DynamicGPSFixTrack<Object, GPSFix> track = new DynamicGPSFixTrackImpl<Object>(new Object(), /* millisecondsOverWhichToAverage */ 30000l);
|
||||
final int timeBetweenFixesInMillis = 1000;
|
||||
Bearing bearing = new DegreeBearingImpl(123);
|
||||
Speed speed = new KnotSpeedImpl(7);
|
||||
Position p = new DegreePosition(0, 0);
|
||||
final MillisecondsTimePoint now = MillisecondsTimePoint.now();
|
||||
TimePoint start = now;
|
||||
final int steps = 10;
|
||||
TimePoint next = null;
|
||||
GPSFix fix = null;
|
||||
for (int i=0; i<steps; i++) {
|
||||
fix = new GPSFixImpl(p, start);
|
||||
track.addGPSFix(fix);
|
||||
next = start.plus(timeBetweenFixesInMillis);
|
||||
p = p.translateGreatCircle(bearing, speed.travel(start, next));
|
||||
start = next;
|
||||
bearing = new DegreeBearingImpl(bearing.getDegrees() + 1);
|
||||
}
|
||||
Distance distance1 = track.getDistanceTraveled(now, next.minus(timeBetweenFixesInMillis));
|
||||
Distance distance2 = track.getDistanceTraveled(now, next.minus(2*timeBetweenFixesInMillis/3));
|
||||
Distance distance3 = track.getDistanceTraveled(now, next.minus(timeBetweenFixesInMillis/3));
|
||||
Distance distance4 = track.getDistanceTraveled(now, next);
|
||||
assertEquals(distance1, distance2); // no progress after time point "next" because no further fixes are known
|
||||
assertEquals(distance1, distance3); // no progress after time point "next" because no further fixes are known
|
||||
assertEquals(distance1, distance4); // no progress after time point "next" because no further fixes are known
|
||||
// now add one more fix
|
||||
fix = new GPSFixImpl(p, start);
|
||||
track.addGPSFix(fix);
|
||||
Distance distance1_new = track.getDistanceTraveled(now, next.minus(timeBetweenFixesInMillis));
|
||||
Distance distance2_new = track.getDistanceTraveled(now, next.minus(2*timeBetweenFixesInMillis/3));
|
||||
Distance distance3_new = track.getDistanceTraveled(now, next.minus(timeBetweenFixesInMillis/3));
|
||||
Distance distance4_new = track.getDistanceTraveled(now, next);
|
||||
assertEquals(distance1, distance1_new);
|
||||
assertFalse(distance2.equals(distance2_new));
|
||||
assertFalse(distance3.equals(distance3_new));
|
||||
assertFalse(distance4.equals(distance4_new));
|
||||
Distance toReachInOneThirdOfTimeBetweenFixesInMillis = speed.travel(next, next.plus(timeBetweenFixesInMillis/3));
|
||||
assertEquals(toReachInOneThirdOfTimeBetweenFixesInMillis.getMeters(), distance2_new.getMeters()-distance1_new.getMeters(), 0.01);
|
||||
assertEquals(toReachInOneThirdOfTimeBetweenFixesInMillis.getMeters(), distance3_new.getMeters()-distance2_new.getMeters(), 0.01);
|
||||
assertEquals(toReachInOneThirdOfTimeBetweenFixesInMillis.getMeters(), distance4_new.getMeters()-distance3_new.getMeters(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistanceCacheAccessForPartialStrip() {
|
||||
final Set<TimePoint> invalidationCalls = new HashSet<TimePoint>();
|
||||
|
||||
@@ -1,24 +1,49 @@
|
||||
package com.sap.sailing.domain.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.base.BoatClass;
|
||||
import com.sap.sailing.domain.base.Buoy;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.base.ControlPoint;
|
||||
import com.sap.sailing.domain.base.DomainFactory;
|
||||
import com.sap.sailing.domain.base.Waypoint;
|
||||
import com.sap.sailing.domain.base.impl.BoatClassImpl;
|
||||
import com.sap.sailing.domain.base.impl.BoatImpl;
|
||||
import com.sap.sailing.domain.base.impl.CompetitorImpl;
|
||||
import com.sap.sailing.domain.base.impl.CourseImpl;
|
||||
import com.sap.sailing.domain.base.impl.KnotSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.base.impl.NationalityImpl;
|
||||
import com.sap.sailing.domain.base.impl.PersonImpl;
|
||||
import com.sap.sailing.domain.base.impl.RaceDefinitionImpl;
|
||||
import com.sap.sailing.domain.base.impl.RegattaImpl;
|
||||
import com.sap.sailing.domain.base.impl.TeamImpl;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.common.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.Wind;
|
||||
import com.sap.sailing.domain.tracking.WindTrack;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.WindImpl;
|
||||
import com.sap.sailing.domain.tracking.impl.WindTrackImpl;
|
||||
|
||||
@@ -213,4 +238,46 @@ public class WindTest {
|
||||
// TODO create a tracked race with corresponding WEB wind source; put leader in downwind, trailer in upwind and
|
||||
// TODO test that windward distance includes the full reaching leg's length
|
||||
}
|
||||
|
||||
/**
|
||||
* See bug 943. Wind estimation should return <code>null</code> instead of causing exceptions in case there
|
||||
* is no wind data to bootstrap the estimator with.
|
||||
*/
|
||||
@Test
|
||||
public void testWindEstimationReturnsNullIfNoUpwindStartAndNoOtherWindDataAvailable() {
|
||||
DomainFactory domainFactory = DomainFactory.INSTANCE;
|
||||
Buoy startFinishLeft = domainFactory.getOrCreateBuoy("Start/Finish left");
|
||||
Buoy startFinishRight = domainFactory.getOrCreateBuoy("Start/Finish right");
|
||||
ControlPoint startFinish = domainFactory.createGate(startFinishLeft, startFinishRight, "Start/Finish");
|
||||
ControlPoint top = domainFactory.getOrCreateBuoy("Top");
|
||||
Waypoint w1 = domainFactory.createWaypoint(startFinish);
|
||||
Waypoint w2 = domainFactory.createWaypoint(top);
|
||||
Waypoint w3 = domainFactory.createWaypoint(startFinish);
|
||||
Competitor competitor = new CompetitorImpl(123, "Test Competitor", new TeamImpl("STG", Collections.singleton(
|
||||
new PersonImpl("Test Competitor", new NationalityImpl("GER"),
|
||||
/* dateOfBirth */null, "This is famous " + "Test Competitor")), new PersonImpl("Rigo van Maas",
|
||||
new NationalityImpl("NED"),
|
||||
/* dateOfBirth */null, "This is Rigo, the coach")), new BoatImpl("Test Competitor" + "'s boat",
|
||||
new BoatClassImpl("505", /* typicallyStartsUpwind */true), null));
|
||||
final BoatClass boatClass = domainFactory.getOrCreateBoatClass("ESS40");
|
||||
DynamicTrackedRace trackedRace = new DynamicTrackedRaceImpl(new DynamicTrackedRegattaImpl(
|
||||
new RegattaImpl("Test Regatta", boatClass,
|
||||
/* trackedRegattaRegistry */ null, domainFactory.createScoringScheme(ScoringSchemeType.LOW_POINT))),
|
||||
new RaceDefinitionImpl("Test Race",
|
||||
new CourseImpl("Test Course", Arrays.asList(new Waypoint[] { w1, w2, w3 })),
|
||||
boatClass, Collections.singleton(competitor)),
|
||||
EmptyWindStore.INSTANCE, /* delayToLiveInMillis */ 1000,
|
||||
/* millisecondsOverWhichToAverageWind */ 30000,
|
||||
/* millisecondsOverWhichToAverageSpeed */ 30000);
|
||||
TimePoint start = MillisecondsTimePoint.now();
|
||||
TimePoint topMarkRounding = start.plus(30000);
|
||||
TimePoint finish = topMarkRounding.plus(30000);
|
||||
trackedRace.updateMarkPassings(competitor, Arrays.asList(new MarkPassing[] {
|
||||
new MarkPassingImpl(start, w1, competitor),
|
||||
new MarkPassingImpl(topMarkRounding, w2, competitor),
|
||||
new MarkPassingImpl(finish, w3, competitor)
|
||||
}));
|
||||
assertFalse(boatClass.typicallyStartsUpwind());
|
||||
assertNull(trackedRace.getEstimatedWindDirection(new DegreePosition(0, 0), MillisecondsTimePoint.now()));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -83,7 +83,8 @@ public class RaceCourseReceiver extends AbstractReceiverWithQueue<Route, RouteDa
|
||||
Course course = getDomainFactory().createCourse(event.getA().getName(), event.getB().getPoints());
|
||||
RaceDefinition existingRaceDefinitionForRace = getDomainFactory().getExistingRaceDefinitionForRace(event.getC());
|
||||
if (existingRaceDefinitionForRace != null) {
|
||||
logger.log(Level.INFO, "Received course update for existing race "+event.getC().getName());
|
||||
logger.log(Level.INFO, "Received course update for existing race "+event.getC().getName()+": "+
|
||||
event.getB().getPoints());
|
||||
// race already exists; this means that we obviously found a course re-definition (yuck...)
|
||||
// Therefore, don't create TrackedRace again because it already exists.
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.sap.sailing.domain.base;
|
||||
|
||||
import com.sap.sailing.domain.common.Named;
|
||||
import com.sap.sailing.domain.common.RaceIdentifier;
|
||||
import com.sap.sailing.domain.common.Renamable;
|
||||
import com.sap.sailing.domain.common.impl.Util;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.leaderboard.Leaderboard;
|
||||
@@ -25,7 +25,7 @@ import com.sap.sailing.util.impl.RaceColumnListeners;
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface RaceColumn extends Renamable {
|
||||
public interface RaceColumn extends Named {
|
||||
/**
|
||||
* @return the fleets for each of which this column has a single race and therefore optionally a {@link TrackedRace}, in
|
||||
* ascending order; best fleets first
|
||||
|
||||
@@ -11,6 +11,8 @@ public interface RaceColumnListener extends Serializable {
|
||||
|
||||
void isMedalRaceChanged(RaceColumn raceColumn, boolean newIsMedalRace);
|
||||
|
||||
boolean canAddRaceColumnToContainer(RaceColumn raceColumn);
|
||||
|
||||
void raceColumnAddedToContainer(RaceColumn raceColumn);
|
||||
|
||||
void raceColumnRemovedFromContainer(RaceColumn raceColumn);
|
||||
|
||||
+1
-13
@@ -14,10 +14,8 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
private static final long serialVersionUID = -7801617988982540470L;
|
||||
|
||||
private final Map<Fleet, TrackedRace> trackedRaces;
|
||||
private String name;
|
||||
private final Map<Fleet, RaceIdentifier> raceIdentifiers;
|
||||
public AbstractRaceColumn(String name) {
|
||||
this.name = name;
|
||||
public AbstractRaceColumn() {
|
||||
this.trackedRaces = new HashMap<Fleet, TrackedRace>();
|
||||
this.raceIdentifiers = new HashMap<Fleet, RaceIdentifier>();
|
||||
}
|
||||
@@ -49,16 +47,6 @@ public abstract class AbstractRaceColumn extends SimpleAbstractRaceColumn implem
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName) {
|
||||
this.name = newName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RaceIdentifier getRaceIdentifier(Fleet fleet) {
|
||||
return raceIdentifiers.get(fleet);
|
||||
|
||||
@@ -76,6 +76,14 @@ public class CourseImpl extends NamedImpl implements Course {
|
||||
public void unlockAfterRead() {
|
||||
LockUtil.unlockAfterRead(lock);
|
||||
}
|
||||
|
||||
public void lockForWrite() {
|
||||
LockUtil.lockForWrite(lock);
|
||||
}
|
||||
|
||||
public void unlockAfterWrite() {
|
||||
LockUtil.unlockAfterWrite(lock);
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||
ois.defaultReadObject();
|
||||
|
||||
+3
@@ -30,6 +30,7 @@ import com.sap.sailing.domain.common.TimePoint;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPoint;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPointExtremeSailingSeriesOverall;
|
||||
import com.sap.sailing.domain.leaderboard.impl.HighPointLastBreaksTie;
|
||||
import com.sap.sailing.domain.leaderboard.impl.LowPoint;
|
||||
import com.sap.sailing.domain.tracking.MarkPassing;
|
||||
import com.sap.sailing.domain.tracking.impl.MarkPassingImpl;
|
||||
@@ -237,6 +238,8 @@ public class DomainFactoryImpl implements DomainFactory {
|
||||
return new HighPoint();
|
||||
case HIGH_POINT_ESS_OVERALL:
|
||||
return new HighPointExtremeSailingSeriesOverall();
|
||||
case HIGH_POINT_LAST_BREAKS_TIE:
|
||||
return new HighPointLastBreaksTie();
|
||||
default:
|
||||
throw new RuntimeException("Unknown scoring scheme type "+scoringSchemeType.name());
|
||||
}
|
||||
|
||||
+7
-1
@@ -18,6 +18,7 @@ import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
public class RaceColumnInSeriesImpl extends AbstractRaceColumn implements RaceColumnInSeries {
|
||||
private static final long serialVersionUID = -2199678838624406645L;
|
||||
private final Series series;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Making this transient will leave it <code>null</code> on a replica. This, however, is OK because
|
||||
@@ -34,11 +35,16 @@ public class RaceColumnInSeriesImpl extends AbstractRaceColumn implements RaceCo
|
||||
* carried out.
|
||||
*/
|
||||
public RaceColumnInSeriesImpl(String name, Series series, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
super(name);
|
||||
this.name = name;
|
||||
this.series = series;
|
||||
this.trackedRegattaRegistry = trackedRegattaRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Regatta getRegatta() {
|
||||
return getSeries().getRegatta();
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.impl.NamedImpl;
|
||||
import com.sap.sailing.domain.leaderboard.ScoringScheme;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.util.impl.RaceColumnListeners;
|
||||
|
||||
@@ -48,6 +49,13 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
/**
|
||||
* Constructs a regatta with a single default series with empty race column list, and a single default fleet which
|
||||
* is not {@link #isPersistent() marked for persistence}.
|
||||
*
|
||||
* @param trackedRegattaRegistry
|
||||
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
|
||||
* in order to re-associate a {@link TrackedRace} passed to {@link #setTrackedRace(Fleet, TrackedRace)}
|
||||
* with this column's series' {@link TrackedRegatta}, and the tracked race's {@link RaceDefinition} with
|
||||
* this column's series {@link Regatta}, respectively. If <code>null</code>, the re-association won't be
|
||||
* carried out.
|
||||
*/
|
||||
public RegattaImpl(String baseName, BoatClass boatClass, TrackedRegattaRegistry trackedRegattaRegistry, ScoringScheme scoringScheme) {
|
||||
this(baseName, boatClass, Collections.singletonList(new SeriesImpl("Default", /* isMedal */false, Collections
|
||||
@@ -207,6 +215,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
|
||||
raceColumnListeners.notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
|
||||
return raceColumnListeners.canAddRaceColumnToContainer(raceColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
raceColumnListeners.notifyListenersAboutRaceColumnAddedToContainer(raceColumn);
|
||||
|
||||
@@ -10,11 +10,13 @@ import com.sap.sailing.domain.base.Fleet;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.RaceColumnInSeries;
|
||||
import com.sap.sailing.domain.base.RaceColumnListener;
|
||||
import com.sap.sailing.domain.base.RaceDefinition;
|
||||
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.tracking.TrackedRace;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegatta;
|
||||
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
|
||||
import com.sap.sailing.util.impl.RaceColumnListeners;
|
||||
|
||||
@@ -28,7 +30,14 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener
|
||||
private final RaceColumnListeners raceColumnListeners;
|
||||
|
||||
/**
|
||||
* @param fleets must be non-empty
|
||||
* @param fleets
|
||||
* must be non-empty
|
||||
* @param trackedRegattaRegistry
|
||||
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
|
||||
* in order to re-associate a {@link TrackedRace} passed to {@link #setTrackedRace(Fleet, TrackedRace)}
|
||||
* with this column's series' {@link TrackedRegatta}, and the tracked race's {@link RaceDefinition} with
|
||||
* this column's series {@link Regatta}, respectively. If <code>null</code>, the re-association won't be
|
||||
* carried out.
|
||||
*/
|
||||
public SeriesImpl(String name, boolean isMedal, Iterable<? extends Fleet> fleets, Iterable<String> raceColumnNames,
|
||||
TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
@@ -84,16 +93,36 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener
|
||||
public Iterable<? extends RaceColumnInSeries> getRaceColumns() {
|
||||
return raceColumns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param trackedRegattaRegistry
|
||||
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
|
||||
* in order to re-associate a {@link TrackedRace} passed to {@link #setTrackedRace(Fleet, TrackedRace)}
|
||||
* with this column's series' {@link TrackedRegatta}, and the tracked race's {@link RaceDefinition} with
|
||||
* this column's series {@link Regatta}, respectively. If <code>null</code>, the re-association won't be
|
||||
* carried out.
|
||||
*/
|
||||
@Override
|
||||
public RaceColumnInSeries addRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
final RaceColumnInSeriesImpl result = createRaceColumn(raceColumnName, trackedRegattaRegistry);
|
||||
result.addRaceColumnListener(this);
|
||||
raceColumns.add(result);
|
||||
raceColumnListeners.notifyListenersAboutRaceColumnAddedToContainer(result);
|
||||
RaceColumnInSeriesImpl result = createRaceColumn(raceColumnName, trackedRegattaRegistry);
|
||||
if (raceColumnListeners.canAddRaceColumnToContainer(result)) {
|
||||
result.addRaceColumnListener(this);
|
||||
raceColumns.add(result);
|
||||
raceColumnListeners.notifyListenersAboutRaceColumnAddedToContainer(result);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trackedRegattaRegistry
|
||||
* used to find the {@link TrackedRegatta} for this column's series' {@link Series#getRegatta() regatta}
|
||||
* in order to re-associate a {@link TrackedRace} passed to {@link #setTrackedRace(Fleet, TrackedRace)}
|
||||
* with this column's series' {@link TrackedRegatta}, and the tracked race's {@link RaceDefinition} with
|
||||
* this column's series {@link Regatta}, respectively. If <code>null</code>, the re-association won't be
|
||||
* carried out.
|
||||
*/
|
||||
private RaceColumnInSeriesImpl createRaceColumn(String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry) {
|
||||
RaceColumnInSeriesImpl result = new RaceColumnInSeriesImpl(raceColumnName, this, trackedRegattaRegistry);
|
||||
return result;
|
||||
@@ -174,6 +203,16 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener
|
||||
raceColumnListeners.notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace);
|
||||
}
|
||||
|
||||
/**
|
||||
* A series listens on its columns; individual columns, however, don't ask whether they can be added; the series itself does.
|
||||
*
|
||||
* @see #addRaceColumn(String, TrackedRegattaRegistry)
|
||||
*/
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
raceColumnListeners.notifyListenersAboutRaceColumnAddedToContainer(raceColumn);
|
||||
|
||||
+1
@@ -3,5 +3,6 @@ package com.sap.sailing.domain.leaderboard;
|
||||
import com.sap.sailing.domain.base.RaceColumn;
|
||||
|
||||
public interface FlexibleRaceColumn extends RaceColumn {
|
||||
void setName(String newName);
|
||||
void setIsMedalRace(boolean isMedalRace);
|
||||
}
|
||||
|
||||
@@ -261,11 +261,13 @@ public interface Leaderboard extends Named {
|
||||
* Tells if the column represented by <code>raceColumn</code> shall be considered when counting the number of "races
|
||||
* so far" for discarding. Although medal races are never discarded themselves, they still count in determining the
|
||||
* number of "races so far" which is then the basis for deciding how many races may be discarded. If a leaderboard
|
||||
* has corrections for a column then that column shall be considered for discarding and counts for determining the
|
||||
* number of races so far. Also, if a tracked race is connected to the column and has started already, the column is
|
||||
* to be considered for discarding.
|
||||
* has corrections for a column for the <code>competitor</code> then that column shall be considered for discarding
|
||||
* and counts for determining the number of races so far. Also, if a tracked race is connected to the column and has
|
||||
* started already, the column is to be considered for discarding unless the column has several unordered fleets and
|
||||
* not all fleets have started their race yet (see
|
||||
* {@link ScoringScheme#isValidInTotalScore(Leaderboard, RaceColumn, TimePoint)}).
|
||||
*/
|
||||
boolean considerForDiscarding(RaceColumn raceColumn, TimePoint timePoint);
|
||||
boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint);
|
||||
|
||||
public void setResultDiscardingRule(ThresholdBasedResultDiscardingRule discardingRule);
|
||||
|
||||
|
||||
+10
-1
@@ -9,6 +9,7 @@ import com.sap.sailing.domain.base.RaceColumn;
|
||||
import com.sap.sailing.domain.base.Regatta;
|
||||
import com.sap.sailing.domain.common.MaxPointsReason;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.domain.common.TimePoint;
|
||||
|
||||
/**
|
||||
* A leaderboard has a scoring scheme that decides how race ranks map to scores, how penalties are to be scored,
|
||||
@@ -79,7 +80,15 @@ public interface ScoringScheme extends Serializable {
|
||||
|
||||
/**
|
||||
* Usually, when all other sorting criteria end up in a tie, the last race sailed is used to decide.
|
||||
* @param nullScoresAreBetter TODO
|
||||
*/
|
||||
int compareByLastRace(List<Double> o1Scores, List<Double> o2Scores, boolean nullScoresAreBetter);
|
||||
|
||||
/**
|
||||
* Under certain circumstances, a scoring scheme may decide that the scores of a column are not (yet) to be used
|
||||
* for the leaderboard's total scores. This may, e.g., be the case if a column is split into more than one fleet and
|
||||
* those fleets are unordered. In that case, scores need to be available for all fleets before the column counts
|
||||
* for the total scores.
|
||||
* @param at TODO
|
||||
*/
|
||||
boolean isValidInTotalScore(Leaderboard leaderboard, RaceColumn raceColumn, TimePoint at);
|
||||
}
|
||||
|
||||
+62
-1
@@ -4,10 +4,20 @@ import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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.common.NoWindException;
|
||||
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.ScoringScheme;
|
||||
import com.sap.sailing.domain.tracking.TrackedRace;
|
||||
|
||||
public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
|
||||
private static final long serialVersionUID = 6830414905539642446L;
|
||||
@@ -58,6 +68,53 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
|
||||
public Comparator<Double> getScoreComparator(boolean nullScoresAreBetter) {
|
||||
return new ScoreComparator(nullScoresAreBetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidInTotalScore(Leaderboard leaderboard, RaceColumn raceColumn, TimePoint at) {
|
||||
boolean result;
|
||||
Iterable<? extends Fleet> fleets = raceColumn.getFleets();
|
||||
if (Util.size(fleets) <= 1 || allFleetsOrdered(fleets)) {
|
||||
result = true;
|
||||
} else {
|
||||
// multiple unordered fleets; ensure that the leaderboard has results for all of them
|
||||
result = leaderboardHasResultsForAllFleets(leaderboard, raceColumn, at);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean leaderboardHasResultsForAllFleets(Leaderboard leaderboard, RaceColumn raceColumn, TimePoint at) {
|
||||
Set<Fleet> fleetsForWhichNoScoreWasFound = new HashSet<Fleet>();
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
final TrackedRace trackedRaceForFleet = raceColumn.getTrackedRace(fleet);
|
||||
if (trackedRaceForFleet == null || !trackedRaceForFleet.hasStarted(at)) {
|
||||
fleetsForWhichNoScoreWasFound.add(fleet);
|
||||
}
|
||||
}
|
||||
for (Competitor competitor : leaderboard.getCompetitors()) {
|
||||
Fleet fleet = raceColumn.getFleetOfCompetitor(competitor);
|
||||
if (fleetsForWhichNoScoreWasFound.contains(fleet)) {
|
||||
try {
|
||||
if (leaderboard.getNetPoints(competitor, raceColumn, at) != null) {
|
||||
fleetsForWhichNoScoreWasFound.remove(fleet);
|
||||
}
|
||||
} catch (NoWindException nwe) {
|
||||
// can't occur here because no started tracked race exists yet for the competitor
|
||||
}
|
||||
}
|
||||
}
|
||||
return fleetsForWhichNoScoreWasFound.isEmpty();
|
||||
}
|
||||
|
||||
private boolean allFleetsOrdered(Iterable<? extends Fleet> fleets) {
|
||||
boolean allOrdered = true;
|
||||
for (Fleet fleet : fleets) {
|
||||
if (fleet.getOrdering() == 0) {
|
||||
allOrdered = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allOrdered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assuming both competitors scored in the same number of races, compares the sorted scores.
|
||||
@@ -91,6 +148,10 @@ public abstract class AbstractScoringSchemeImpl implements ScoringScheme {
|
||||
|
||||
@Override
|
||||
public int compareByLastRace(List<Double> o1Scores, List<Double> o2Scores, boolean nullScoresAreBetter) {
|
||||
return getScoreComparator(nullScoresAreBetter).compare(o1Scores.get(o1Scores.size()-1), o2Scores.get(o2Scores.size()-1));
|
||||
int result = 0;
|
||||
if (!o1Scores.isEmpty() && !o2Scores.isEmpty()) {
|
||||
result = getScoreComparator(nullScoresAreBetter).compare(o1Scores.get(o1Scores.size()-1), o2Scores.get(o2Scores.size()-1));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-15
@@ -242,9 +242,11 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
public Double getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException {
|
||||
double result = getCarriedPoints(competitor);
|
||||
for (RaceColumn r : getRaceColumns()) {
|
||||
final Double totalPoints = getTotalPoints(competitor, r, timePoint);
|
||||
if (totalPoints != null) {
|
||||
result += totalPoints;
|
||||
if (getScoringScheme().isValidInTotalScore(this, r, timePoint)) {
|
||||
final Double totalPoints = getTotalPoints(competitor, r, timePoint);
|
||||
if (totalPoints != null) {
|
||||
result += totalPoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -334,18 +336,12 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean considerForDiscarding(RaceColumn raceColumn, TimePoint timePoint) {
|
||||
boolean result = getScoreCorrection().hasCorrectionFor(raceColumn);
|
||||
if (!result && !raceColumn.isMedalRace()) {
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
|
||||
if (trackedRace != null && trackedRace.hasStarted(timePoint)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
public boolean countRaceForComparisonWithDiscardingThresholds(Competitor competitor, RaceColumn raceColumn, TimePoint timePoint) {
|
||||
TrackedRace trackedRaceForCompetitorInColumn;
|
||||
return getScoringScheme().isValidInTotalScore(this, raceColumn, timePoint) &&
|
||||
(getScoreCorrection().isScoreCorrected(competitor, raceColumn) ||
|
||||
((trackedRaceForCompetitorInColumn=raceColumn.getTrackedRace(competitor)) != null &&
|
||||
trackedRaceForCompetitorInColumn.hasStarted(timePoint)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,6 +418,21 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
|
||||
getRaceColumnListeners().notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace);
|
||||
}
|
||||
|
||||
/**
|
||||
* A leaderboard will only accept the addition of a race column if the column's name is unique across the leaderboard.
|
||||
*/
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn newRaceColumn) {
|
||||
boolean result = true;
|
||||
for (RaceColumn raceColumn : getRaceColumns()) {
|
||||
if (raceColumn.getName().equals(newRaceColumn.getName())) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(raceColumn);
|
||||
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
package com.sap.sailing.domain.leaderboard.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
|
||||
/**
|
||||
* In this variant of the {@link HighPoint}
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
*/
|
||||
public class HighPointLastBreaksTie extends HighPoint {
|
||||
private static final long serialVersionUID = -5338636946886101669L;
|
||||
|
||||
@Override
|
||||
public int compareByBetterScore(List<Double> o1Scores, List<Double> o2Scores, boolean nullScoresAreBetter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScoringSchemeType getType() {
|
||||
return ScoringSchemeType.HIGH_POINT_LAST_BREAKS_TIE;
|
||||
}
|
||||
}
|
||||
+27
-23
@@ -50,11 +50,13 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
private final ScoringScheme scoringScheme;
|
||||
private final Map<Pair<Competitor, RaceColumn>, Double> totalPointsCache;
|
||||
private final boolean nullScoresAreBetter;
|
||||
private final TimePoint timePoint;
|
||||
|
||||
public LeaderboardTotalRankComparator(Leaderboard leaderboard, TimePoint timePoint,
|
||||
ScoringScheme scoringScheme, boolean nullScoresAreBetter) throws NoWindException {
|
||||
super();
|
||||
this.leaderboard = leaderboard;
|
||||
this.timePoint = timePoint;
|
||||
this.scoringScheme = scoringScheme;
|
||||
this.nullScoresAreBetter = nullScoresAreBetter;
|
||||
totalPointsCache = new HashMap<Pair<Competitor, RaceColumn>, Double>();
|
||||
@@ -79,29 +81,31 @@ public class LeaderboardTotalRankComparator implements Comparator<Competitor> {
|
||||
Double o1MedalRaceScore = 0.0;
|
||||
Double o2MedalRaceScore = 0.0;
|
||||
for (RaceColumn raceColumn : getLeaderboard().getRaceColumns()) {
|
||||
int preemptiveColumnResult = 0;
|
||||
final Double o1Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o1, raceColumn));
|
||||
if (o1Score != null) {
|
||||
o1Scores.add(o1Score);
|
||||
o1ScoreSum += o1Score;
|
||||
}
|
||||
final Double o2Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o2, raceColumn));
|
||||
if (o2Score != null) {
|
||||
o2Scores.add(o2Score);
|
||||
o2ScoreSum += o2Score;
|
||||
}
|
||||
if (raceColumn.isMedalRace()) {
|
||||
o1MedalRaceScore = o1Score;
|
||||
o2MedalRaceScore = o2Score;
|
||||
// similar to compareByFleet, however, tracking is not required; having medal race column points
|
||||
// (tracked or manual) is sufficient
|
||||
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
|
||||
}
|
||||
if (preemptiveColumnResult == 0) {
|
||||
preemptiveColumnResult = compareByFleet(raceColumn, o1, o2);
|
||||
}
|
||||
if (preemptiveColumnResult != 0) {
|
||||
return preemptiveColumnResult;
|
||||
if (getLeaderboard().getScoringScheme().isValidInTotalScore(getLeaderboard(), raceColumn, timePoint)) {
|
||||
int preemptiveColumnResult = 0;
|
||||
final Double o1Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o1, raceColumn));
|
||||
if (o1Score != null) {
|
||||
o1Scores.add(o1Score);
|
||||
o1ScoreSum += o1Score;
|
||||
}
|
||||
final Double o2Score = totalPointsCache.get(new Pair<Competitor, RaceColumn>(o2, raceColumn));
|
||||
if (o2Score != null) {
|
||||
o2Scores.add(o2Score);
|
||||
o2ScoreSum += o2Score;
|
||||
}
|
||||
if (raceColumn.isMedalRace()) {
|
||||
o1MedalRaceScore = o1Score;
|
||||
o2MedalRaceScore = o2Score;
|
||||
// similar to compareByFleet, however, tracking is not required; having medal race column points
|
||||
// (tracked or manual) is sufficient
|
||||
preemptiveColumnResult = compareByMedalRaceParticipation(o1Score, o2Score);
|
||||
}
|
||||
if (preemptiveColumnResult == 0) {
|
||||
preemptiveColumnResult = compareByFleet(raceColumn, o1, o2);
|
||||
}
|
||||
if (preemptiveColumnResult != 0) {
|
||||
return preemptiveColumnResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now count the races in which they scored; if they scored in a different number of races, prefer the
|
||||
|
||||
+14
-2
@@ -10,7 +10,8 @@ import com.sap.sailing.domain.leaderboard.FlexibleRaceColumn;
|
||||
|
||||
public class RaceColumnImpl extends AbstractRaceColumn implements FlexibleRaceColumn {
|
||||
private static final long serialVersionUID = -7801617988982540470L;
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* All fleets for which this column can contain a race. This is the maximum set of keys possible for
|
||||
* {@link #trackedRaces} and {@link #raceIdentifiers}.
|
||||
@@ -19,7 +20,8 @@ public class RaceColumnImpl extends AbstractRaceColumn implements FlexibleRaceCo
|
||||
private boolean medalRace;
|
||||
|
||||
public RaceColumnImpl(String name, boolean medalRace, Iterable<Fleet> fleets) {
|
||||
super(name);
|
||||
super();
|
||||
this.name = name;
|
||||
this.medalRace = medalRace;
|
||||
List<Fleet> myFleets = new ArrayList<Fleet>();
|
||||
for (Fleet fleet : fleets) {
|
||||
@@ -29,6 +31,16 @@ public class RaceColumnImpl extends AbstractRaceColumn implements FlexibleRaceCo
|
||||
this.fleets = myFleets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName) {
|
||||
this.name = newName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMedalRace() {
|
||||
return medalRace;
|
||||
|
||||
+3
-3
@@ -51,7 +51,7 @@ public class ResultDiscardingRuleImpl implements ThresholdBasedResultDiscardingR
|
||||
|
||||
@Override
|
||||
public Set<RaceColumn> getDiscardedRaceColumns(final Competitor competitor, final Leaderboard leaderboard, final TimePoint timePoint) {
|
||||
int resultsToDiscard = getNumberOfResultsToDiscard(leaderboard.getRaceColumns(), leaderboard, timePoint);
|
||||
int resultsToDiscard = getNumberOfResultsToDiscard(competitor, leaderboard.getRaceColumns(), leaderboard, timePoint);
|
||||
Set<RaceColumn> result;
|
||||
if (resultsToDiscard > 0) {
|
||||
result = new HashSet<RaceColumn>();
|
||||
@@ -94,11 +94,11 @@ public class ResultDiscardingRuleImpl implements ThresholdBasedResultDiscardingR
|
||||
return result;
|
||||
}
|
||||
|
||||
private int getNumberOfResultsToDiscard(Iterable<RaceColumn> raceColumns, Leaderboard leaderboard, TimePoint timePoint) {
|
||||
private int getNumberOfResultsToDiscard(Competitor competitor, Iterable<RaceColumn> raceColumns, Leaderboard leaderboard, TimePoint timePoint) {
|
||||
int numberOfResultsToDiscard;
|
||||
int numberOfStartedRaces = 0;
|
||||
for (RaceColumn raceInLeaderboard : raceColumns) {
|
||||
if (leaderboard.considerForDiscarding(raceInLeaderboard, timePoint)) {
|
||||
if (leaderboard.countRaceForComparisonWithDiscardingThresholds(competitor, raceInLeaderboard, timePoint)) {
|
||||
numberOfStartedRaces++;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -95,10 +95,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String newName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseTrackedRace(Fleet fleet) {
|
||||
}
|
||||
@@ -118,6 +114,11 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
|
||||
getRaceColumnListeners().notifyListenersAboutIsMedalRaceChanged(raceColumn, newIsMedalRace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
|
||||
return getRaceColumnListeners().canAddRaceColumnToContainer(raceColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
getRaceColumnListeners().notifyListenersAboutRaceColumnAddedToContainer(raceColumn);
|
||||
|
||||
+6
-4
@@ -41,12 +41,14 @@ public class CombinedWindAsNavigableSet extends VirtualWindFixesAsNavigableSet {
|
||||
/**
|
||||
* Time point up to and including which the GPS fixes are considered in the race's tracks. Returns the value of
|
||||
* {@link #to} unless it is <code>null</code>. In this case, the time point of the
|
||||
* {@link TrackedRace#getEndOfRace() assumed end of race},
|
||||
* {@link #ceilingToResolution(Wind) ceiled to the resolution of this set} will be returned instead. If no valid
|
||||
* time of a newest event can be obtained from the race, <code>MillisecondsTimePoint(1)</code> is returned instead.
|
||||
* {@link TrackedRace#getEndOfRace() assumed end of race}, {@link #ceilingToResolution(Wind) ceiled to the
|
||||
* resolution of this set} will be considered instead. If no assumed end of race can be determined either, the time
|
||||
* point of the last event received so far is used. If no valid time of a newest event can be obtained from the
|
||||
* race, <code>MillisecondsTimePoint(1)</code> is returned instead.
|
||||
*/
|
||||
protected TimePoint getTo() {
|
||||
return getToInternal() == null ? getTrackedRace().getEndOfRace() == null ? new MillisecondsTimePoint(1)
|
||||
return getToInternal() == null ? getTrackedRace().getEndOfRace() == null ? getTrackedRace().getTimePointOfLastEvent() == null ?
|
||||
new MillisecondsTimePoint(1) : getTrackedRace().getTimePointOfLastEvent()
|
||||
: ceilingToResolution(getTrackedRace().getEndOfRace()) : getToInternal();
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -63,7 +63,6 @@ public class DynamicTrackedRaceImpl extends TrackedRaceImpl implements
|
||||
windSourcesToExclude.add(windSourceToExclude);
|
||||
}
|
||||
windSourcesToExclude.add(new WindSourceImpl(WindSourceType.COURSE_BASED));
|
||||
windSourcesToExclude.add(new WindSourceImpl(WindSourceType.TRACK_BASED_ESTIMATION));
|
||||
setWindSourcesToExclude(windSourcesToExclude);
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -794,6 +794,14 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
protected void invalidateValidityAndDistanceCaches(FixType gpsFix) {
|
||||
assertWriteLock();
|
||||
TimePoint distanceCacheInvalidationStart = gpsFix.getTimePoint();
|
||||
// see also bug 968: cache entries for intervals ending after the last fix need to be removed because they are
|
||||
// based on the last fix's position and don't extrapolate; now, with the new gpsFix, the positions between the last
|
||||
// and the new fix are defined by interpolation and hence differ from the previous assumption the competitor would have
|
||||
// stopped moving at the last fix.
|
||||
FixType last = getInternalFixes().lower(gpsFix);
|
||||
if (last != null) {
|
||||
distanceCacheInvalidationStart = last.getTimePoint().plus(1); // add one millisecond to invalidate *after* the last fix only
|
||||
}
|
||||
gpsFix.invalidateCache();
|
||||
Iterable<FixType> lowers = getEarlierFixesWhoseValidityMayBeAffected(gpsFix);
|
||||
for (FixType lower : lowers) {
|
||||
|
||||
+3
-3
@@ -1526,7 +1526,8 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
try {
|
||||
for (Competitor competitor : getRace().getCompetitors()) {
|
||||
TrackedLegOfCompetitor leg = getTrackedLeg(competitor, timePoint);
|
||||
if (leg != null) {
|
||||
// if bearings was set to null this indicates there was an exception; no need for further calculations, return null
|
||||
if (bearings != null && leg != null) {
|
||||
TrackedLeg trackedLeg = getTrackedLeg(leg.getLeg());
|
||||
LegType legType;
|
||||
try {
|
||||
@@ -1543,8 +1544,7 @@ public abstract class TrackedRaceImpl implements TrackedRace, CourseListener {
|
||||
if (estimatedSpeedWithConfidence != null
|
||||
&& estimatedSpeedWithConfidence.getObject() != null &&
|
||||
// Mark passings may be missing or far off. This can lead to boats apparently
|
||||
// going
|
||||
// "backwards" regarding the leg's direction; ignore those
|
||||
// going "backwards" regarding the leg's direction; ignore those
|
||||
isNavigatingForward(estimatedSpeedWithConfidence.getObject().getBearing(),
|
||||
trackedLeg, timePoint)) {
|
||||
// additionally to generally excluding maneuvers, reduce confidence around mark
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.sap.sailing.util.impl;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -16,25 +14,40 @@ public class LockUtil {
|
||||
private static final int NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK = 5;
|
||||
private static final Logger logger = Logger.getLogger(Util.class.getName());
|
||||
private static final Map<NamedReentrantReadWriteLock, TimePoint> lastTimeWriteLockWasObtained = new WeakHashMap<>();
|
||||
|
||||
/**
|
||||
* Bug <a href="http://bugs.sun.com/view_bug.do?bug_id=6822370">http://bugs.sun.com/view_bug.do?bug_id=6822370</a> seems
|
||||
* dangerous, particularly if it happens in a <code>LiveLeaderboardUpdater</code> thread. Even though the bug is reported to
|
||||
* have been fixed in JDK 7(b79) we should be careful. This method tries to acquire a lock, allowing for five seconds to pass.
|
||||
* After five seconds and not having retrieved the lock, tries again until the lock has been acquired.
|
||||
* @param lockParent TODO
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static void lock(Lock lock, String lockDescriptionForTimeoutLogMessage) {
|
||||
private static void lock(Lock lock, String lockDescriptionForTimeoutLogMessage, NamedReentrantReadWriteLock lockParent) {
|
||||
boolean locked = false;
|
||||
boolean interrupted = false;
|
||||
while (!locked) {
|
||||
try {
|
||||
locked = lock.tryLock(NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK, TimeUnit.SECONDS);
|
||||
if (!locked) {
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
new Throwable("This is where the lock couldn't be acquired").printStackTrace(new PrintStream(
|
||||
bos));
|
||||
logger.info("Couldn't acquire lock "+lockDescriptionForTimeoutLogMessage+" in "+NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK+"s at "+
|
||||
getCurrentStackTrace()+"Trying again...");
|
||||
StringBuilder message = new StringBuilder();
|
||||
message.append("Couldn't acquire lock ");
|
||||
message.append(lockDescriptionForTimeoutLogMessage);
|
||||
message.append(" in ");
|
||||
message.append(NUMBER_OF_SECONDS_TO_WAIT_FOR_LOCK);
|
||||
message.append("s at ");
|
||||
message.append(getCurrentStackTrace());
|
||||
Thread writer = lockParent.getWriter();
|
||||
if (writer != null) {
|
||||
message.append("\nThe current writer is:\n");
|
||||
appendThreadData(message, writer);
|
||||
}
|
||||
message.append("\nThe current readers are:\n");
|
||||
for (Thread reader : lockParent.getReaders()) {
|
||||
appendThreadData(message, reader);
|
||||
}
|
||||
message.append("Trying again...");
|
||||
logger.info(message.toString());
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
@@ -47,9 +60,16 @@ public class LockUtil {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendThreadData(StringBuilder message, Thread writer) {
|
||||
message.append(writer);
|
||||
message.append('\n');
|
||||
message.append(getStackTrace(writer));
|
||||
message.append('\n');
|
||||
}
|
||||
|
||||
public static void lockForRead(NamedReentrantReadWriteLock lock) {
|
||||
lock(lock.readLock(), "readLock "+lock.getName());
|
||||
lock(lock.readLock(), "readLock "+lock.getName(), lock);
|
||||
}
|
||||
|
||||
public static void unlockAfterRead(NamedReentrantReadWriteLock lock) {
|
||||
@@ -57,7 +77,7 @@ public class LockUtil {
|
||||
}
|
||||
|
||||
public static void lockForWrite(NamedReentrantReadWriteLock lock) {
|
||||
lock(lock.writeLock(), "writeLock "+lock.getName());
|
||||
lock(lock.writeLock(), "writeLock "+lock.getName(), lock);
|
||||
synchronized (lastTimeWriteLockWasObtained) {
|
||||
lastTimeWriteLockWasObtained.put(lock, MillisecondsTimePoint.now());
|
||||
}
|
||||
@@ -71,7 +91,7 @@ public class LockUtil {
|
||||
}
|
||||
if (timePointWriteLockWasObtained == null) {
|
||||
logger.info("Internal error: write lock "+lock.getName()+" to be unlocked but no time recorded for when it was last obtained.\n"+
|
||||
getCurrentStackTrace());
|
||||
"This is where the lock interaction happened:\n"+getCurrentStackTrace());
|
||||
} else {
|
||||
TimePoint now = MillisecondsTimePoint.now();
|
||||
if (now.asMillis()-timePointWriteLockWasObtained.asMillis() > 10000l) {
|
||||
@@ -81,12 +101,17 @@ public class LockUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getStackTrace(Thread thread) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (StackTraceElement sf : thread.getStackTrace()) {
|
||||
sb.append(sf.toString());
|
||||
sb.append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String getCurrentStackTrace() {
|
||||
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
new Throwable("This is where the lock interaction happened").printStackTrace(new PrintStream(
|
||||
bos));
|
||||
String stackTrace = new String(bos.toByteArray());
|
||||
return stackTrace;
|
||||
return getStackTrace(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
+152
-1
@@ -1,5 +1,12 @@
|
||||
package com.sap.sailing.util.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import com.sap.sailing.domain.common.Named;
|
||||
@@ -7,10 +14,136 @@ import com.sap.sailing.domain.common.Named;
|
||||
public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implements Named {
|
||||
private static final long serialVersionUID = 2906084982209339774L;
|
||||
private final String name;
|
||||
private final WriteLockWrapper writeLockWrapper;
|
||||
private final ReadLockWrapper readLockWrapper;
|
||||
private transient List<Thread> readers;
|
||||
|
||||
private class WriteLockWrapper extends WriteLock {
|
||||
private static final long serialVersionUID = -4234819025137348944L;
|
||||
private final WriteLock writeLock;
|
||||
|
||||
protected WriteLockWrapper(WriteLock writeLock) {
|
||||
super(NamedReentrantReadWriteLock.this);
|
||||
this.writeLock = writeLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
writeLock.lock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
writeLock.lockInterruptibly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
return writeLock.tryLock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return writeLock.tryLock(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock() {
|
||||
writeLock.unlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Condition newCondition() {
|
||||
return writeLock.newCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return writeLock.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHeldByCurrentThread() {
|
||||
return writeLock.isHeldByCurrentThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHoldCount() {
|
||||
return writeLock.getHoldCount();
|
||||
}
|
||||
}
|
||||
|
||||
private class ReadLockWrapper extends ReadLock {
|
||||
private static final long serialVersionUID = -4232071609936663619L;
|
||||
private final ReadLock readLock;
|
||||
|
||||
protected ReadLockWrapper(ReadLock readLock) {
|
||||
super(NamedReentrantReadWriteLock.this);
|
||||
this.readLock = readLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
readLock.lock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lockInterruptibly() throws InterruptedException {
|
||||
try {
|
||||
readLock.lockInterruptibly();
|
||||
readers.add(Thread.currentThread());
|
||||
} catch (InterruptedException ie) {
|
||||
throw ie;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
boolean result = readLock.tryLock();
|
||||
if (result) {
|
||||
readers.add(Thread.currentThread());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
boolean result = readLock.tryLock(timeout, unit);
|
||||
if (result) {
|
||||
readers.add(Thread.currentThread());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock() {
|
||||
readLock.unlock();
|
||||
readers.remove(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Condition newCondition() {
|
||||
return readLock.newCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return readLock.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public NamedReentrantReadWriteLock(String name, boolean fair) {
|
||||
super(fair);
|
||||
this.name = name;
|
||||
this.writeLockWrapper = new WriteLockWrapper(super.writeLock());
|
||||
this.readLockWrapper = new ReadLockWrapper(super.readLock());
|
||||
this.readers = Collections.synchronizedList(new ArrayList<Thread>());
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||
ois.defaultReadObject();
|
||||
this.readers = Collections.synchronizedList(new ArrayList<Thread>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -18,8 +151,26 @@ public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implemen
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WriteLock writeLock() {
|
||||
return writeLockWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadLock readLock() {
|
||||
return readLockWrapper;
|
||||
}
|
||||
|
||||
public List<Thread> getReaders() {
|
||||
return new ArrayList<Thread>(readers);
|
||||
}
|
||||
|
||||
public Thread getWriter() {
|
||||
return getOwner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReentrantReadWriteLock "+getName()+" ("+(isFair()?"fair":"unfair")+")";
|
||||
return "ReentrantReadWriteLock "+getName()+" ("+(isFair()?"fair":"unfair")+")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,4 +92,15 @@ public class RaceColumnListeners implements Serializable {
|
||||
return new HashSet<RaceColumnListener>(raceColumnListeners);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn columnToAdd) {
|
||||
boolean result = true;
|
||||
for (RaceColumnListener listener : getRaceColumnListeners()) {
|
||||
result = listener.canAddRaceColumnToContainer(columnToAdd);
|
||||
if (!result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -119,12 +119,9 @@ public class GwtTestCaseColumnToggling extends GWTTestCase {
|
||||
}
|
||||
|
||||
private void addColumnToLeaderboard() {
|
||||
leaderboardPanel = new LeaderboardPanelMock(service, LEADERBOARD_NAME,
|
||||
null, sc);
|
||||
|
||||
leaderboardPanel = new LeaderboardPanelMock(service, LEADERBOARD_NAME, null, sc);
|
||||
service.addColumnToLeaderboard(COLUMN1_NAME, LEADERBOARD_NAME, false,
|
||||
new AsyncCallback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
fail("Failed to add column to leaderboard.");
|
||||
@@ -134,7 +131,7 @@ public class GwtTestCaseColumnToggling extends GWTTestCase {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
System.out.println("Added column to leaderboard.");
|
||||
RaceColumnDTO race = new RaceColumnDTO();
|
||||
RaceColumnDTO race = new RaceColumnDTO(/* isValidInTotalScore */ null);
|
||||
race.name = COLUMN1_NAME;
|
||||
race.setMedalRace(false);
|
||||
leaderboardPanel.addColumn(leaderboardPanel.createRaceColumn(race));
|
||||
|
||||
@@ -21,5 +21,5 @@
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="com.google.gwt.dev.DevMode"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-war "${project_loc:com.sap.sailing.gwt.ui}" -noserver -remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -codeServerPort 9997 -startupUrl /gwt/AdminConsole.html com.sap.sailing.gwt.ui.AdminConsole -startupUrl /gwt/LeaderboardEditing.html com.sap.sailing.gwt.ui.LeaderboardEditing -startupUrl /gwt/UserManagement.html com.sap.sailing.gwt.ui.UserManagement -startupUrl /gwt/Leaderboard.html com.sap.sailing.gwt.ui.Leaderboard -startupUrl /gwt/Spectator.html com.sap.sailing.gwt.ui.Spectator -startupUrl /gwt/RaceBoard.html com.sap.sailing.gwt.ui.RaceBoard"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="com.sap.sailing.gwt.ui"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx1024m"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx2048m -XX:MaxPermSize=512m"/>
|
||||
</launchConfiguration>
|
||||
|
||||
+107
-108
@@ -1,108 +1,107 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
|
||||
public abstract class AbstractLeaderboardDialog extends DataEntryDialog<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringMessages;
|
||||
protected TextBox nameTextBox;
|
||||
protected LeaderboardDescriptor leaderboard;
|
||||
|
||||
protected LongBox[] discardThresholdBoxes;
|
||||
protected static final int MAX_NUMBER_OF_DISCARDED_RESULTS = 4;
|
||||
|
||||
public AbstractLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, StringMessages stringConstants,
|
||||
Validator<LeaderboardDescriptor> validator, AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, null, stringConstants.ok(), stringConstants.cancel(), validator, callback);
|
||||
this.stringMessages = stringConstants;
|
||||
this.leaderboard = leaderboardDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
int[] discardThresholdsBoxContents = getDiscardThresholds(discardThresholdBoxes);
|
||||
leaderboard.setName(nameTextBox.getValue());
|
||||
leaderboard.setDiscardThresholds(discardThresholdsBoxContents);
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
protected static int[] getDiscardThresholds(LongBox[] discardThresholdBoxes) {
|
||||
List<Integer> discardThresholds = new ArrayList<Integer>();
|
||||
// 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()) {
|
||||
scoringSchemeListBox2.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringMessages));
|
||||
}
|
||||
return scoringSchemeListBox2;
|
||||
}
|
||||
|
||||
protected static ScoringSchemeType getSelectedScoringSchemeType(ListBox scoringSchemeListBox, StringMessages stringMessages) {
|
||||
ScoringSchemeType result = null;
|
||||
int selIndex = scoringSchemeListBox.getSelectedIndex();
|
||||
if (selIndex >= 0) {
|
||||
String itemText = scoringSchemeListBox.getItemText(selIndex);
|
||||
for (ScoringSchemeType scoringSchemeType : ScoringSchemeType.values()) {
|
||||
if (ScoringSchemeTypeFormatter.format(scoringSchemeType, stringMessages).equals(itemText)) {
|
||||
result = scoringSchemeType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
|
||||
public abstract class AbstractLeaderboardDialog extends DataEntryDialog<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringMessages;
|
||||
protected TextBox nameTextBox;
|
||||
protected LeaderboardDescriptor leaderboard;
|
||||
|
||||
protected LongBox[] discardThresholdBoxes;
|
||||
protected static final int MAX_NUMBER_OF_DISCARDED_RESULTS = 4;
|
||||
|
||||
public AbstractLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, StringMessages stringConstants,
|
||||
Validator<LeaderboardDescriptor> validator, DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, null, stringConstants.ok(), stringConstants.cancel(), validator, callback);
|
||||
this.stringMessages = stringConstants;
|
||||
this.leaderboard = leaderboardDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
int[] discardThresholdsBoxContents = getDiscardThresholds(discardThresholdBoxes);
|
||||
leaderboard.setName(nameTextBox.getValue());
|
||||
leaderboard.setDiscardThresholds(discardThresholdsBoxContents);
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
protected static int[] getDiscardThresholds(LongBox[] discardThresholdBoxes) {
|
||||
List<Integer> discardThresholds = new ArrayList<Integer>();
|
||||
// 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()) {
|
||||
scoringSchemeListBox2.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringMessages));
|
||||
}
|
||||
return scoringSchemeListBox2;
|
||||
}
|
||||
|
||||
protected static ScoringSchemeType getSelectedScoringSchemeType(ListBox scoringSchemeListBox, StringMessages stringMessages) {
|
||||
ScoringSchemeType result = null;
|
||||
int selIndex = scoringSchemeListBox.getSelectedIndex();
|
||||
if (selIndex >= 0) {
|
||||
String itemText = scoringSchemeListBox.getItemText(selIndex);
|
||||
for (ScoringSchemeType scoringSchemeType : ScoringSchemeType.values()) {
|
||||
if (ScoringSchemeTypeFormatter.format(scoringSchemeType, stringMessages).equals(itemText)) {
|
||||
result = scoringSchemeType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-25
@@ -1,25 +1,24 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
|
||||
public class EventCreateDialog extends EventDialog {
|
||||
|
||||
public EventCreateDialog(Collection<EventDTO> existingEvents,
|
||||
StringMessages stringConstants, AsyncCallback<EventDTO> callback) {
|
||||
super(new EventParameterValidator(stringConstants, existingEvents),
|
||||
stringConstants, callback);
|
||||
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setWidth("200px");
|
||||
venueEntryField = createTextBox(null);
|
||||
venueEntryField.setWidth("200px");
|
||||
publicationUrlEntryField = createTextBox(null);
|
||||
publicationUrlEntryField.setWidth("200px");
|
||||
isPublicCheckBox = createCheckbox("");
|
||||
isPublicCheckBox.setValue(false);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
|
||||
public class EventCreateDialog extends EventDialog {
|
||||
|
||||
public EventCreateDialog(Collection<EventDTO> existingEvents,
|
||||
StringMessages stringConstants, DialogCallback<EventDTO> callback) {
|
||||
super(new EventParameterValidator(stringConstants, existingEvents),
|
||||
stringConstants, callback);
|
||||
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setWidth("200px");
|
||||
venueEntryField = createTextBox(null);
|
||||
venueEntryField.setWidth("200px");
|
||||
publicationUrlEntryField = createTextBox(null);
|
||||
publicationUrlEntryField.setWidth("200px");
|
||||
isPublicCheckBox = createCheckbox("");
|
||||
isPublicCheckBox.setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
+105
-106
@@ -1,106 +1,105 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
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.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.VenueDTO;
|
||||
|
||||
public class EventDialog extends DataEntryDialog<EventDTO> {
|
||||
protected StringMessages stringConstants;
|
||||
protected TextBox nameEntryField;
|
||||
protected TextBox venueEntryField;
|
||||
protected TextBox publicationUrlEntryField;
|
||||
protected CheckBox isPublicCheckBox;
|
||||
|
||||
protected static class EventParameterValidator implements Validator<EventDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<EventDTO> existingEvents;
|
||||
|
||||
public EventParameterValidator(StringMessages stringConstants, Collection<EventDTO> existingEvents) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingEvents = new ArrayList<EventDTO>(existingEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(EventDTO eventToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = eventToValidate.name != null && eventToValidate.name.length() > 0;
|
||||
boolean venueNotEmpty = eventToValidate.venue.name != null && eventToValidate.venue.name.length() > 0;
|
||||
|
||||
boolean unique = true;
|
||||
for (EventDTO event : existingEvents) {
|
||||
if (event.name.equals(eventToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!venueNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterNonEmptyVenue();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.eventWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public EventDialog(EventParameterValidator validator, StringMessages stringConstants,
|
||||
AsyncCallback<EventDTO> callback) {
|
||||
super(stringConstants.event(), null, stringConstants.ok(), stringConstants.cancel(), validator,
|
||||
callback);
|
||||
this.stringConstants = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EventDTO getResult() {
|
||||
EventDTO eventDTO = new EventDTO(nameEntryField.getText());
|
||||
eventDTO.venue = new VenueDTO(venueEntryField.getText());
|
||||
eventDTO.publicationUrl = publicationUrlEntryField.getText();
|
||||
eventDTO.isPublic = isPublicCheckBox.getValue();
|
||||
return eventDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
|
||||
Grid formGrid = new Grid(4, 2);
|
||||
panel.add(formGrid);
|
||||
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 0, new Label(stringConstants.venue() + ":"));
|
||||
formGrid.setWidget(1, 1, venueEntryField);
|
||||
formGrid.setWidget(2, 0, new Label(stringConstants.publicationUrl() + ":"));
|
||||
formGrid.setWidget(2, 1, publicationUrlEntryField);
|
||||
formGrid.setWidget(3, 0, new Label(stringConstants.isPublic() + ":"));
|
||||
formGrid.setWidget(3, 1, isPublicCheckBox);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
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.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.VenueDTO;
|
||||
|
||||
public class EventDialog extends DataEntryDialog<EventDTO> {
|
||||
protected StringMessages stringConstants;
|
||||
protected TextBox nameEntryField;
|
||||
protected TextBox venueEntryField;
|
||||
protected TextBox publicationUrlEntryField;
|
||||
protected CheckBox isPublicCheckBox;
|
||||
|
||||
protected static class EventParameterValidator implements Validator<EventDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<EventDTO> existingEvents;
|
||||
|
||||
public EventParameterValidator(StringMessages stringConstants, Collection<EventDTO> existingEvents) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingEvents = new ArrayList<EventDTO>(existingEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(EventDTO eventToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = eventToValidate.name != null && eventToValidate.name.length() > 0;
|
||||
boolean venueNotEmpty = eventToValidate.venue.name != null && eventToValidate.venue.name.length() > 0;
|
||||
|
||||
boolean unique = true;
|
||||
for (EventDTO event : existingEvents) {
|
||||
if (event.name.equals(eventToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!venueNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterNonEmptyVenue();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.eventWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public EventDialog(EventParameterValidator validator, StringMessages stringConstants,
|
||||
DialogCallback<EventDTO> callback) {
|
||||
super(stringConstants.event(), null, stringConstants.ok(), stringConstants.cancel(), validator,
|
||||
callback);
|
||||
this.stringConstants = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EventDTO getResult() {
|
||||
EventDTO eventDTO = new EventDTO(nameEntryField.getText());
|
||||
eventDTO.venue = new VenueDTO(venueEntryField.getText());
|
||||
eventDTO.publicationUrl = publicationUrlEntryField.getText();
|
||||
eventDTO.isPublic = isPublicCheckBox.getValue();
|
||||
return eventDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
|
||||
Grid formGrid = new Grid(4, 2);
|
||||
panel.add(formGrid);
|
||||
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 0, new Label(stringConstants.venue() + ":"));
|
||||
formGrid.setWidget(1, 1, venueEntryField);
|
||||
formGrid.setWidget(2, 0, new Label(stringConstants.publicationUrl() + ":"));
|
||||
formGrid.setWidget(2, 1, publicationUrlEntryField);
|
||||
formGrid.setWidget(3, 0, new Label(stringConstants.isPublic() + ":"));
|
||||
formGrid.setWidget(3, 1, isPublicCheckBox);
|
||||
return panel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
-24
@@ -1,24 +1,23 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
|
||||
public class EventEditDialog extends EventDialog {
|
||||
|
||||
public EventEditDialog(EventDTO event, Collection<EventDTO> otherExistingEvents,
|
||||
StringMessages stringConstants, AsyncCallback<EventDTO> callback) {
|
||||
super(new EventParameterValidator(stringConstants, otherExistingEvents), stringConstants, callback);
|
||||
|
||||
nameEntryField = createTextBox(event.name);
|
||||
nameEntryField.setWidth("200px");
|
||||
venueEntryField = createTextBox(event.venue.name);
|
||||
venueEntryField.setWidth("200px");
|
||||
publicationUrlEntryField = createTextBox(event.publicationUrl);
|
||||
publicationUrlEntryField.setWidth("200px");
|
||||
isPublicCheckBox = createCheckbox("");
|
||||
isPublicCheckBox.setValue(event.isPublic);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
|
||||
public class EventEditDialog extends EventDialog {
|
||||
|
||||
public EventEditDialog(EventDTO event, Collection<EventDTO> otherExistingEvents,
|
||||
StringMessages stringConstants, DialogCallback<EventDTO> callback) {
|
||||
super(new EventParameterValidator(stringConstants, otherExistingEvents), stringConstants, callback);
|
||||
|
||||
nameEntryField = createTextBox(event.name);
|
||||
nameEntryField.setWidth("200px");
|
||||
venueEntryField = createTextBox(event.venue.name);
|
||||
venueEntryField.setWidth("200px");
|
||||
publicationUrlEntryField = createTextBox(event.publicationUrl);
|
||||
publicationUrlEntryField.setWidth("200px");
|
||||
isPublicCheckBox = createCheckbox("");
|
||||
isPublicCheckBox.setValue(event.isPublic);
|
||||
}
|
||||
}
|
||||
|
||||
+18
-19
@@ -1,19 +1,18 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog {
|
||||
|
||||
public FlexibleLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback);
|
||||
nameTextBox = createTextBox(null);
|
||||
scoringSchemeListBox = createScoringSchemeListBox(this, stringMessages);
|
||||
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog {
|
||||
|
||||
public FlexibleLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback);
|
||||
nameTextBox = createTextBox(null);
|
||||
scoringSchemeListBox = createScoringSchemeListBox(this, stringMessages);
|
||||
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
|
||||
}
|
||||
}
|
||||
|
||||
+97
-98
@@ -1,98 +1,97 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
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.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialog {
|
||||
protected ListBox scoringSchemeListBox;
|
||||
|
||||
protected static class LeaderboardParameterValidator implements Validator<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringConstants;
|
||||
protected final Collection<StrippedLeaderboardDTO> existingLeaderboards;
|
||||
|
||||
public LeaderboardParameterValidator(StringMessages stringConstants, Collection<StrippedLeaderboardDTO> existingLeaderboards){
|
||||
super();
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingLeaderboards = existingLeaderboards;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
} else if(!unique){
|
||||
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
|
||||
} else if (!discardThresholdsAscending) {
|
||||
errorMessage = stringConstants.discardThresholdsMustBeAscending();
|
||||
} else {
|
||||
errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public FlexibleLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, LeaderboardParameterValidator validator, AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, leaderboardDTO, stringMessages, validator, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
LeaderboardDescriptor leaderboard = super.getResult();
|
||||
leaderboard.setRegattaName(null);
|
||||
leaderboard.setScoringScheme(getSelectedScoringSchemeType(scoringSchemeListBox, stringMessages));
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
Grid formGrid = new Grid(3,2);
|
||||
formGrid.setCellSpacing(3);
|
||||
formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameTextBox);
|
||||
formGrid.setWidget(1, 0, new Label(stringMessages.scoringSystem() + ":"));
|
||||
formGrid.setWidget(1, 1, scoringSchemeListBox);
|
||||
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(hp);
|
||||
return mainPanel;
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
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.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public abstract class FlexibleLeaderboardDialog extends AbstractLeaderboardDialog {
|
||||
protected ListBox scoringSchemeListBox;
|
||||
|
||||
protected static class LeaderboardParameterValidator implements Validator<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringConstants;
|
||||
protected final Collection<StrippedLeaderboardDTO> existingLeaderboards;
|
||||
|
||||
public LeaderboardParameterValidator(StringMessages stringConstants, Collection<StrippedLeaderboardDTO> existingLeaderboards){
|
||||
super();
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingLeaderboards = existingLeaderboards;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
} else if(!unique){
|
||||
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
|
||||
} else if (!discardThresholdsAscending) {
|
||||
errorMessage = stringConstants.discardThresholdsMustBeAscending();
|
||||
} else {
|
||||
errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public FlexibleLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, LeaderboardParameterValidator validator, DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, leaderboardDTO, stringMessages, validator, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
LeaderboardDescriptor leaderboard = super.getResult();
|
||||
leaderboard.setRegattaName(null);
|
||||
leaderboard.setScoringScheme(getSelectedScoringSchemeType(scoringSchemeListBox, stringMessages));
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
Grid formGrid = new Grid(3,2);
|
||||
formGrid.setCellSpacing(3);
|
||||
formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameTextBox);
|
||||
formGrid.setWidget(1, 0, new Label(stringMessages.scoringSystem() + ":"));
|
||||
formGrid.setWidget(1, 1, scoringSchemeListBox);
|
||||
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(hp);
|
||||
return mainPanel;
|
||||
}
|
||||
}
|
||||
|
||||
+33
-34
@@ -1,34 +1,33 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog {
|
||||
|
||||
public FlexibleLeaderboardEditDialog(Collection<StrippedLeaderboardDTO> otherExistingLeaderboards,
|
||||
LeaderboardDescriptor leaderboard, StringMessages stringConstants, ErrorReporter errorReporter,
|
||||
AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.editFlexibleLeaderboard(), leaderboard, stringConstants, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(
|
||||
stringConstants, otherExistingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(leaderboard.getName());
|
||||
|
||||
scoringSchemeListBox = createListBox(false);
|
||||
int j = 0;
|
||||
for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants));
|
||||
if(leaderboard.getScoringScheme() == scoringSchemeType) {
|
||||
scoringSchemeListBox.setSelectedIndex(j);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
scoringSchemeListBox.setEnabled(false);
|
||||
discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboard.getDiscardThresholds(), this);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.domain.common.ScoringSchemeType;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog {
|
||||
|
||||
public FlexibleLeaderboardEditDialog(Collection<StrippedLeaderboardDTO> otherExistingLeaderboards,
|
||||
LeaderboardDescriptor leaderboard, StringMessages stringConstants, ErrorReporter errorReporter,
|
||||
DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.editFlexibleLeaderboard(), leaderboard, stringConstants, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(
|
||||
stringConstants, otherExistingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(leaderboard.getName());
|
||||
|
||||
scoringSchemeListBox = createListBox(false);
|
||||
int j = 0;
|
||||
for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants));
|
||||
if(leaderboard.getScoringScheme() == scoringSchemeType) {
|
||||
scoringSchemeListBox.setSelectedIndex(j);
|
||||
}
|
||||
j++;
|
||||
}
|
||||
scoringSchemeListBox.setEnabled(false);
|
||||
discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboard.getDiscardThresholds(), this);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -14,6 +14,7 @@ import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
@@ -114,14 +115,14 @@ public class FregResultImportUrlPanel extends FlowPanel {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}, new AsyncCallback<String>() {
|
||||
}, new DialogCallback<String>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
// user cancelled; just don't add
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(String result) {
|
||||
public void ok(String result) {
|
||||
urlListBox.addItem(result);
|
||||
sailingService.addFragUrl(result, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
|
||||
+19
-18
@@ -47,6 +47,7 @@ import com.sap.sailing.domain.common.RegattaIdentifier;
|
||||
import com.sap.sailing.domain.common.RegattaName;
|
||||
import com.sap.sailing.domain.common.RegattaNameAndRaceName;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.ParallelExecutionCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ParallelExecutionHolder;
|
||||
@@ -248,13 +249,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
AbstractLeaderboardDialog dialog = new RegattaLeaderboardEditDialog(Collections
|
||||
.unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas),
|
||||
descriptor, stringMessages, errorReporter,
|
||||
new AsyncCallback<LeaderboardDescriptor>() {
|
||||
new DialogCallback<LeaderboardDescriptor>() {
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(LeaderboardDescriptor result) {
|
||||
public void ok(LeaderboardDescriptor result) {
|
||||
updateLeaderboard(oldLeaderboardName, result);
|
||||
}
|
||||
});
|
||||
@@ -264,13 +265,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
FlexibleLeaderboardEditDialog dialog = new FlexibleLeaderboardEditDialog(Collections
|
||||
.unmodifiableCollection(otherExistingLeaderboard),
|
||||
descriptor, stringMessages, errorReporter,
|
||||
new AsyncCallback<LeaderboardDescriptor>() {
|
||||
new DialogCallback<LeaderboardDescriptor>() {
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(LeaderboardDescriptor result) {
|
||||
public void ok(LeaderboardDescriptor result) {
|
||||
updateLeaderboard(oldLeaderboardName, result);
|
||||
}
|
||||
});
|
||||
@@ -693,13 +694,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
}
|
||||
existingRacesWithoutThisRace.remove(raceColumnWithFleet.getA());
|
||||
final RaceColumnInLeaderboardDialog raceDialog = new RaceColumnInLeaderboardDialog(existingRacesWithoutThisRace,
|
||||
raceColumnWithFleet.getA(), stringMessages, new AsyncCallback<RaceColumnDTO>() {
|
||||
raceColumnWithFleet.getA(), stringMessages, new DialogCallback<RaceColumnDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final RaceColumnDTO result) {
|
||||
public void ok(final RaceColumnDTO result) {
|
||||
final ParallelExecutionCallback<Void> renameLeaderboardColumnCallback = new ParallelExecutionCallback<Void>();
|
||||
final ParallelExecutionCallback<Void> updateIsMedalRaceCallback = new ParallelExecutionCallback<Void>();
|
||||
new ParallelExecutionHolder(renameLeaderboardColumnCallback, updateIsMedalRaceCallback) {
|
||||
@@ -748,13 +749,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
}
|
||||
|
||||
final RaceColumnsInLeaderboardDialog raceDialog = new RaceColumnsInLeaderboardDialog(existingRaceColumns,
|
||||
stringMessages, new AsyncCallback<List<RaceColumnDTO>>() {
|
||||
stringMessages, new DialogCallback<List<RaceColumnDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final List<RaceColumnDTO> result) {
|
||||
public void ok(final List<RaceColumnDTO> result) {
|
||||
updateRaceColumnsOfLeaderboard(leaderboardName, existingRaceColumns, result);
|
||||
}
|
||||
});
|
||||
@@ -838,13 +839,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
|
||||
private void createFlexibleLeaderboard() {
|
||||
AbstractLeaderboardDialog dialog = new FlexibleLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList),
|
||||
stringMessages, errorReporter, new AsyncCallback<LeaderboardDescriptor>() {
|
||||
stringMessages, errorReporter, new DialogCallback<LeaderboardDescriptor>() {
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final LeaderboardDescriptor newLeaderboard) {
|
||||
public void ok(final LeaderboardDescriptor newLeaderboard) {
|
||||
sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDiscardThresholds(),
|
||||
newLeaderboard.getScoringScheme(),
|
||||
new AsyncCallback<StrippedLeaderboardDTO>() {
|
||||
@@ -866,13 +867,13 @@ public class LeaderboardConfigPanel extends FormPanel implements RegattaDisplaye
|
||||
|
||||
private void createRegattaLeaderboard() {
|
||||
RegattaLeaderboardCreateDialog dialog = new RegattaLeaderboardCreateDialog(Collections.unmodifiableCollection(availableLeaderboardList),
|
||||
Collections.unmodifiableCollection(allRegattas), stringMessages, errorReporter, new AsyncCallback<LeaderboardDescriptor>() {
|
||||
Collections.unmodifiableCollection(allRegattas), stringMessages, errorReporter, new DialogCallback<LeaderboardDescriptor>() {
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final LeaderboardDescriptor newLeaderboard) {
|
||||
public void ok(final LeaderboardDescriptor newLeaderboard) {
|
||||
RegattaIdentifier regattaIdentifier = new RegattaName(newLeaderboard.getRegattaName());
|
||||
sailingService.createRegattaLeaderboard(regattaIdentifier, newLeaderboard.getDiscardThresholds(),
|
||||
new AsyncCallback<StrippedLeaderboardDTO>() {
|
||||
|
||||
+7
-6
@@ -37,6 +37,7 @@ import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SingleSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.AnchorCell;
|
||||
import com.sap.sailing.gwt.ui.client.AbstractRegattaPanel;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RegattaRefresher;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
@@ -450,11 +451,11 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
|
||||
final String oldGroupName = group.name;
|
||||
ArrayList<LeaderboardGroupDTO> otherExistingGroups = new ArrayList<LeaderboardGroupDTO>(availableLeaderboardGroups);
|
||||
otherExistingGroups.remove(group);
|
||||
LeaderboardGroupEditDialog dialog = new LeaderboardGroupEditDialog(group, otherExistingGroups, stringMessages, new AsyncCallback<LeaderboardGroupDTO>() {
|
||||
LeaderboardGroupEditDialog dialog = new LeaderboardGroupEditDialog(group, otherExistingGroups, stringMessages, new DialogCallback<LeaderboardGroupDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {}
|
||||
public void cancel() {}
|
||||
@Override
|
||||
public void onSuccess(LeaderboardGroupDTO group) {
|
||||
public void ok(LeaderboardGroupDTO group) {
|
||||
updateGroup(oldGroupName, group);
|
||||
}
|
||||
});
|
||||
@@ -557,11 +558,11 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel {
|
||||
private void addNewGroup() {
|
||||
LeaderboardGroupCreateDialog dialog = new LeaderboardGroupCreateDialog(
|
||||
Collections.unmodifiableCollection(availableLeaderboardGroups), stringMessages,
|
||||
new AsyncCallback<LeaderboardGroupDTO>() {
|
||||
new DialogCallback<LeaderboardGroupDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {}
|
||||
public void cancel() {}
|
||||
@Override
|
||||
public void onSuccess(LeaderboardGroupDTO newGroup) {
|
||||
public void ok(LeaderboardGroupDTO newGroup) {
|
||||
createNewGroup(newGroup);
|
||||
}
|
||||
});
|
||||
|
||||
+1
-2
@@ -2,14 +2,13 @@ package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
|
||||
|
||||
public class LeaderboardGroupCreateDialog extends LeaderboardGroupDialog {
|
||||
|
||||
public LeaderboardGroupCreateDialog(Collection<LeaderboardGroupDTO> existingGroups,
|
||||
StringMessages stringMessages, AsyncCallback<LeaderboardGroupDTO> callback) {
|
||||
StringMessages stringMessages, DialogCallback<LeaderboardGroupDTO> callback) {
|
||||
super(new LeaderboardGroupDTO(), stringMessages,
|
||||
callback, existingGroups);
|
||||
nameEntryField = createTextBox(null);
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ import java.util.List;
|
||||
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
@@ -94,7 +93,7 @@ public class LeaderboardGroupDialog extends DataEntryDialog<LeaderboardGroupDTO>
|
||||
}
|
||||
|
||||
public LeaderboardGroupDialog(LeaderboardGroupDTO group, StringMessages stringMessages,
|
||||
AsyncCallback<LeaderboardGroupDTO> callback, Collection<LeaderboardGroupDTO> existingLeaderboardGroups) {
|
||||
DialogCallback<LeaderboardGroupDTO> callback, Collection<LeaderboardGroupDTO> existingLeaderboardGroups) {
|
||||
super(stringMessages.leaderboardGroup(), null, stringMessages.ok(), stringMessages.cancel(),
|
||||
new LeaderboardGroupParameterValidator(stringMessages, existingLeaderboardGroups), callback);
|
||||
this.stringMessages = stringMessages;
|
||||
|
||||
+1
-2
@@ -2,14 +2,13 @@ package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
|
||||
|
||||
public class LeaderboardGroupEditDialog extends LeaderboardGroupDialog {
|
||||
public LeaderboardGroupEditDialog(LeaderboardGroupDTO group, Collection<LeaderboardGroupDTO> otherExistingGroups,
|
||||
StringMessages stringMessages, AsyncCallback<LeaderboardGroupDTO> callback) {
|
||||
StringMessages stringMessages, DialogCallback<LeaderboardGroupDTO> callback) {
|
||||
super(group, stringMessages, callback, otherExistingGroups);
|
||||
// don't allow editing the overall leaderboard's scoring scheme if the group already uses an overall leaderboard
|
||||
getOverallLeaderboardScoringSchemeListBox().setEnabled(!group.hasOverallLeaderboard());
|
||||
|
||||
+104
-105
@@ -1,105 +1,104 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
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.TextBox;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
|
||||
/**
|
||||
* Fills a {@link RaceColumnDTO} object by setting its {@link RaceColumnDTO#setMedalRace(boolean) medal race} property and its name.
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class RaceColumnInLeaderboardDialog extends DataEntryDialog<RaceColumnDTO> {
|
||||
private final TextBox raceNameBox;
|
||||
private final CheckBox isMedalRace;
|
||||
private final StringMessages stringConstants;
|
||||
|
||||
private RaceColumnDTO raceColumnToEdit;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<RaceColumnDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private List<RaceColumnDTO> existingRaces;
|
||||
|
||||
public RaceDialogValidator(StringMessages stringConstants, List<RaceColumnDTO> existingRaceColumnsAndFleetNames) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingRaces = existingRaceColumnsAndFleetNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(RaceColumnDTO valueToValidate) {
|
||||
String errorMessage;
|
||||
String racename = valueToValidate.getRaceColumnName();
|
||||
Boolean isMedalRace = valueToValidate.isMedalRace();
|
||||
boolean isNameNotEmpty = racename != null & racename != "";
|
||||
boolean medalRaceNotNull = isMedalRace != null;
|
||||
|
||||
boolean unique = true;
|
||||
for (RaceColumnDTO raceColumn : existingRaces) {
|
||||
if (raceColumn.getRaceColumnName().equals(valueToValidate.getRaceColumnName())) {
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isNameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!medalRaceNotNull) {
|
||||
errorMessage = stringConstants.medalRaceIsNull();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.raceWithThisNameAlreadyExists();
|
||||
} else {
|
||||
return errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public RaceColumnInLeaderboardDialog(List<RaceColumnDTO> existingRaces, RaceColumnDTO raceColumnToEdit,
|
||||
StringMessages stringConstants, AsyncCallback<RaceColumnDTO> callback) {
|
||||
super(stringConstants.actionRaceEdit(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(stringConstants, existingRaces), callback);
|
||||
this.raceColumnToEdit = raceColumnToEdit;
|
||||
this.stringConstants = stringConstants;
|
||||
raceNameBox = createTextBox(raceColumnToEdit.getRaceColumnName());
|
||||
isMedalRace = createCheckbox(stringConstants.medalRace());
|
||||
isMedalRace.setValue(raceColumnToEdit.isMedalRace());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RaceColumnDTO getResult() {
|
||||
raceColumnToEdit.name = raceNameBox.getValue();
|
||||
raceColumnToEdit.setMedalRace(isMedalRace.getValue());
|
||||
return raceColumnToEdit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
|
||||
HorizontalPanel raceNamePanel = new HorizontalPanel();
|
||||
raceNamePanel.setSpacing(3);
|
||||
mainPanel.add(raceNamePanel);
|
||||
raceNamePanel.add(new Label(stringConstants.name() + ":"));
|
||||
raceNamePanel.add(raceNameBox);
|
||||
alignAllPanelWidgetsVertically(raceNamePanel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
|
||||
mainPanel.add(isMedalRace);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
raceNameBox.setFocus(true);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
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.TextBox;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
|
||||
/**
|
||||
* Fills a {@link RaceColumnDTO} object by setting its {@link RaceColumnDTO#setMedalRace(boolean) medal race} property and its name.
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public class RaceColumnInLeaderboardDialog extends DataEntryDialog<RaceColumnDTO> {
|
||||
private final TextBox raceNameBox;
|
||||
private final CheckBox isMedalRace;
|
||||
private final StringMessages stringConstants;
|
||||
|
||||
private RaceColumnDTO raceColumnToEdit;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<RaceColumnDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private List<RaceColumnDTO> existingRaces;
|
||||
|
||||
public RaceDialogValidator(StringMessages stringConstants, List<RaceColumnDTO> existingRaceColumnsAndFleetNames) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingRaces = existingRaceColumnsAndFleetNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(RaceColumnDTO valueToValidate) {
|
||||
String errorMessage;
|
||||
String racename = valueToValidate.getRaceColumnName();
|
||||
Boolean isMedalRace = valueToValidate.isMedalRace();
|
||||
boolean isNameNotEmpty = racename != null & racename != "";
|
||||
boolean medalRaceNotNull = isMedalRace != null;
|
||||
|
||||
boolean unique = true;
|
||||
for (RaceColumnDTO raceColumn : existingRaces) {
|
||||
if (raceColumn.getRaceColumnName().equals(valueToValidate.getRaceColumnName())) {
|
||||
unique = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isNameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!medalRaceNotNull) {
|
||||
errorMessage = stringConstants.medalRaceIsNull();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.raceWithThisNameAlreadyExists();
|
||||
} else {
|
||||
return errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public RaceColumnInLeaderboardDialog(List<RaceColumnDTO> existingRaces, RaceColumnDTO raceColumnToEdit,
|
||||
StringMessages stringConstants, DialogCallback<RaceColumnDTO> callback) {
|
||||
super(stringConstants.actionRaceEdit(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(stringConstants, existingRaces), callback);
|
||||
this.raceColumnToEdit = raceColumnToEdit;
|
||||
this.stringConstants = stringConstants;
|
||||
raceNameBox = createTextBox(raceColumnToEdit.getRaceColumnName());
|
||||
isMedalRace = createCheckbox(stringConstants.medalRace());
|
||||
isMedalRace.setValue(raceColumnToEdit.isMedalRace());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RaceColumnDTO getResult() {
|
||||
raceColumnToEdit.name = raceNameBox.getValue();
|
||||
raceColumnToEdit.setMedalRace(isMedalRace.getValue());
|
||||
return raceColumnToEdit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
|
||||
HorizontalPanel raceNamePanel = new HorizontalPanel();
|
||||
raceNamePanel.setSpacing(3);
|
||||
mainPanel.add(raceNamePanel);
|
||||
raceNamePanel.add(new Label(stringConstants.name() + ":"));
|
||||
raceNamePanel.add(raceNameBox);
|
||||
alignAllPanelWidgetsVertically(raceNamePanel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
|
||||
mainPanel.add(isMedalRace);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
raceNameBox.setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
+331
-313
@@ -1,313 +1,331 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
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.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class RaceColumnInRegattaSeriesDialog extends DataEntryDialog<Pair<SeriesDTO, List<RaceColumnDTO>>> {
|
||||
private final RegattaDTO regatta;
|
||||
private final ListBox seriesListBox;
|
||||
private final ListBox addRacesListBox;
|
||||
private Button addRacesBtn;
|
||||
private final List<TextBox> raceNameEntryFields;
|
||||
private final List<Button> raceNameDeleteButtons;
|
||||
private final StringMessages stringMessages;
|
||||
private final TextBox raceNamePrefixTextBox;
|
||||
private final boolean hasOneSeries;
|
||||
private Grid raceColumnsGrid;
|
||||
private VerticalPanel additionalWidgetPanel;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<Pair<SeriesDTO, List<RaceColumnDTO>>> {
|
||||
private StringMessages stringConstants;
|
||||
|
||||
public RaceDialogValidator(RegattaDTO regatta, StringMessages stringConstants) {
|
||||
this.stringConstants = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(Pair<SeriesDTO, List<RaceColumnDTO>> valueToValidate) {
|
||||
String errorMessage = null;
|
||||
|
||||
SeriesDTO series = valueToValidate.getA();
|
||||
if(series == null) {
|
||||
errorMessage = "You must select a series";
|
||||
}
|
||||
|
||||
if(errorMessage == null) {
|
||||
List<RaceColumnDTO> raceColumnsToValidate = valueToValidate.getB();
|
||||
int index = 0;
|
||||
boolean raceColumnNameNotEmpty = true;
|
||||
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
raceColumnNameNotEmpty = raceColumn.name != null && raceColumn.name.length() > 0;
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
boolean raceColumnUnique = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
if (!setToFindDuplicates.add(raceColumn.name)) {
|
||||
raceColumnUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
errorMessage = stringConstants.race() + " " + (index + 1) + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!raceColumnUnique) {
|
||||
errorMessage = stringConstants.race() + " " + (index2 + 1) + ": "
|
||||
+ stringConstants.raceWithThisNameAlreadyExists();
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RaceColumnInRegattaSeriesDialog(RegattaDTO regatta, StringMessages stringConstants,
|
||||
AsyncCallback<Pair<SeriesDTO, List<RaceColumnDTO>>> callback) {
|
||||
super(stringConstants.actionEditRaces(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(regatta, stringConstants), callback);
|
||||
this.regatta = regatta;
|
||||
this.stringMessages = stringConstants;
|
||||
this.hasOneSeries = regatta.series.size() == 1;
|
||||
seriesListBox = createListBox(false);
|
||||
addRacesListBox = createListBox(false);
|
||||
raceNamePrefixTextBox = createTextBox(null);
|
||||
raceNameEntryFields = new ArrayList<TextBox>();
|
||||
raceNameDeleteButtons = new ArrayList<Button>();
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
private Widget createRaceNameWidget(String defaultName, boolean enabled) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(40);
|
||||
textBox.setEnabled(enabled);
|
||||
raceNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createRaceNameDeleteButtonWidget() {
|
||||
final Button raceNameDeleteBtn = new Button(stringMessages.delete());
|
||||
raceNameDeleteBtn.addStyleName("inlineButton");
|
||||
raceNameDeleteButtons.add(raceNameDeleteBtn);
|
||||
raceNameDeleteBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
int index = 0;
|
||||
for(Button btn: raceNameDeleteButtons) {
|
||||
if(raceNameDeleteBtn == btn) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
raceNameEntryFields.remove(index);
|
||||
raceNameDeleteButtons.remove(index);
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
}
|
||||
});
|
||||
return raceNameDeleteBtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<SeriesDTO, List<RaceColumnDTO>> getResult() {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
List<RaceColumnDTO> races = new ArrayList<RaceColumnDTO>();
|
||||
int racesCount = raceNameEntryFields.size();
|
||||
for(int i = 0; i < racesCount; i++) {
|
||||
String raceColumnName = raceNameEntryFields.get(i).getValue();
|
||||
RaceColumnDTO raceColumnDTO = findRaceColumnInSeriesByName(selectedSeries, raceColumnName);
|
||||
if(raceColumnDTO == null) {
|
||||
raceColumnDTO = new RaceColumnDTO();
|
||||
raceColumnDTO.name = raceColumnName;
|
||||
}
|
||||
races.add(raceColumnDTO);
|
||||
}
|
||||
return new Pair<SeriesDTO, List<RaceColumnDTO>>(selectedSeries, races);
|
||||
}
|
||||
|
||||
private RaceColumnDTO findRaceColumnInSeriesByName(SeriesDTO series, String raceColumnName) {
|
||||
RaceColumnDTO result = null;
|
||||
if(series != null) {
|
||||
for(RaceColumnDTO raceColumn: series.getRaceColumns()) {
|
||||
if(raceColumn.name.equals(raceColumnName)) {
|
||||
result = raceColumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
additionalWidgetPanel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
additionalWidgetPanel.add(additionalWidget);
|
||||
}
|
||||
|
||||
HorizontalPanel seriesPanel = new HorizontalPanel();
|
||||
seriesPanel.setSpacing(3);
|
||||
seriesPanel.add(new Label(stringMessages.series() + ":"));
|
||||
if(hasOneSeries) {
|
||||
String seriesName = regatta.series.get(0).name;
|
||||
seriesListBox.addItem(seriesName);
|
||||
seriesListBox.setSelectedIndex(0);
|
||||
if("Default".equals(seriesName)) {
|
||||
raceNamePrefixTextBox.setText("R");
|
||||
} else {
|
||||
raceNamePrefixTextBox.setText(seriesName.substring(0, 1).toUpperCase());
|
||||
}
|
||||
} else {
|
||||
seriesListBox.addItem("Please select a series");
|
||||
for (SeriesDTO series : regatta.series) {
|
||||
seriesListBox.addItem(series.name);
|
||||
}
|
||||
}
|
||||
|
||||
seriesListBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
if(selectedSeries == null) {
|
||||
raceNamePrefixTextBox.setText("");
|
||||
} else {
|
||||
raceNamePrefixTextBox.setText(selectedSeries.name.substring(0, 1).toUpperCase());
|
||||
}
|
||||
fillExistingRacesOfSeries();
|
||||
}
|
||||
});
|
||||
|
||||
seriesPanel.add(seriesListBox);
|
||||
additionalWidgetPanel.add(seriesPanel);
|
||||
|
||||
// add races controls
|
||||
HorizontalPanel addRacesPanel = new HorizontalPanel();
|
||||
addRacesPanel.setSpacing(3);
|
||||
addRacesPanel.add(new Label(stringMessages.add()));
|
||||
addRacesPanel.add(addRacesListBox);
|
||||
for(int i = 1; i <= 10; i++) {
|
||||
addRacesListBox.addItem("" + i);
|
||||
}
|
||||
addRacesListBox.setSelectedIndex(0);
|
||||
raceNamePrefixTextBox.setWidth("20px");
|
||||
addRacesPanel.add(raceNamePrefixTextBox);
|
||||
addRacesBtn = new Button(stringMessages.add());
|
||||
addRacesBtn.addStyleName("inlineButton");
|
||||
addRacesBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
if(selectedSeries != null) {
|
||||
String racePrefix = raceNamePrefixTextBox.getText();
|
||||
int racesCountToCreate = addRacesListBox.getSelectedIndex()+1;
|
||||
int currentSize = raceNameEntryFields.size();
|
||||
for(int i = 1; i <= racesCountToCreate; i++) {
|
||||
String raceName = racePrefix;
|
||||
if(racesCountToCreate != 1 || selectedSeries.getRaceColumns().size() > 0) {
|
||||
raceName += (currentSize + i);
|
||||
}
|
||||
createRaceNameWidget(raceName, true);
|
||||
createRaceNameDeleteButtonWidget();
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
} else {
|
||||
Window.alert("Please select a series first.");
|
||||
}
|
||||
}
|
||||
});
|
||||
addRacesPanel.add(addRacesBtn);
|
||||
additionalWidgetPanel.add(addRacesPanel);
|
||||
|
||||
additionalWidgetPanel.add(createHeadlineLabel(stringMessages.races()));
|
||||
additionalWidgetPanel.add(raceColumnsGrid);
|
||||
|
||||
if(hasOneSeries) {
|
||||
fillExistingRacesOfSeries();
|
||||
}
|
||||
|
||||
return additionalWidgetPanel;
|
||||
}
|
||||
|
||||
private void fillExistingRacesOfSeries() {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
raceNameEntryFields.clear();
|
||||
raceNameDeleteButtons.clear();
|
||||
if(selectedSeries != null && !selectedSeries.getRaceColumns().isEmpty()) {
|
||||
for(RaceColumnDTO raceColumn: selectedSeries.getRaceColumns()) {
|
||||
createRaceNameWidget(raceColumn.name, false);
|
||||
createRaceNameDeleteButtonWidget();
|
||||
}
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
}
|
||||
|
||||
private void updateRaceColumnsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(raceColumnsGrid);
|
||||
parentPanel.remove(raceColumnsGrid);
|
||||
int raceNamesCount = raceNameEntryFields.size();
|
||||
if(raceNamesCount > 0) {
|
||||
raceColumnsGrid = new Grid(raceNamesCount + 1, 3);
|
||||
raceColumnsGrid.setCellSpacing(4);
|
||||
raceColumnsGrid.setHTML(0, 0, stringMessages.name());
|
||||
for(int i = 0; i < raceNamesCount; i++) {
|
||||
raceColumnsGrid.setWidget(i+1, 0, raceNameEntryFields.get(i));
|
||||
raceColumnsGrid.setWidget(i+1, 1, raceNameDeleteButtons.get(i));
|
||||
}
|
||||
} else {
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
parentPanel.insert(raceColumnsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
private SeriesDTO getSelectedSeries() {
|
||||
SeriesDTO result = null;
|
||||
int selIndex = seriesListBox.getSelectedIndex();
|
||||
if(selIndex > 0 || hasOneSeries) { // the zero index represents the 'no selection' text
|
||||
String itemText = seriesListBox.getItemText(selIndex);
|
||||
for(SeriesDTO seriesDTO: regatta.series) {
|
||||
if(seriesDTO.name.equals(itemText)) {
|
||||
result = seriesDTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
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.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class RaceColumnInRegattaSeriesDialog extends DataEntryDialog<Pair<SeriesDTO, List<RaceColumnDTO>>> {
|
||||
private final RegattaDTO regatta;
|
||||
private final ListBox seriesListBox;
|
||||
private final ListBox addRacesListBox;
|
||||
private Button addRacesBtn;
|
||||
private final List<TextBox> raceNameEntryFields;
|
||||
private final List<Button> raceNameDeleteButtons;
|
||||
private final StringMessages stringMessages;
|
||||
private final TextBox raceNamePrefixTextBox;
|
||||
private final boolean hasOneSeries;
|
||||
private Grid raceColumnsGrid;
|
||||
private VerticalPanel additionalWidgetPanel;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<Pair<SeriesDTO, List<RaceColumnDTO>>> {
|
||||
private StringMessages stringConstants;
|
||||
private RegattaDTO regatta;
|
||||
|
||||
public RaceDialogValidator(RegattaDTO regatta, StringMessages stringConstants) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.regatta = regatta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(Pair<SeriesDTO, List<RaceColumnDTO>> valueToValidate) {
|
||||
Set<String> raceColumnNamesOfOtherSeries = new HashSet<String>();
|
||||
SeriesDTO seriesToValidate = valueToValidate.getA();
|
||||
List<RaceColumnDTO> raceColumnsToValidate = valueToValidate.getB();
|
||||
|
||||
String errorMessage = null;
|
||||
if(seriesToValidate == null) {
|
||||
errorMessage = stringConstants.pleaseSelectASeries();
|
||||
} else {
|
||||
for (SeriesDTO seriesDTO: regatta.series) {
|
||||
if(!seriesDTO.name.equals(seriesToValidate.name)) {
|
||||
for(RaceColumnDTO raceColumn: seriesDTO.getRaceColumns()) {
|
||||
raceColumnNamesOfOtherSeries.add(raceColumn.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean raceColumnNameNotEmpty = true;
|
||||
RaceColumnDTO wrongRaceColumn = null;
|
||||
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
raceColumnNameNotEmpty = raceColumn.name != null && raceColumn.name.length() > 0;
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
wrongRaceColumn = raceColumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean raceColumnUniqueInSeries = true;
|
||||
boolean raceColumnUniqueInRegatta = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
if (!setToFindDuplicates.add(raceColumn.name)) {
|
||||
raceColumnUniqueInSeries = false;
|
||||
wrongRaceColumn = raceColumn;
|
||||
break;
|
||||
} else if(raceColumnNamesOfOtherSeries.contains(raceColumn.name)) {
|
||||
raceColumnUniqueInRegatta = false;
|
||||
wrongRaceColumn = raceColumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
errorMessage = stringConstants.race() + " " + wrongRaceColumn.name + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!raceColumnUniqueInSeries) {
|
||||
errorMessage = stringConstants.race() + " " + wrongRaceColumn.name + ": "
|
||||
+ stringConstants.raceWithThisNameAlreadyExists();
|
||||
} else if (!raceColumnUniqueInRegatta) {
|
||||
errorMessage = stringConstants.race() + " " + wrongRaceColumn.name + ": "
|
||||
+ stringConstants.raceWithThisNameAlreadyExistsInRegatta();
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RaceColumnInRegattaSeriesDialog(RegattaDTO regatta, StringMessages stringConstants,
|
||||
DialogCallback<Pair<SeriesDTO, List<RaceColumnDTO>>> callback) {
|
||||
super(stringConstants.actionEditRaces(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(regatta, stringConstants), callback);
|
||||
this.regatta = regatta;
|
||||
this.stringMessages = stringConstants;
|
||||
this.hasOneSeries = regatta.series.size() == 1;
|
||||
seriesListBox = createListBox(false);
|
||||
addRacesListBox = createListBox(false);
|
||||
raceNamePrefixTextBox = createTextBox(null);
|
||||
raceNameEntryFields = new ArrayList<TextBox>();
|
||||
raceNameDeleteButtons = new ArrayList<Button>();
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
private Widget createRaceNameWidget(String defaultName, boolean enabled) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(40);
|
||||
textBox.setEnabled(enabled);
|
||||
raceNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createRaceNameDeleteButtonWidget() {
|
||||
final Button raceNameDeleteBtn = new Button(stringMessages.delete());
|
||||
raceNameDeleteBtn.addStyleName("inlineButton");
|
||||
raceNameDeleteButtons.add(raceNameDeleteBtn);
|
||||
raceNameDeleteBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
int index = 0;
|
||||
for(Button btn: raceNameDeleteButtons) {
|
||||
if(raceNameDeleteBtn == btn) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
raceNameEntryFields.remove(index);
|
||||
raceNameDeleteButtons.remove(index);
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
validate();
|
||||
}
|
||||
});
|
||||
return raceNameDeleteBtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<SeriesDTO, List<RaceColumnDTO>> getResult() {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
List<RaceColumnDTO> races = new ArrayList<RaceColumnDTO>();
|
||||
int racesCount = raceNameEntryFields.size();
|
||||
for(int i = 0; i < racesCount; i++) {
|
||||
String raceColumnName = raceNameEntryFields.get(i).getValue();
|
||||
RaceColumnDTO raceColumnDTO = findRaceColumnInSeriesByName(selectedSeries, raceColumnName);
|
||||
if(raceColumnDTO == null) {
|
||||
raceColumnDTO = new RaceColumnDTO(/* isValidInTotalScore not relevant here; not in scope of a leaderboard */ null);
|
||||
raceColumnDTO.name = raceColumnName;
|
||||
}
|
||||
races.add(raceColumnDTO);
|
||||
}
|
||||
return new Pair<SeriesDTO, List<RaceColumnDTO>>(selectedSeries, races);
|
||||
}
|
||||
|
||||
private RaceColumnDTO findRaceColumnInSeriesByName(SeriesDTO series, String raceColumnName) {
|
||||
RaceColumnDTO result = null;
|
||||
if(series != null) {
|
||||
for(RaceColumnDTO raceColumn: series.getRaceColumns()) {
|
||||
if(raceColumn.name.equals(raceColumnName)) {
|
||||
result = raceColumn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
additionalWidgetPanel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
additionalWidgetPanel.add(additionalWidget);
|
||||
}
|
||||
|
||||
HorizontalPanel seriesPanel = new HorizontalPanel();
|
||||
seriesPanel.setSpacing(3);
|
||||
seriesPanel.add(new Label(stringMessages.series() + ":"));
|
||||
if(hasOneSeries) {
|
||||
String seriesName = regatta.series.get(0).name;
|
||||
seriesListBox.addItem(seriesName);
|
||||
seriesListBox.setSelectedIndex(0);
|
||||
if("Default".equals(seriesName)) {
|
||||
raceNamePrefixTextBox.setText("R");
|
||||
} else {
|
||||
raceNamePrefixTextBox.setText(seriesName.substring(0, 1).toUpperCase());
|
||||
}
|
||||
} else {
|
||||
seriesListBox.addItem("Please select a series");
|
||||
for (SeriesDTO series : regatta.series) {
|
||||
seriesListBox.addItem(series.name);
|
||||
}
|
||||
}
|
||||
|
||||
seriesListBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
if(selectedSeries == null) {
|
||||
raceNamePrefixTextBox.setText("");
|
||||
} else {
|
||||
raceNamePrefixTextBox.setText(selectedSeries.name.substring(0, 1).toUpperCase());
|
||||
}
|
||||
fillExistingRacesOfSeries();
|
||||
}
|
||||
});
|
||||
|
||||
seriesPanel.add(seriesListBox);
|
||||
additionalWidgetPanel.add(seriesPanel);
|
||||
|
||||
// add races controls
|
||||
HorizontalPanel addRacesPanel = new HorizontalPanel();
|
||||
addRacesPanel.setSpacing(3);
|
||||
addRacesPanel.add(new Label(stringMessages.add()));
|
||||
addRacesPanel.add(addRacesListBox);
|
||||
for(int i = 1; i <= 10; i++) {
|
||||
addRacesListBox.addItem("" + i);
|
||||
}
|
||||
addRacesListBox.setSelectedIndex(0);
|
||||
raceNamePrefixTextBox.setWidth("20px");
|
||||
addRacesPanel.add(raceNamePrefixTextBox);
|
||||
addRacesBtn = new Button(stringMessages.add());
|
||||
addRacesBtn.addStyleName("inlineButton");
|
||||
addRacesBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
if(selectedSeries != null) {
|
||||
String racePrefix = raceNamePrefixTextBox.getText();
|
||||
int racesCountToCreate = addRacesListBox.getSelectedIndex()+1;
|
||||
int currentSize = raceNameEntryFields.size();
|
||||
for(int i = 1; i <= racesCountToCreate; i++) {
|
||||
String raceName = racePrefix;
|
||||
if(racesCountToCreate != 1 || selectedSeries.getRaceColumns().size() > 0) {
|
||||
raceName += (currentSize + i);
|
||||
}
|
||||
createRaceNameWidget(raceName, true);
|
||||
createRaceNameDeleteButtonWidget();
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
validate();
|
||||
} else {
|
||||
Window.alert("Please select a series first.");
|
||||
}
|
||||
}
|
||||
});
|
||||
addRacesPanel.add(addRacesBtn);
|
||||
additionalWidgetPanel.add(addRacesPanel);
|
||||
|
||||
additionalWidgetPanel.add(createHeadlineLabel(stringMessages.races()));
|
||||
additionalWidgetPanel.add(raceColumnsGrid);
|
||||
|
||||
if(hasOneSeries) {
|
||||
fillExistingRacesOfSeries();
|
||||
}
|
||||
|
||||
return additionalWidgetPanel;
|
||||
}
|
||||
|
||||
private void fillExistingRacesOfSeries() {
|
||||
SeriesDTO selectedSeries = getSelectedSeries();
|
||||
raceNameEntryFields.clear();
|
||||
raceNameDeleteButtons.clear();
|
||||
if(selectedSeries != null && !selectedSeries.getRaceColumns().isEmpty()) {
|
||||
for(RaceColumnDTO raceColumn: selectedSeries.getRaceColumns()) {
|
||||
createRaceNameWidget(raceColumn.name, false);
|
||||
createRaceNameDeleteButtonWidget();
|
||||
}
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidgetPanel);
|
||||
}
|
||||
|
||||
private void updateRaceColumnsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(raceColumnsGrid);
|
||||
parentPanel.remove(raceColumnsGrid);
|
||||
int raceNamesCount = raceNameEntryFields.size();
|
||||
if(raceNamesCount > 0) {
|
||||
raceColumnsGrid = new Grid(raceNamesCount + 1, 3);
|
||||
raceColumnsGrid.setCellSpacing(4);
|
||||
raceColumnsGrid.setHTML(0, 0, stringMessages.name());
|
||||
for(int i = 0; i < raceNamesCount; i++) {
|
||||
raceColumnsGrid.setWidget(i+1, 0, raceNameEntryFields.get(i));
|
||||
raceColumnsGrid.setWidget(i+1, 1, raceNameDeleteButtons.get(i));
|
||||
}
|
||||
} else {
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
parentPanel.insert(raceColumnsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
private SeriesDTO getSelectedSeries() {
|
||||
SeriesDTO result = null;
|
||||
int selIndex = seriesListBox.getSelectedIndex();
|
||||
if(selIndex > 0 || hasOneSeries) { // the zero index represents the 'no selection' text
|
||||
String itemText = seriesListBox.getItemText(selIndex);
|
||||
for(SeriesDTO seriesDTO: regatta.series) {
|
||||
if(seriesDTO.name.equals(itemText)) {
|
||||
result = seriesDTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
|
||||
+206
-207
@@ -1,207 +1,206 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
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.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.TextBox;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
|
||||
public class RaceColumnsInLeaderboardDialog extends DataEntryDialog<List<RaceColumnDTO>> {
|
||||
private final ListBox addRacesListBox;
|
||||
private Button addRacesBtn;
|
||||
private final List<TextBox> raceNameEntryFields;
|
||||
private final List<CheckBox> isMedalRaceCheckboxes;
|
||||
private final StringMessages stringMessages;
|
||||
private final TextBox raceNamePrefixTextBox;
|
||||
private Grid raceColumnsGrid;
|
||||
private VerticalPanel additionalWidget;
|
||||
private List<RaceColumnDTO> existingRaces;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<List<RaceColumnDTO>> {
|
||||
private StringMessages stringConstants;
|
||||
|
||||
public RaceDialogValidator(StringMessages stringConstants) {
|
||||
this.stringConstants = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(List<RaceColumnDTO> raceColumnsWithFleetToValidate) {
|
||||
String errorMessage = null;
|
||||
|
||||
List<RaceColumnDTO> raceColumnsToValidate = new ArrayList<RaceColumnDTO>();
|
||||
for (RaceColumnDTO raceColumnDTO : raceColumnsToValidate) {
|
||||
raceColumnsToValidate.add(raceColumnDTO);
|
||||
}
|
||||
|
||||
if(errorMessage == null) {
|
||||
int index = 0;
|
||||
boolean raceColumnNameNotEmpty = true;
|
||||
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
raceColumnNameNotEmpty = raceColumn.name != null && raceColumn.name.length() > 0;
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
boolean raceColumnUnique = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
if (!setToFindDuplicates.add(raceColumn.name)) {
|
||||
raceColumnUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
errorMessage = stringConstants.race() + " " + (index + 1) + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!raceColumnUnique) {
|
||||
errorMessage = stringConstants.race() + " " + (index2 + 1) + ": "
|
||||
+ stringConstants.raceWithThisNameAlreadyExists();
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RaceColumnsInLeaderboardDialog(List<RaceColumnDTO> existingRaces, StringMessages stringConstants,
|
||||
AsyncCallback<List<RaceColumnDTO>> callback) {
|
||||
super(stringConstants.actionAddRaces(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(stringConstants), callback);
|
||||
this.existingRaces = existingRaces;
|
||||
this.stringMessages = stringConstants;
|
||||
addRacesListBox = createListBox(false);
|
||||
raceNamePrefixTextBox = createTextBox(null);
|
||||
raceNameEntryFields = new ArrayList<TextBox>();
|
||||
isMedalRaceCheckboxes = new ArrayList<CheckBox>();
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
private Widget createRaceNameWidget(String defaultName, boolean enabled) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(25);
|
||||
textBox.setEnabled(enabled);
|
||||
raceNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createMedalRaceWidget(boolean isMedalRace, boolean enabled) {
|
||||
CheckBox checkBox = createCheckbox(stringMessages.medalRace());
|
||||
checkBox.setEnabled(enabled);
|
||||
isMedalRaceCheckboxes.add(checkBox);
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<RaceColumnDTO> getResult() {
|
||||
List<RaceColumnDTO> racesWithFleet = new ArrayList<RaceColumnDTO>();
|
||||
int racesCount = raceNameEntryFields.size();
|
||||
for(int i = 0; i < racesCount; i++) {
|
||||
String raceColumnName = raceNameEntryFields.get(i).getValue();
|
||||
RaceColumnDTO raceColumnDTO = new RaceColumnDTO();
|
||||
raceColumnDTO.name = raceColumnName;
|
||||
raceColumnDTO.setMedalRace(false);
|
||||
racesWithFleet.add(raceColumnDTO);
|
||||
}
|
||||
return racesWithFleet;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
additionalWidget = new VerticalPanel();
|
||||
|
||||
raceNamePrefixTextBox.setText("R");
|
||||
|
||||
// add races controls
|
||||
HorizontalPanel addRacesPanel = new HorizontalPanel();
|
||||
addRacesPanel.setSpacing(5);
|
||||
addRacesPanel.add(new Label(stringMessages.add()));
|
||||
addRacesPanel.add(addRacesListBox);
|
||||
for(int i = 1; i <= 20; i++) {
|
||||
addRacesListBox.addItem("" + i);
|
||||
}
|
||||
addRacesListBox.setSelectedIndex(0);
|
||||
addRacesPanel.add(new Label(stringMessages.racesWithNamePrefix()+" "));
|
||||
raceNamePrefixTextBox.setWidth("20px");
|
||||
addRacesPanel.add(raceNamePrefixTextBox);
|
||||
addRacesBtn = new Button(stringMessages.add());
|
||||
addRacesBtn.addStyleName("inlineButton");
|
||||
addRacesBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
String racePrefix = raceNamePrefixTextBox.getText();
|
||||
int racesCountToCreate = addRacesListBox.getSelectedIndex()+1;
|
||||
int currentSize = raceNameEntryFields.size();
|
||||
for(int i = 1; i <= racesCountToCreate; i++) {
|
||||
String raceName = racePrefix;
|
||||
if(racesCountToCreate != 1 || existingRaces.size() > 0) {
|
||||
raceName += (currentSize + i);
|
||||
}
|
||||
createRaceNameWidget(raceName, true);
|
||||
createMedalRaceWidget(false, true);
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidget);
|
||||
|
||||
}
|
||||
});
|
||||
addRacesPanel.add(addRacesBtn);
|
||||
additionalWidget.add(addRacesPanel);
|
||||
alignAllPanelWidgetsVertically(addRacesPanel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
|
||||
additionalWidget.add(createHeadlineLabel(stringMessages.races()));
|
||||
additionalWidget.add(raceColumnsGrid);
|
||||
|
||||
for(RaceColumnDTO raceColumn: existingRaces) {
|
||||
createRaceNameWidget(raceColumn.getRaceColumnName(), false);
|
||||
createMedalRaceWidget(raceColumn.isMedalRace(), false);
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidget);
|
||||
|
||||
return additionalWidget;
|
||||
}
|
||||
|
||||
private void updateRaceColumnsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(raceColumnsGrid);
|
||||
parentPanel.remove(raceColumnsGrid);
|
||||
int raceNamesCount = raceNameEntryFields.size();
|
||||
if(raceNamesCount > 0) {
|
||||
raceColumnsGrid = new Grid(raceNamesCount, 3);
|
||||
raceColumnsGrid.setCellSpacing(4);
|
||||
for(int i = 0; i < raceNamesCount; i++) {
|
||||
raceColumnsGrid.setWidget(i, 0, raceNameEntryFields.get(i));
|
||||
raceColumnsGrid.setWidget(i, 1, isMedalRaceCheckboxes.get(i));
|
||||
}
|
||||
} else {
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
parentPanel.insert(raceColumnsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
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.TextBox;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
|
||||
public class RaceColumnsInLeaderboardDialog extends DataEntryDialog<List<RaceColumnDTO>> {
|
||||
private final ListBox addRacesListBox;
|
||||
private Button addRacesBtn;
|
||||
private final List<TextBox> raceNameEntryFields;
|
||||
private final List<CheckBox> isMedalRaceCheckboxes;
|
||||
private final StringMessages stringMessages;
|
||||
private final TextBox raceNamePrefixTextBox;
|
||||
private Grid raceColumnsGrid;
|
||||
private VerticalPanel additionalWidget;
|
||||
private List<RaceColumnDTO> existingRaces;
|
||||
|
||||
private static class RaceDialogValidator implements Validator<List<RaceColumnDTO>> {
|
||||
private StringMessages stringConstants;
|
||||
|
||||
public RaceDialogValidator(StringMessages stringConstants) {
|
||||
this.stringConstants = stringConstants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(List<RaceColumnDTO> raceColumnsWithFleetToValidate) {
|
||||
String errorMessage = null;
|
||||
|
||||
List<RaceColumnDTO> raceColumnsToValidate = new ArrayList<RaceColumnDTO>();
|
||||
for (RaceColumnDTO raceColumnDTO : raceColumnsToValidate) {
|
||||
raceColumnsToValidate.add(raceColumnDTO);
|
||||
}
|
||||
|
||||
if(errorMessage == null) {
|
||||
int index = 0;
|
||||
boolean raceColumnNameNotEmpty = true;
|
||||
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
raceColumnNameNotEmpty = raceColumn.name != null && raceColumn.name.length() > 0;
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
boolean raceColumnUnique = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (RaceColumnDTO raceColumn : raceColumnsToValidate) {
|
||||
if (!setToFindDuplicates.add(raceColumn.name)) {
|
||||
raceColumnUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
|
||||
if (!raceColumnNameNotEmpty) {
|
||||
errorMessage = stringConstants.race() + " " + (index + 1) + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!raceColumnUnique) {
|
||||
errorMessage = stringConstants.race() + " " + (index2 + 1) + ": "
|
||||
+ stringConstants.raceWithThisNameAlreadyExists();
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RaceColumnsInLeaderboardDialog(List<RaceColumnDTO> existingRaces, StringMessages stringConstants,
|
||||
DialogCallback<List<RaceColumnDTO>> callback) {
|
||||
super(stringConstants.actionAddRaces(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RaceDialogValidator(stringConstants), callback);
|
||||
this.existingRaces = existingRaces;
|
||||
this.stringMessages = stringConstants;
|
||||
addRacesListBox = createListBox(false);
|
||||
raceNamePrefixTextBox = createTextBox(null);
|
||||
raceNameEntryFields = new ArrayList<TextBox>();
|
||||
isMedalRaceCheckboxes = new ArrayList<CheckBox>();
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
private Widget createRaceNameWidget(String defaultName, boolean enabled) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(25);
|
||||
textBox.setEnabled(enabled);
|
||||
raceNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createMedalRaceWidget(boolean isMedalRace, boolean enabled) {
|
||||
CheckBox checkBox = createCheckbox(stringMessages.medalRace());
|
||||
checkBox.setEnabled(enabled);
|
||||
isMedalRaceCheckboxes.add(checkBox);
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<RaceColumnDTO> getResult() {
|
||||
List<RaceColumnDTO> racesWithFleet = new ArrayList<RaceColumnDTO>();
|
||||
int racesCount = raceNameEntryFields.size();
|
||||
for(int i = 0; i < racesCount; i++) {
|
||||
String raceColumnName = raceNameEntryFields.get(i).getValue();
|
||||
RaceColumnDTO raceColumnDTO = new RaceColumnDTO(/* isValidInTotalScore not relevant here because no scores attached */ null);
|
||||
raceColumnDTO.name = raceColumnName;
|
||||
raceColumnDTO.setMedalRace(false);
|
||||
racesWithFleet.add(raceColumnDTO);
|
||||
}
|
||||
return racesWithFleet;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
additionalWidget = new VerticalPanel();
|
||||
|
||||
raceNamePrefixTextBox.setText("R");
|
||||
|
||||
// add races controls
|
||||
HorizontalPanel addRacesPanel = new HorizontalPanel();
|
||||
addRacesPanel.setSpacing(5);
|
||||
addRacesPanel.add(new Label(stringMessages.add()));
|
||||
addRacesPanel.add(addRacesListBox);
|
||||
for(int i = 1; i <= 20; i++) {
|
||||
addRacesListBox.addItem("" + i);
|
||||
}
|
||||
addRacesListBox.setSelectedIndex(0);
|
||||
addRacesPanel.add(new Label(stringMessages.racesWithNamePrefix()+" "));
|
||||
raceNamePrefixTextBox.setWidth("20px");
|
||||
addRacesPanel.add(raceNamePrefixTextBox);
|
||||
addRacesBtn = new Button(stringMessages.add());
|
||||
addRacesBtn.addStyleName("inlineButton");
|
||||
addRacesBtn.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
String racePrefix = raceNamePrefixTextBox.getText();
|
||||
int racesCountToCreate = addRacesListBox.getSelectedIndex()+1;
|
||||
int currentSize = raceNameEntryFields.size();
|
||||
for(int i = 1; i <= racesCountToCreate; i++) {
|
||||
String raceName = racePrefix;
|
||||
if(racesCountToCreate != 1 || existingRaces.size() > 0) {
|
||||
raceName += (currentSize + i);
|
||||
}
|
||||
createRaceNameWidget(raceName, true);
|
||||
createMedalRaceWidget(false, true);
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidget);
|
||||
|
||||
}
|
||||
});
|
||||
addRacesPanel.add(addRacesBtn);
|
||||
additionalWidget.add(addRacesPanel);
|
||||
alignAllPanelWidgetsVertically(addRacesPanel, HasVerticalAlignment.ALIGN_MIDDLE);
|
||||
|
||||
additionalWidget.add(createHeadlineLabel(stringMessages.races()));
|
||||
additionalWidget.add(raceColumnsGrid);
|
||||
|
||||
for(RaceColumnDTO raceColumn: existingRaces) {
|
||||
createRaceNameWidget(raceColumn.getRaceColumnName(), false);
|
||||
createMedalRaceWidget(raceColumn.isMedalRace(), false);
|
||||
}
|
||||
updateRaceColumnsGrid(additionalWidget);
|
||||
|
||||
return additionalWidget;
|
||||
}
|
||||
|
||||
private void updateRaceColumnsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(raceColumnsGrid);
|
||||
parentPanel.remove(raceColumnsGrid);
|
||||
int raceNamesCount = raceNameEntryFields.size();
|
||||
if(raceNamesCount > 0) {
|
||||
raceColumnsGrid = new Grid(raceNamesCount, 3);
|
||||
raceColumnsGrid.setCellSpacing(4);
|
||||
for(int i = 0; i < raceNamesCount; i++) {
|
||||
raceColumnsGrid.setWidget(i, 0, raceNameEntryFields.get(i));
|
||||
raceColumnsGrid.setWidget(i, 1, isMedalRaceCheckboxes.get(i));
|
||||
}
|
||||
} else {
|
||||
raceColumnsGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
parentPanel.insert(raceColumnsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
}
|
||||
}
|
||||
|
||||
+521
-520
File diff suppressed because it is too large
Load Diff
+26
-27
@@ -1,27 +1,26 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog {
|
||||
|
||||
public RegattaLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, Collection<RegattaDTO> existingRegattas, StringMessages stringConstants,
|
||||
ErrorReporter errorReporter, AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.createRegattaLeaderboard(), new LeaderboardDescriptor(), existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringConstants, existingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(null);
|
||||
|
||||
regattaListBox = createListBox(false);
|
||||
regattaListBox.addItem(stringConstants.pleaseSelectARegatta());
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
regattaListBox.addItem(regatta.name);
|
||||
}
|
||||
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog {
|
||||
|
||||
public RegattaLeaderboardCreateDialog(Collection<StrippedLeaderboardDTO> existingLeaderboards, Collection<RegattaDTO> existingRegattas, StringMessages stringConstants,
|
||||
ErrorReporter errorReporter, DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.createRegattaLeaderboard(), new LeaderboardDescriptor(), existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringConstants, existingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(null);
|
||||
|
||||
regattaListBox = createListBox(false);
|
||||
regattaListBox.addItem(stringConstants.pleaseSelectARegatta());
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
regattaListBox.addItem(regatta.name);
|
||||
}
|
||||
discardThresholdBoxes = initEmptyDiscardThresholdBoxes(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+123
-124
@@ -1,124 +1,123 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
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.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
|
||||
public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog {
|
||||
protected ListBox regattaListBox;
|
||||
protected Collection<RegattaDTO> existingRegattas;
|
||||
|
||||
protected static class LeaderboardParameterValidator implements Validator<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringConstants;
|
||||
protected final Collection<StrippedLeaderboardDTO> existingLeaderboards;
|
||||
|
||||
public LeaderboardParameterValidator(StringMessages stringConstants, Collection<StrippedLeaderboardDTO> existingLeaderboards){
|
||||
super();
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingLeaderboards = existingLeaderboards;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
boolean regattaSelected = leaderboardToValidate.getRegattaName() != null ? true : false;
|
||||
|
||||
if (!nonEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if(!regattaSelected){
|
||||
errorMessage = stringConstants.pleaseSelectARegatta();
|
||||
} else if(!unique){
|
||||
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
|
||||
} else if (!discardThresholdsAscending) {
|
||||
errorMessage = stringConstants.discardThresholdsMustBeAscending();
|
||||
} else {
|
||||
errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public RegattaLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, Collection<RegattaDTO> existingRegattas, StringMessages stringConstants,
|
||||
ErrorReporter errorReporter, LeaderboardParameterValidator validator, AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, leaderboardDTO, stringConstants, validator, callback);
|
||||
this.existingRegattas = existingRegattas;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
LeaderboardDescriptor leaderboard = super.getResult();
|
||||
leaderboard.setRegattaName(getSelectedRegatta() != null ? getSelectedRegatta().name : null);
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
|
||||
Grid formGrid = new Grid(3,2);
|
||||
formGrid.setCellSpacing(3);
|
||||
formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameTextBox);
|
||||
formGrid.setWidget(1, 0, new Label(stringMessages.regatta() + ":"));
|
||||
formGrid.setWidget(1, 1, regattaListBox);
|
||||
|
||||
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(hp);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
public RegattaDTO getSelectedRegatta() {
|
||||
RegattaDTO result = null;
|
||||
int selIndex = regattaListBox.getSelectedIndex();
|
||||
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)) {
|
||||
result = regattaDTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
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.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
|
||||
public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog {
|
||||
protected ListBox regattaListBox;
|
||||
protected Collection<RegattaDTO> existingRegattas;
|
||||
|
||||
protected static class LeaderboardParameterValidator implements Validator<LeaderboardDescriptor> {
|
||||
protected final StringMessages stringConstants;
|
||||
protected final Collection<StrippedLeaderboardDTO> existingLeaderboards;
|
||||
|
||||
public LeaderboardParameterValidator(StringMessages stringConstants, Collection<StrippedLeaderboardDTO> existingLeaderboards){
|
||||
super();
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingLeaderboards = existingLeaderboards;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
boolean regattaSelected = leaderboardToValidate.getRegattaName() != null ? true : false;
|
||||
|
||||
if (!nonEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if(!regattaSelected){
|
||||
errorMessage = stringConstants.pleaseSelectARegatta();
|
||||
} else if(!unique){
|
||||
errorMessage = stringConstants.leaderboardWithThisNameAlreadyExists();
|
||||
} else if (!discardThresholdsAscending) {
|
||||
errorMessage = stringConstants.discardThresholdsMustBeAscending();
|
||||
} else {
|
||||
errorMessage = null;
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public RegattaLeaderboardDialog(String title, LeaderboardDescriptor leaderboardDTO, Collection<RegattaDTO> existingRegattas, StringMessages stringConstants,
|
||||
ErrorReporter errorReporter, LeaderboardParameterValidator validator, DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(title, leaderboardDTO, stringConstants, validator, callback);
|
||||
this.existingRegattas = existingRegattas;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LeaderboardDescriptor getResult() {
|
||||
LeaderboardDescriptor leaderboard = super.getResult();
|
||||
leaderboard.setRegattaName(getSelectedRegatta() != null ? getSelectedRegatta().name : null);
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
|
||||
Grid formGrid = new Grid(3,2);
|
||||
formGrid.setCellSpacing(3);
|
||||
formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameTextBox);
|
||||
formGrid.setWidget(1, 0, new Label(stringMessages.regatta() + ":"));
|
||||
formGrid.setWidget(1, 1, regattaListBox);
|
||||
|
||||
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(hp);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
public RegattaDTO getSelectedRegatta() {
|
||||
RegattaDTO result = null;
|
||||
int selIndex = regattaListBox.getSelectedIndex();
|
||||
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)) {
|
||||
result = regattaDTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+33
-34
@@ -1,34 +1,33 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class RegattaLeaderboardEditDialog extends RegattaLeaderboardDialog {
|
||||
|
||||
public RegattaLeaderboardEditDialog(Collection<StrippedLeaderboardDTO> otherExistingLeaderboards, Collection<RegattaDTO> existingRegattas,
|
||||
LeaderboardDescriptor leaderboard, StringMessages stringConstants, ErrorReporter errorReporter,
|
||||
AsyncCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.editRegattaLeaderboard(), leaderboard, existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(
|
||||
stringConstants, otherExistingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(leaderboard.getName());
|
||||
|
||||
regattaListBox = createListBox(false);
|
||||
regattaListBox.addItem(stringConstants.pleaseSelectARegatta());
|
||||
int i=1;
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
regattaListBox.addItem(regatta.name);
|
||||
if (regatta.name.equals(leaderboard.getRegattaName())) {
|
||||
regattaListBox.setSelectedIndex(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
regattaListBox.setEnabled(false);
|
||||
discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboard.getDiscardThresholds(), this);
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
|
||||
|
||||
public class RegattaLeaderboardEditDialog extends RegattaLeaderboardDialog {
|
||||
|
||||
public RegattaLeaderboardEditDialog(Collection<StrippedLeaderboardDTO> otherExistingLeaderboards, Collection<RegattaDTO> existingRegattas,
|
||||
LeaderboardDescriptor leaderboard, StringMessages stringConstants, ErrorReporter errorReporter,
|
||||
DialogCallback<LeaderboardDescriptor> callback) {
|
||||
super(stringConstants.editRegattaLeaderboard(), leaderboard, existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(
|
||||
stringConstants, otherExistingLeaderboards), callback);
|
||||
|
||||
nameTextBox = createTextBox(leaderboard.getName());
|
||||
|
||||
regattaListBox = createListBox(false);
|
||||
regattaListBox.addItem(stringConstants.pleaseSelectARegatta());
|
||||
int i=1;
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
regattaListBox.addItem(regatta.name);
|
||||
if (regatta.name.equals(leaderboard.getRegattaName())) {
|
||||
regattaListBox.setSelectedIndex(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
regattaListBox.setEnabled(false);
|
||||
discardThresholdBoxes = initPrefilledDiscardThresholdBoxes(leaderboard.getDiscardThresholds(), this);
|
||||
}
|
||||
}
|
||||
|
||||
+530
-528
File diff suppressed because it is too large
Load Diff
+232
-233
@@ -1,233 +1,232 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.dom.client.Style.FontWeight;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
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.ScoringSchemeType;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.shared.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class RegattaWithSeriesAndFleetsCreateDialog extends DataEntryDialog<RegattaDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private RegattaDTO regatta;
|
||||
|
||||
private TextBox nameEntryField;
|
||||
private TextBox boatClassEntryField;
|
||||
private ListBox scoringSchemeListBox;
|
||||
|
||||
private List<SeriesDTO> createdSeries;
|
||||
|
||||
private Grid seriesGrid;
|
||||
|
||||
protected static class RegattaParameterValidator implements Validator<RegattaDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<RegattaDTO> existingRegattas;
|
||||
|
||||
public RegattaParameterValidator(StringMessages stringConstants, Collection<RegattaDTO> existingRegattas) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingRegattas = new ArrayList<RegattaDTO>(existingRegattas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(RegattaDTO regattaToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = regattaToValidate.name != null && regattaToValidate.name.length() > 0;
|
||||
boolean boatClassNotEmpty = regattaToValidate.boatClass != null
|
||||
&& regattaToValidate.boatClass.name.length() > 0;
|
||||
|
||||
boolean unique = true;
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
if (regatta.name.equals(regattaToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!boatClassNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.regattaWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
if (errorMessage == null) {
|
||||
List<SeriesDTO> seriesToValidate = regattaToValidate.series;
|
||||
int index = 0;
|
||||
boolean seriesNameNotEmpty = true;
|
||||
|
||||
for (SeriesDTO series : seriesToValidate) {
|
||||
seriesNameNotEmpty = series.name != null && series.name.length() > 0;
|
||||
if (!seriesNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
boolean seriesUnique = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (SeriesDTO series : seriesToValidate) {
|
||||
if (!setToFindDuplicates.add(series.name)) {
|
||||
seriesUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
|
||||
if (!seriesNameNotEmpty) {
|
||||
errorMessage = stringConstants.series() + " " + (index + 1) + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!seriesUnique) {
|
||||
errorMessage = stringConstants.series() + " " + (index2 + 1) + ": "
|
||||
+ stringConstants.seriesWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RegattaWithSeriesAndFleetsCreateDialog(Collection<RegattaDTO> existingRegattas,
|
||||
StringMessages stringConstants, AsyncCallback<RegattaDTO> callback) {
|
||||
super(stringConstants.regatta(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RegattaParameterValidator(stringConstants, existingRegattas), callback);
|
||||
this.stringConstants = stringConstants;
|
||||
this.regatta = new RegattaDTO();
|
||||
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setVisibleLength(40);
|
||||
boatClassEntryField = createTextBox(null);
|
||||
boatClassEntryField.setVisibleLength(20);
|
||||
scoringSchemeListBox = createListBox(false);
|
||||
for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants));
|
||||
}
|
||||
|
||||
createdSeries = new ArrayList<SeriesDTO>();
|
||||
seriesGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegattaDTO getResult() {
|
||||
regatta.name = nameEntryField.getText();
|
||||
regatta.boatClass = new BoatClassDTO(boatClassEntryField.getText(), 0.0);
|
||||
regatta.scoringScheme = getSelectedScoringSchemeType();
|
||||
regatta.series = new ArrayList<SeriesDTO>();
|
||||
regatta.series.addAll(createdSeries);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
public ScoringSchemeType getSelectedScoringSchemeType() {
|
||||
ScoringSchemeType result = null;
|
||||
int selIndex = scoringSchemeListBox.getSelectedIndex();
|
||||
if(selIndex >= 0) {
|
||||
String itemText = scoringSchemeListBox.getItemText(selIndex);
|
||||
for(ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
if(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants).equals(itemText)) {
|
||||
result = scoringSchemeType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
final VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
Grid formGrid = new Grid(3, 2);
|
||||
panel.add(formGrid);
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 0, new Label(stringConstants.boatClass() + ":"));
|
||||
formGrid.setWidget(1, 1, boatClassEntryField);
|
||||
formGrid.setWidget(2, 0, new Label(stringConstants.scoringSystem() + ":"));
|
||||
formGrid.setWidget(2, 1, scoringSchemeListBox);
|
||||
|
||||
panel.add(createHeadlineLabel(stringConstants.series()));
|
||||
panel.add(seriesGrid);
|
||||
Button addSeriesButton = new Button("Add series");
|
||||
addSeriesButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
RegattaDTO result = getResult();
|
||||
SeriesWithFleetsCreateDialog dialog = new SeriesWithFleetsCreateDialog(Collections
|
||||
.unmodifiableCollection(result.series), stringConstants, new AsyncCallback<SeriesDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(SeriesDTO newSeries) {
|
||||
createdSeries.add(newSeries);
|
||||
updateSeriesGrid(panel);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
panel.add(addSeriesButton);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void updateSeriesGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(seriesGrid);
|
||||
parentPanel.remove(seriesGrid);
|
||||
|
||||
int seriesCount = createdSeries.size();
|
||||
seriesGrid = new Grid(seriesCount * 2, 3);
|
||||
seriesGrid.setCellSpacing(3);
|
||||
|
||||
for (int i = 0; i < seriesCount; i++) {
|
||||
SeriesDTO seriesDTO = createdSeries.get(i);
|
||||
Label seriesLabel = new Label((i + 1) + ". " + stringConstants.series() + ":");
|
||||
seriesLabel.setWordWrap(false);
|
||||
seriesLabel.getElement().getStyle().setFontWeight(FontWeight.BOLD);
|
||||
seriesGrid.setWidget(i * 2, 0, seriesLabel);
|
||||
seriesGrid.setHTML(i * 2, 1, seriesDTO.name);
|
||||
if (seriesDTO.getFleets() != null && seriesDTO.getFleets().size() > 0) {
|
||||
seriesGrid.setHTML(i * 2 + 1, 1, seriesDTO.getFleets().size() + " fleets: "
|
||||
+ seriesDTO.getFleets().toString());
|
||||
} else {
|
||||
seriesGrid.setHTML(i * 2 + 1, 1, seriesDTO.getFleets().size() + " No fleets defined.");
|
||||
}
|
||||
}
|
||||
|
||||
parentPanel.insert(seriesGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.dom.client.Style.FontWeight;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
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.ScoringSchemeType;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter;
|
||||
import com.sap.sailing.gwt.ui.shared.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class RegattaWithSeriesAndFleetsCreateDialog extends DataEntryDialog<RegattaDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private RegattaDTO regatta;
|
||||
|
||||
private TextBox nameEntryField;
|
||||
private TextBox boatClassEntryField;
|
||||
private ListBox scoringSchemeListBox;
|
||||
|
||||
private List<SeriesDTO> createdSeries;
|
||||
|
||||
private Grid seriesGrid;
|
||||
|
||||
protected static class RegattaParameterValidator implements Validator<RegattaDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<RegattaDTO> existingRegattas;
|
||||
|
||||
public RegattaParameterValidator(StringMessages stringConstants, Collection<RegattaDTO> existingRegattas) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingRegattas = new ArrayList<RegattaDTO>(existingRegattas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(RegattaDTO regattaToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = regattaToValidate.name != null && regattaToValidate.name.length() > 0;
|
||||
boolean boatClassNotEmpty = regattaToValidate.boatClass != null
|
||||
&& regattaToValidate.boatClass.name.length() > 0;
|
||||
|
||||
boolean unique = true;
|
||||
for (RegattaDTO regatta : existingRegattas) {
|
||||
if (regatta.name.equals(regattaToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!boatClassNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.regattaWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
if (errorMessage == null) {
|
||||
List<SeriesDTO> seriesToValidate = regattaToValidate.series;
|
||||
int index = 0;
|
||||
boolean seriesNameNotEmpty = true;
|
||||
|
||||
for (SeriesDTO series : seriesToValidate) {
|
||||
seriesNameNotEmpty = series.name != null && series.name.length() > 0;
|
||||
if (!seriesNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
boolean seriesUnique = true;
|
||||
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (SeriesDTO series : seriesToValidate) {
|
||||
if (!setToFindDuplicates.add(series.name)) {
|
||||
seriesUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
|
||||
if (!seriesNameNotEmpty) {
|
||||
errorMessage = stringConstants.series() + " " + (index + 1) + ": "
|
||||
+ stringConstants.pleaseEnterAName();
|
||||
} else if (!seriesUnique) {
|
||||
errorMessage = stringConstants.series() + " " + (index2 + 1) + ": "
|
||||
+ stringConstants.seriesWithThisNameAlreadyExists();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public RegattaWithSeriesAndFleetsCreateDialog(Collection<RegattaDTO> existingRegattas,
|
||||
StringMessages stringConstants, DialogCallback<RegattaDTO> callback) {
|
||||
super(stringConstants.regatta(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new RegattaParameterValidator(stringConstants, existingRegattas), callback);
|
||||
this.stringConstants = stringConstants;
|
||||
this.regatta = new RegattaDTO();
|
||||
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setVisibleLength(40);
|
||||
boatClassEntryField = createTextBox(null);
|
||||
boatClassEntryField.setVisibleLength(20);
|
||||
scoringSchemeListBox = createListBox(false);
|
||||
for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
scoringSchemeListBox.addItem(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants));
|
||||
}
|
||||
|
||||
createdSeries = new ArrayList<SeriesDTO>();
|
||||
seriesGrid = new Grid(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RegattaDTO getResult() {
|
||||
regatta.name = nameEntryField.getText();
|
||||
regatta.boatClass = new BoatClassDTO(boatClassEntryField.getText(), 0.0);
|
||||
regatta.scoringScheme = getSelectedScoringSchemeType();
|
||||
regatta.series = new ArrayList<SeriesDTO>();
|
||||
regatta.series.addAll(createdSeries);
|
||||
return regatta;
|
||||
}
|
||||
|
||||
public ScoringSchemeType getSelectedScoringSchemeType() {
|
||||
ScoringSchemeType result = null;
|
||||
int selIndex = scoringSchemeListBox.getSelectedIndex();
|
||||
if(selIndex >= 0) {
|
||||
String itemText = scoringSchemeListBox.getItemText(selIndex);
|
||||
for(ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) {
|
||||
if(ScoringSchemeTypeFormatter.format(scoringSchemeType, stringConstants).equals(itemText)) {
|
||||
result = scoringSchemeType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
final VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
Grid formGrid = new Grid(3, 2);
|
||||
panel.add(formGrid);
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 0, new Label(stringConstants.boatClass() + ":"));
|
||||
formGrid.setWidget(1, 1, boatClassEntryField);
|
||||
formGrid.setWidget(2, 0, new Label(stringConstants.scoringSystem() + ":"));
|
||||
formGrid.setWidget(2, 1, scoringSchemeListBox);
|
||||
|
||||
panel.add(createHeadlineLabel(stringConstants.series()));
|
||||
panel.add(seriesGrid);
|
||||
Button addSeriesButton = new Button("Add series");
|
||||
addSeriesButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
RegattaDTO result = getResult();
|
||||
SeriesWithFleetsCreateDialog dialog = new SeriesWithFleetsCreateDialog(Collections
|
||||
.unmodifiableCollection(result.series), stringConstants, new DialogCallback<SeriesDTO>() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ok(SeriesDTO newSeries) {
|
||||
createdSeries.add(newSeries);
|
||||
updateSeriesGrid(panel);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
panel.add(addSeriesButton);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void updateSeriesGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(seriesGrid);
|
||||
parentPanel.remove(seriesGrid);
|
||||
|
||||
int seriesCount = createdSeries.size();
|
||||
seriesGrid = new Grid(seriesCount * 2, 3);
|
||||
seriesGrid.setCellSpacing(3);
|
||||
|
||||
for (int i = 0; i < seriesCount; i++) {
|
||||
SeriesDTO seriesDTO = createdSeries.get(i);
|
||||
Label seriesLabel = new Label((i + 1) + ". " + stringConstants.series() + ":");
|
||||
seriesLabel.setWordWrap(false);
|
||||
seriesLabel.getElement().getStyle().setFontWeight(FontWeight.BOLD);
|
||||
seriesGrid.setWidget(i * 2, 0, seriesLabel);
|
||||
seriesGrid.setHTML(i * 2, 1, seriesDTO.name);
|
||||
if (seriesDTO.getFleets() != null && seriesDTO.getFleets().size() > 0) {
|
||||
seriesGrid.setHTML(i * 2 + 1, 1, seriesDTO.getFleets().size() + " fleets: "
|
||||
+ seriesDTO.getFleets().toString());
|
||||
} else {
|
||||
seriesGrid.setHTML(i * 2 + 1, 1, seriesDTO.getFleets().size() + " No fleets defined.");
|
||||
}
|
||||
}
|
||||
|
||||
parentPanel.insert(seriesGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-4
@@ -15,6 +15,7 @@ import com.google.gwt.user.client.ui.Widget;
|
||||
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;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
@@ -62,9 +63,9 @@ public class ReplicationPanel extends FlowPanel {
|
||||
|
||||
private void addReplication() {
|
||||
AddReplicationDialog dialog = new AddReplicationDialog(null,
|
||||
new AsyncCallback<Triple<Pair<String, String>, Integer, Integer>>() {
|
||||
new DialogCallback<Triple<Pair<String, String>, Integer, Integer>>() {
|
||||
@Override
|
||||
public void onSuccess(final Triple<Pair<String, String>, Integer, Integer> masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber) {
|
||||
public void ok(final Triple<Pair<String, String>, Integer, Integer> masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber) {
|
||||
sailingService.startReplicatingFromMaster(masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getA().getA(),
|
||||
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getA().getB(),
|
||||
masterNameAndExchangeNameAndMessagingPortNumberAndServletPortNumber.getC(),
|
||||
@@ -84,7 +85,7 @@ public class ReplicationPanel extends FlowPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
public void cancel() {
|
||||
// simply don't add replication
|
||||
}
|
||||
});
|
||||
@@ -141,7 +142,7 @@ public class ReplicationPanel extends FlowPanel {
|
||||
private final IntegerBox servletPortField;
|
||||
|
||||
public AddReplicationDialog(final Validator<Triple<Pair<String, String>, Integer, Integer>> validator,
|
||||
final AsyncCallback<Triple<Pair<String, String>, Integer, Integer>> callback) {
|
||||
final DialogCallback<Triple<Pair<String, String>, Integer, Integer>> callback) {
|
||||
super(stringMessages.add(), stringMessages.enterMaster(),
|
||||
stringMessages.ok(), stringMessages.cancel(), validator, callback);
|
||||
hostnameEntryField = createTextBox("localhost");
|
||||
|
||||
+243
-242
@@ -1,242 +1,243 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.cell.client.FieldUpdater;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.cellview.client.CellTable;
|
||||
import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SingleSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
|
||||
/**
|
||||
* Allows administrators to manage data of a sailing event. This is a temporary panel because the managed event
|
||||
* is not connected with any regatta and it used only to manage of basic attributes of the an event.
|
||||
* @author Frank Mittag (C5163974)
|
||||
*
|
||||
*/
|
||||
public class SailingEventManagementPanel extends SimplePanel {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
private CellTable<EventDTO> eventTable;
|
||||
private SingleSelectionModel<EventDTO> eventSelectionModel;
|
||||
private ListDataProvider<EventDTO> eventProvider;
|
||||
|
||||
private final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
|
||||
|
||||
public SailingEventManagementPanel(final SailingServiceAsync sailingService, final ErrorReporter errorReporter,
|
||||
final StringMessages stringMessages) {
|
||||
this.sailingService = sailingService;
|
||||
this.stringMessages = stringMessages;
|
||||
this.errorReporter = errorReporter;
|
||||
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
this.setWidget(mainPanel);
|
||||
mainPanel.setWidth("100%");
|
||||
|
||||
HorizontalPanel eventsPanel = new HorizontalPanel();
|
||||
eventsPanel.setSpacing(5);
|
||||
mainPanel.add(eventsPanel);
|
||||
|
||||
Button createEventBtn = new Button(stringMessages.actionAddEvent());
|
||||
createEventBtn.addClickHandler(new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
openCreateEventDialog();
|
||||
}
|
||||
});
|
||||
eventsPanel.add(createEventBtn);
|
||||
|
||||
// sailing events table
|
||||
TextColumn<EventDTO> eventNameColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.name;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> venueNameColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.venue != null ? event.venue.name : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> publicationUrlColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.publicationUrl;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> isPublicColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.isPublic ? stringMessages.yes() : stringMessages.no();
|
||||
}
|
||||
};
|
||||
|
||||
ImagesBarColumn<EventDTO, RegattaConfigImagesBarCell> eventActionColumn = new ImagesBarColumn<EventDTO, RegattaConfigImagesBarCell>(
|
||||
new RegattaConfigImagesBarCell(stringMessages));
|
||||
eventActionColumn.setFieldUpdater(new FieldUpdater<EventDTO, String>() {
|
||||
@Override
|
||||
public void update(int index, EventDTO event, String value) {
|
||||
if (RegattaConfigImagesBarCell.ACTION_REMOVE.equals(value)) {
|
||||
if (Window.confirm(stringMessages.doYouReallyWantToRemoveRegatta(event.name))) {
|
||||
removeEvent(event);
|
||||
}
|
||||
} else if (RegattaConfigImagesBarCell.ACTION_EDIT.equals(value)) {
|
||||
openEditEventDialog(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
eventTable = new CellTable<EventDTO>(10000, tableRes);
|
||||
eventTable.addColumn(eventNameColumn, stringMessages.event());
|
||||
eventTable.addColumn(venueNameColumn, stringMessages.venue());
|
||||
eventTable.addColumn(publicationUrlColumn, stringMessages.publicationUrl());
|
||||
eventTable.addColumn(isPublicColumn, stringMessages.isPublic());
|
||||
eventTable.addColumn(eventActionColumn, stringMessages.actions());
|
||||
|
||||
eventSelectionModel = new SingleSelectionModel<EventDTO>();
|
||||
eventSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
|
||||
@Override
|
||||
public void onSelectionChange(SelectionChangeEvent event) {
|
||||
}
|
||||
});
|
||||
eventTable.setSelectionModel(eventSelectionModel);
|
||||
|
||||
eventProvider = new ListDataProvider<EventDTO>();
|
||||
eventProvider.addDataDisplay(eventTable);
|
||||
mainPanel.add(eventTable);
|
||||
|
||||
fillEvents();
|
||||
}
|
||||
|
||||
private void removeEvent(final EventDTO event) {
|
||||
sailingService.removeEvent(event.name, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error trying to remove event " + event.name + ": " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void openCreateEventDialog() {
|
||||
List<EventDTO> existingEvents = new ArrayList<EventDTO>(eventProvider.getList());
|
||||
EventCreateDialog dialog = new EventCreateDialog(Collections.unmodifiableCollection(existingEvents), stringMessages,
|
||||
new AsyncCallback<EventDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(EventDTO newEvent) {
|
||||
createNewEvent(newEvent);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void openEditEventDialog(final EventDTO selectedEvent) {
|
||||
List<EventDTO> existingEvents = new ArrayList<EventDTO>(eventProvider.getList());
|
||||
existingEvents.remove(selectedEvent);
|
||||
EventEditDialog dialog = new EventEditDialog(selectedEvent, Collections.unmodifiableCollection(existingEvents), stringMessages,
|
||||
new AsyncCallback<EventDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(EventDTO updatedEvent) {
|
||||
updateEvent(selectedEvent.name, updatedEvent);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void updateEvent(final String oldEventName, final EventDTO updatedEvent) {
|
||||
List<String> regattaNames = new ArrayList<String>();
|
||||
for(RegattaDTO regatta: updatedEvent.regattas) {
|
||||
regattaNames.add(regatta.name);
|
||||
}
|
||||
|
||||
sailingService.updateEvent(oldEventName, updatedEvent.venue, updatedEvent.publicationUrl, updatedEvent.isPublic,
|
||||
regattaNames, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to update sailing event" + oldEventName + ": " + t.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
if(!oldEventName.equals(updatedEvent.name)) {
|
||||
sailingService.renameEvent(oldEventName, updatedEvent.name, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to rename sailing event" + oldEventName + ": " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createNewEvent(final EventDTO newEvent) {
|
||||
sailingService.createEvent(newEvent.name, newEvent.venue.name, newEvent.publicationUrl, newEvent.isPublic, new AsyncCallback<EventDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to create new event" + newEvent.name + ": " + t.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(EventDTO newEvent) {
|
||||
fillEvents();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fillEvents() {
|
||||
sailingService.getEvents(new AsyncCallback<List<EventDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Remote Procedure Call getEvents() - Failure: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<EventDTO> result) {
|
||||
eventProvider.getList().clear();
|
||||
eventProvider.getList().addAll(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.cell.client.FieldUpdater;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.cellview.client.CellTable;
|
||||
import com.google.gwt.user.cellview.client.TextColumn;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.HorizontalPanel;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.google.gwt.view.client.SelectionChangeEvent;
|
||||
import com.google.gwt.view.client.SingleSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
|
||||
/**
|
||||
* Allows administrators to manage data of a sailing event. This is a temporary panel because the managed event
|
||||
* is not connected with any regatta and it used only to manage of basic attributes of the an event.
|
||||
* @author Frank Mittag (C5163974)
|
||||
*
|
||||
*/
|
||||
public class SailingEventManagementPanel extends SimplePanel {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final ErrorReporter errorReporter;
|
||||
private final StringMessages stringMessages;
|
||||
|
||||
private CellTable<EventDTO> eventTable;
|
||||
private SingleSelectionModel<EventDTO> eventSelectionModel;
|
||||
private ListDataProvider<EventDTO> eventProvider;
|
||||
|
||||
private final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
|
||||
|
||||
public SailingEventManagementPanel(final SailingServiceAsync sailingService, final ErrorReporter errorReporter,
|
||||
final StringMessages stringMessages) {
|
||||
this.sailingService = sailingService;
|
||||
this.stringMessages = stringMessages;
|
||||
this.errorReporter = errorReporter;
|
||||
|
||||
VerticalPanel mainPanel = new VerticalPanel();
|
||||
this.setWidget(mainPanel);
|
||||
mainPanel.setWidth("100%");
|
||||
|
||||
HorizontalPanel eventsPanel = new HorizontalPanel();
|
||||
eventsPanel.setSpacing(5);
|
||||
mainPanel.add(eventsPanel);
|
||||
|
||||
Button createEventBtn = new Button(stringMessages.actionAddEvent());
|
||||
createEventBtn.addClickHandler(new ClickHandler() {
|
||||
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
openCreateEventDialog();
|
||||
}
|
||||
});
|
||||
eventsPanel.add(createEventBtn);
|
||||
|
||||
// sailing events table
|
||||
TextColumn<EventDTO> eventNameColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.name;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> venueNameColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.venue != null ? event.venue.name : "";
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> publicationUrlColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.publicationUrl;
|
||||
}
|
||||
};
|
||||
|
||||
TextColumn<EventDTO> isPublicColumn = new TextColumn<EventDTO>() {
|
||||
@Override
|
||||
public String getValue(EventDTO event) {
|
||||
return event.isPublic ? stringMessages.yes() : stringMessages.no();
|
||||
}
|
||||
};
|
||||
|
||||
ImagesBarColumn<EventDTO, RegattaConfigImagesBarCell> eventActionColumn = new ImagesBarColumn<EventDTO, RegattaConfigImagesBarCell>(
|
||||
new RegattaConfigImagesBarCell(stringMessages));
|
||||
eventActionColumn.setFieldUpdater(new FieldUpdater<EventDTO, String>() {
|
||||
@Override
|
||||
public void update(int index, EventDTO event, String value) {
|
||||
if (RegattaConfigImagesBarCell.ACTION_REMOVE.equals(value)) {
|
||||
if (Window.confirm(stringMessages.doYouReallyWantToRemoveRegatta(event.name))) {
|
||||
removeEvent(event);
|
||||
}
|
||||
} else if (RegattaConfigImagesBarCell.ACTION_EDIT.equals(value)) {
|
||||
openEditEventDialog(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
eventTable = new CellTable<EventDTO>(10000, tableRes);
|
||||
eventTable.addColumn(eventNameColumn, stringMessages.event());
|
||||
eventTable.addColumn(venueNameColumn, stringMessages.venue());
|
||||
eventTable.addColumn(publicationUrlColumn, stringMessages.publicationUrl());
|
||||
eventTable.addColumn(isPublicColumn, stringMessages.isPublic());
|
||||
eventTable.addColumn(eventActionColumn, stringMessages.actions());
|
||||
|
||||
eventSelectionModel = new SingleSelectionModel<EventDTO>();
|
||||
eventSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
|
||||
@Override
|
||||
public void onSelectionChange(SelectionChangeEvent event) {
|
||||
}
|
||||
});
|
||||
eventTable.setSelectionModel(eventSelectionModel);
|
||||
|
||||
eventProvider = new ListDataProvider<EventDTO>();
|
||||
eventProvider.addDataDisplay(eventTable);
|
||||
mainPanel.add(eventTable);
|
||||
|
||||
fillEvents();
|
||||
}
|
||||
|
||||
private void removeEvent(final EventDTO event) {
|
||||
sailingService.removeEvent(event.name, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Error trying to remove event " + event.name + ": " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void openCreateEventDialog() {
|
||||
List<EventDTO> existingEvents = new ArrayList<EventDTO>(eventProvider.getList());
|
||||
EventCreateDialog dialog = new EventCreateDialog(Collections.unmodifiableCollection(existingEvents), stringMessages,
|
||||
new DialogCallback<EventDTO>() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ok(EventDTO newEvent) {
|
||||
createNewEvent(newEvent);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void openEditEventDialog(final EventDTO selectedEvent) {
|
||||
List<EventDTO> existingEvents = new ArrayList<EventDTO>(eventProvider.getList());
|
||||
existingEvents.remove(selectedEvent);
|
||||
EventEditDialog dialog = new EventEditDialog(selectedEvent, Collections.unmodifiableCollection(existingEvents), stringMessages,
|
||||
new DialogCallback<EventDTO>() {
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ok(EventDTO updatedEvent) {
|
||||
updateEvent(selectedEvent.name, updatedEvent);
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void updateEvent(final String oldEventName, final EventDTO updatedEvent) {
|
||||
List<String> regattaNames = new ArrayList<String>();
|
||||
for(RegattaDTO regatta: updatedEvent.regattas) {
|
||||
regattaNames.add(regatta.name);
|
||||
}
|
||||
|
||||
sailingService.updateEvent(oldEventName, updatedEvent.venue, updatedEvent.publicationUrl, updatedEvent.isPublic,
|
||||
regattaNames, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to update sailing event" + oldEventName + ": " + t.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
if(!oldEventName.equals(updatedEvent.name)) {
|
||||
sailingService.renameEvent(oldEventName, updatedEvent.name, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
fillEvents();
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to rename sailing event" + oldEventName + ": " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createNewEvent(final EventDTO newEvent) {
|
||||
sailingService.createEvent(newEvent.name, newEvent.venue.name, newEvent.publicationUrl, newEvent.isPublic, new AsyncCallback<EventDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
errorReporter.reportError("Error trying to create new event" + newEvent.name + ": " + t.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(EventDTO newEvent) {
|
||||
fillEvents();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fillEvents() {
|
||||
sailingService.getEvents(new AsyncCallback<List<EventDTO>>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
errorReporter.reportError("Remote Procedure Call getEvents() - Failure: " + caught.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<EventDTO> result) {
|
||||
eventProvider.getList().clear();
|
||||
eventProvider.getList().addAll(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+256
-257
@@ -1,257 +1,256 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
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.IntegerBox;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
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.Color;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.FleetDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private SeriesDTO series;
|
||||
|
||||
private TextBox nameEntryField;
|
||||
private CheckBox isMedalSeriesCheckbox;
|
||||
|
||||
private List<TextBox> fleetNameEntryFields;
|
||||
private List<ListBox> fleetColorEntryFields;
|
||||
private List<IntegerBox> fleetOrderNoEntryFields;
|
||||
|
||||
private Grid fleetsGrid;
|
||||
|
||||
protected static class SeriesParameterValidator implements Validator<SeriesDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<SeriesDTO> existingSeries;
|
||||
|
||||
public SeriesParameterValidator(StringMessages stringConstants, Collection<SeriesDTO> existingSeries) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingSeries = new ArrayList<SeriesDTO>(existingSeries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(SeriesDTO seriesToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = seriesToValidate.name != null && seriesToValidate.name.length() > 0;
|
||||
boolean unique = true;
|
||||
for (SeriesDTO series : existingSeries) {
|
||||
if (series.name.equals(seriesToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.seriesWithThisNameAlreadyExists();
|
||||
}
|
||||
if (errorMessage == null) {
|
||||
List<FleetDTO> fleetsToValidate = seriesToValidate.getFleets();
|
||||
int index = 0;
|
||||
boolean fleetNameNotEmpty = true;
|
||||
for (FleetDTO fleet : fleetsToValidate) {
|
||||
fleetNameNotEmpty = fleet.name != null && fleet.name.length() > 0;
|
||||
if (!fleetNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
int index2 = 0;
|
||||
boolean fleetUnique = true;
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (FleetDTO fleet: fleetsToValidate) {
|
||||
if(!setToFindDuplicates.add(fleet.name)) {
|
||||
fleetUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
if (!fleetNameNotEmpty) {
|
||||
errorMessage = stringConstants.fleet() + " " + (index + 1) + ": " + stringConstants.pleaseEnterAName();
|
||||
} else if (!fleetUnique) {
|
||||
errorMessage = stringConstants.fleet() + " " + (index2 + 1) + ": " + stringConstants.fleetWithThisNameAlreadyExists();
|
||||
}
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public SeriesWithFleetsCreateDialog(Collection<SeriesDTO> existingSeries, StringMessages stringConstants,
|
||||
AsyncCallback<SeriesDTO> callback) {
|
||||
super(stringConstants.series(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new SeriesParameterValidator(stringConstants, existingSeries), callback);
|
||||
this.stringConstants = stringConstants;
|
||||
this.series = new SeriesDTO();
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setVisibleLength(40);
|
||||
isMedalSeriesCheckbox = createCheckbox(stringConstants.medalSeries());
|
||||
fleetNameEntryFields = new ArrayList<TextBox>();
|
||||
fleetColorEntryFields = new ArrayList<ListBox>();
|
||||
fleetOrderNoEntryFields = new ArrayList<IntegerBox>();
|
||||
fleetsGrid = new Grid(0, 0);
|
||||
// create at least one fleet
|
||||
addFleetWidget("Default", 0, null);
|
||||
}
|
||||
|
||||
private Widget createFleetNameWidget(String defaultName) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(40);
|
||||
textBox.setWidth("175px");
|
||||
fleetNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createFleetColorWidget(Color defaultColor) {
|
||||
final ListBox listBox = createListBox(false);
|
||||
final int fleetIndex = fleetNameEntryFields.size()-1;
|
||||
listBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
// set default order no of the selected color
|
||||
int selIndex = listBox.getSelectedIndex();
|
||||
IntegerBox orderNoBox = fleetOrderNoEntryFields.get(fleetIndex);
|
||||
TextBox nameBox = fleetNameEntryFields.get(fleetIndex);
|
||||
if (selIndex == 0) {
|
||||
orderNoBox.setValue(0);
|
||||
} else {
|
||||
String value = listBox.getValue(selIndex);
|
||||
final FleetColors color = FleetColors.valueOf(value);
|
||||
if (color != null) {
|
||||
orderNoBox.setValue(color.getDefaultOrderNo());
|
||||
nameBox.setValue(""+color.name().charAt(0)+color.name().toLowerCase().substring(1));
|
||||
}
|
||||
}
|
||||
validate();
|
||||
}
|
||||
});
|
||||
listBox.addItem(stringConstants.noColor());
|
||||
for(FleetColors value: FleetColors.values()) {
|
||||
listBox.addItem(value.name());
|
||||
}
|
||||
if(defaultColor == null) {
|
||||
listBox.setSelectedIndex(0);
|
||||
}
|
||||
fleetColorEntryFields.add(listBox);
|
||||
return listBox;
|
||||
}
|
||||
|
||||
private Widget createFleetOrderNoWidget(int defaultValue) {
|
||||
IntegerBox intBox = createIntegerBox(defaultValue, 3);
|
||||
fleetOrderNoEntryFields.add(intBox);
|
||||
return intBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SeriesDTO getResult() {
|
||||
series.name = nameEntryField.getText();
|
||||
series.setMedal(isMedalSeriesCheckbox.getValue());
|
||||
List<FleetDTO> fleets = new ArrayList<FleetDTO>();
|
||||
int fleetsCount = fleetNameEntryFields.size();
|
||||
for(int i = 0; i < fleetsCount; i++) {
|
||||
FleetDTO fleetDTO = new FleetDTO();
|
||||
fleetDTO.name = fleetNameEntryFields.get(i).getValue();
|
||||
fleetDTO.setColor(getSelectedColor(fleetColorEntryFields.get(i)));
|
||||
int orderNo = -1;
|
||||
if(fleetOrderNoEntryFields.get(i).getValue() != null) {
|
||||
orderNo = fleetOrderNoEntryFields.get(i).getValue();
|
||||
}
|
||||
fleetDTO.setOrderNo(orderNo);
|
||||
fleets.add(fleetDTO);
|
||||
}
|
||||
series.setFleets(fleets);
|
||||
return series;
|
||||
}
|
||||
|
||||
private Color getSelectedColor(ListBox colorListBox) {
|
||||
Color result = null;
|
||||
int selIndex = colorListBox.getSelectedIndex();
|
||||
// the zero index represents the 'no color' option
|
||||
if(selIndex > 0) {
|
||||
String value = colorListBox.getValue(selIndex);
|
||||
for(FleetColors color: FleetColors.values()) {
|
||||
if(color.name().equals(value)) {
|
||||
result = color.getColor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
final VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
Grid formGrid = new Grid(2, 2);
|
||||
panel.add(formGrid);
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 1, isMedalSeriesCheckbox);
|
||||
panel.add(createHeadlineLabel(stringConstants.fleets()));
|
||||
panel.add(fleetsGrid);
|
||||
Button addFleetButton = new Button(stringConstants.addFleet());
|
||||
addFleetButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
addFleetWidget(null, 0, null);
|
||||
updateFleetsGrid(panel);
|
||||
}
|
||||
});
|
||||
panel.add(addFleetButton);
|
||||
updateFleetsGrid(panel);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void addFleetWidget(String fleetName, int ordering, Color color) {
|
||||
createFleetNameWidget(fleetName);
|
||||
createFleetOrderNoWidget(ordering);
|
||||
createFleetColorWidget(color);
|
||||
}
|
||||
|
||||
private void updateFleetsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(fleetsGrid);
|
||||
parentPanel.remove(fleetsGrid);
|
||||
int fleetCount = fleetNameEntryFields.size();
|
||||
fleetsGrid = new Grid(fleetCount + 1, 3);
|
||||
fleetsGrid.setCellSpacing(4);
|
||||
fleetsGrid.setHTML(0, 0, stringConstants.color());
|
||||
fleetsGrid.setHTML(0, 1, stringConstants.name());
|
||||
fleetsGrid.setHTML(0, 2, stringConstants.rank());
|
||||
for(int i = 0; i < fleetCount; i++) {
|
||||
fleetsGrid.setWidget(i+1, 0, fleetColorEntryFields.get(i));
|
||||
fleetsGrid.setWidget(i+1, 1, fleetNameEntryFields.get(i));
|
||||
fleetsGrid.setWidget(i+1, 2, fleetOrderNoEntryFields.get(i));
|
||||
}
|
||||
parentPanel.insert(fleetsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.event.dom.client.ChangeEvent;
|
||||
import com.google.gwt.event.dom.client.ChangeHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.IntegerBox;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
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.Color;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.shared.FleetDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
|
||||
|
||||
public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private SeriesDTO series;
|
||||
|
||||
private TextBox nameEntryField;
|
||||
private CheckBox isMedalSeriesCheckbox;
|
||||
|
||||
private List<TextBox> fleetNameEntryFields;
|
||||
private List<ListBox> fleetColorEntryFields;
|
||||
private List<IntegerBox> fleetOrderNoEntryFields;
|
||||
|
||||
private Grid fleetsGrid;
|
||||
|
||||
protected static class SeriesParameterValidator implements Validator<SeriesDTO> {
|
||||
|
||||
private StringMessages stringConstants;
|
||||
private ArrayList<SeriesDTO> existingSeries;
|
||||
|
||||
public SeriesParameterValidator(StringMessages stringConstants, Collection<SeriesDTO> existingSeries) {
|
||||
this.stringConstants = stringConstants;
|
||||
this.existingSeries = new ArrayList<SeriesDTO>(existingSeries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMessage(SeriesDTO seriesToValidate) {
|
||||
String errorMessage = null;
|
||||
boolean nameNotEmpty = seriesToValidate.name != null && seriesToValidate.name.length() > 0;
|
||||
boolean unique = true;
|
||||
for (SeriesDTO series : existingSeries) {
|
||||
if (series.name.equals(seriesToValidate.name)) {
|
||||
unique = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nameNotEmpty) {
|
||||
errorMessage = stringConstants.pleaseEnterAName();
|
||||
} else if (!unique) {
|
||||
errorMessage = stringConstants.seriesWithThisNameAlreadyExists();
|
||||
}
|
||||
if (errorMessage == null) {
|
||||
List<FleetDTO> fleetsToValidate = seriesToValidate.getFleets();
|
||||
int index = 0;
|
||||
boolean fleetNameNotEmpty = true;
|
||||
for (FleetDTO fleet : fleetsToValidate) {
|
||||
fleetNameNotEmpty = fleet.name != null && fleet.name.length() > 0;
|
||||
if (!fleetNameNotEmpty) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
int index2 = 0;
|
||||
boolean fleetUnique = true;
|
||||
HashSet<String> setToFindDuplicates = new HashSet<String>();
|
||||
for (FleetDTO fleet: fleetsToValidate) {
|
||||
if(!setToFindDuplicates.add(fleet.name)) {
|
||||
fleetUnique = false;
|
||||
break;
|
||||
}
|
||||
index2++;
|
||||
}
|
||||
if (!fleetNameNotEmpty) {
|
||||
errorMessage = stringConstants.fleet() + " " + (index + 1) + ": " + stringConstants.pleaseEnterAName();
|
||||
} else if (!fleetUnique) {
|
||||
errorMessage = stringConstants.fleet() + " " + (index2 + 1) + ": " + stringConstants.fleetWithThisNameAlreadyExists();
|
||||
}
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public SeriesWithFleetsCreateDialog(Collection<SeriesDTO> existingSeries, StringMessages stringConstants,
|
||||
DialogCallback<SeriesDTO> callback) {
|
||||
super(stringConstants.series(), null, stringConstants.ok(), stringConstants.cancel(),
|
||||
new SeriesParameterValidator(stringConstants, existingSeries), callback);
|
||||
this.stringConstants = stringConstants;
|
||||
this.series = new SeriesDTO();
|
||||
nameEntryField = createTextBox(null);
|
||||
nameEntryField.setVisibleLength(40);
|
||||
isMedalSeriesCheckbox = createCheckbox(stringConstants.medalSeries());
|
||||
fleetNameEntryFields = new ArrayList<TextBox>();
|
||||
fleetColorEntryFields = new ArrayList<ListBox>();
|
||||
fleetOrderNoEntryFields = new ArrayList<IntegerBox>();
|
||||
fleetsGrid = new Grid(0, 0);
|
||||
// create at least one fleet
|
||||
addFleetWidget("Default", 0, null);
|
||||
}
|
||||
|
||||
private Widget createFleetNameWidget(String defaultName) {
|
||||
TextBox textBox = createTextBox(defaultName);
|
||||
textBox.setVisibleLength(40);
|
||||
textBox.setWidth("175px");
|
||||
fleetNameEntryFields.add(textBox);
|
||||
return textBox;
|
||||
}
|
||||
|
||||
private Widget createFleetColorWidget(Color defaultColor) {
|
||||
final ListBox listBox = createListBox(false);
|
||||
final int fleetIndex = fleetNameEntryFields.size()-1;
|
||||
listBox.addChangeHandler(new ChangeHandler() {
|
||||
@Override
|
||||
public void onChange(ChangeEvent event) {
|
||||
// set default order no of the selected color
|
||||
int selIndex = listBox.getSelectedIndex();
|
||||
IntegerBox orderNoBox = fleetOrderNoEntryFields.get(fleetIndex);
|
||||
TextBox nameBox = fleetNameEntryFields.get(fleetIndex);
|
||||
if (selIndex == 0) {
|
||||
orderNoBox.setValue(0);
|
||||
} else {
|
||||
String value = listBox.getValue(selIndex);
|
||||
final FleetColors color = FleetColors.valueOf(value);
|
||||
if (color != null) {
|
||||
orderNoBox.setValue(color.getDefaultOrderNo());
|
||||
nameBox.setValue(""+color.name().charAt(0)+color.name().toLowerCase().substring(1));
|
||||
}
|
||||
}
|
||||
validate();
|
||||
}
|
||||
});
|
||||
listBox.addItem(stringConstants.noColor());
|
||||
for(FleetColors value: FleetColors.values()) {
|
||||
listBox.addItem(value.name());
|
||||
}
|
||||
if(defaultColor == null) {
|
||||
listBox.setSelectedIndex(0);
|
||||
}
|
||||
fleetColorEntryFields.add(listBox);
|
||||
return listBox;
|
||||
}
|
||||
|
||||
private Widget createFleetOrderNoWidget(int defaultValue) {
|
||||
IntegerBox intBox = createIntegerBox(defaultValue, 3);
|
||||
fleetOrderNoEntryFields.add(intBox);
|
||||
return intBox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SeriesDTO getResult() {
|
||||
series.name = nameEntryField.getText();
|
||||
series.setMedal(isMedalSeriesCheckbox.getValue());
|
||||
List<FleetDTO> fleets = new ArrayList<FleetDTO>();
|
||||
int fleetsCount = fleetNameEntryFields.size();
|
||||
for(int i = 0; i < fleetsCount; i++) {
|
||||
FleetDTO fleetDTO = new FleetDTO();
|
||||
fleetDTO.name = fleetNameEntryFields.get(i).getValue();
|
||||
fleetDTO.setColor(getSelectedColor(fleetColorEntryFields.get(i)));
|
||||
int orderNo = -1;
|
||||
if(fleetOrderNoEntryFields.get(i).getValue() != null) {
|
||||
orderNo = fleetOrderNoEntryFields.get(i).getValue();
|
||||
}
|
||||
fleetDTO.setOrderNo(orderNo);
|
||||
fleets.add(fleetDTO);
|
||||
}
|
||||
series.setFleets(fleets);
|
||||
return series;
|
||||
}
|
||||
|
||||
private Color getSelectedColor(ListBox colorListBox) {
|
||||
Color result = null;
|
||||
int selIndex = colorListBox.getSelectedIndex();
|
||||
// the zero index represents the 'no color' option
|
||||
if(selIndex > 0) {
|
||||
String value = colorListBox.getValue(selIndex);
|
||||
for(FleetColors color: FleetColors.values()) {
|
||||
if(color.name().equals(value)) {
|
||||
result = color.getColor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Widget getAdditionalWidget() {
|
||||
final VerticalPanel panel = new VerticalPanel();
|
||||
Widget additionalWidget = super.getAdditionalWidget();
|
||||
if (additionalWidget != null) {
|
||||
panel.add(additionalWidget);
|
||||
}
|
||||
Grid formGrid = new Grid(2, 2);
|
||||
panel.add(formGrid);
|
||||
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
|
||||
formGrid.setWidget(0, 1, nameEntryField);
|
||||
formGrid.setWidget(1, 1, isMedalSeriesCheckbox);
|
||||
panel.add(createHeadlineLabel(stringConstants.fleets()));
|
||||
panel.add(fleetsGrid);
|
||||
Button addFleetButton = new Button(stringConstants.addFleet());
|
||||
addFleetButton.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
addFleetWidget(null, 0, null);
|
||||
updateFleetsGrid(panel);
|
||||
}
|
||||
});
|
||||
panel.add(addFleetButton);
|
||||
updateFleetsGrid(panel);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private void addFleetWidget(String fleetName, int ordering, Color color) {
|
||||
createFleetNameWidget(fleetName);
|
||||
createFleetOrderNoWidget(ordering);
|
||||
createFleetColorWidget(color);
|
||||
}
|
||||
|
||||
private void updateFleetsGrid(VerticalPanel parentPanel) {
|
||||
int widgetIndex = parentPanel.getWidgetIndex(fleetsGrid);
|
||||
parentPanel.remove(fleetsGrid);
|
||||
int fleetCount = fleetNameEntryFields.size();
|
||||
fleetsGrid = new Grid(fleetCount + 1, 3);
|
||||
fleetsGrid.setCellSpacing(4);
|
||||
fleetsGrid.setHTML(0, 0, stringConstants.color());
|
||||
fleetsGrid.setHTML(0, 1, stringConstants.name());
|
||||
fleetsGrid.setHTML(0, 2, stringConstants.rank());
|
||||
for(int i = 0; i < fleetCount; i++) {
|
||||
fleetsGrid.setWidget(i+1, 0, fleetColorEntryFields.get(i));
|
||||
fleetsGrid.setWidget(i+1, 1, fleetNameEntryFields.get(i));
|
||||
fleetsGrid.setWidget(i+1, 2, fleetOrderNoEntryFields.get(i));
|
||||
}
|
||||
parentPanel.insert(fleetsGrid, widgetIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
nameEntryField.setFocus(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -297,7 +297,7 @@ public class TrackedRacesListComposite extends SimplePanel implements Component<
|
||||
TextColumn<RaceDTO> hasWindDataColumn = new TextColumn<RaceDTO>() {
|
||||
@Override
|
||||
public String getValue(RaceDTO raceDTO) {
|
||||
if (raceDTO.isTracked && raceDTO.trackedRace.hasWindData == true)
|
||||
if (raceDTO.isTracked && raceDTO.trackedRace != null && raceDTO.trackedRace.hasWindData == true)
|
||||
return stringMessages.yes();
|
||||
else
|
||||
return stringMessages.no();
|
||||
@@ -307,7 +307,7 @@ public class TrackedRacesListComposite extends SimplePanel implements Component<
|
||||
TextColumn<RaceDTO> hasGPSDataColumn = new TextColumn<RaceDTO>() {
|
||||
@Override
|
||||
public String getValue(RaceDTO raceDTO) {
|
||||
if (raceDTO.isTracked && raceDTO.trackedRace.hasGPSData == true)
|
||||
if (raceDTO.isTracked && raceDTO.trackedRace != null && raceDTO.trackedRace.hasGPSData == true)
|
||||
return stringMessages.yes();
|
||||
else
|
||||
return stringMessages.no();
|
||||
|
||||
+4
-3
@@ -32,6 +32,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.WindSource;
|
||||
import com.sap.sailing.domain.common.WindSourceType;
|
||||
import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
|
||||
@@ -215,13 +216,13 @@ public class WindPanel extends FormPanel implements RegattaDisplayer, WindShower
|
||||
|
||||
private void showWindSettingDialog(RaceDTO race, CourseDTO course) {
|
||||
WindSettingDialog windSettingDialog = new WindSettingDialog(race, course, stringMessages,
|
||||
new AsyncCallback<WindDTO>() {
|
||||
new DialogCallback<WindDTO>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final WindDTO result) {
|
||||
public void ok(final WindDTO result) {
|
||||
addWindFix(result);
|
||||
}
|
||||
});
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.adminconsole;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.DoubleBox;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
@@ -55,7 +54,7 @@ public class WindSettingDialog extends DataEntryDialog<WindDTO> {
|
||||
}
|
||||
}
|
||||
|
||||
public WindSettingDialog(RaceDTO race, CourseDTO courseDTO, StringMessages stringMessages, AsyncCallback<WindDTO> callback) {
|
||||
public WindSettingDialog(RaceDTO race, CourseDTO courseDTO, StringMessages stringMessages, DialogCallback<WindDTO> callback) {
|
||||
super(stringMessages.actionAddWindData(), null, stringMessages.ok(), stringMessages.cancel(), new WindDataValidator(stringMessages), callback);
|
||||
this.stringMessages = stringMessages;
|
||||
speedInKnotsBox = createDoubleBox(5);
|
||||
|
||||
+9
-4
@@ -49,6 +49,11 @@ public abstract class DataEntryDialog<T> {
|
||||
*/
|
||||
String getErrorMessage(T valueToValidate);
|
||||
}
|
||||
|
||||
public static interface DialogCallback<T> {
|
||||
void ok(T editedObject);
|
||||
void cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param validator
|
||||
@@ -60,7 +65,7 @@ public abstract class DataEntryDialog<T> {
|
||||
* {@link AsyncCallback#onSuccess(Object) confirmed}
|
||||
*/
|
||||
public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
|
||||
Validator<T> validator, final AsyncCallback<T> callback) {
|
||||
Validator<T> validator, final DialogCallback<T> callback) {
|
||||
this(title, message, okButtonName, cancelButtonName, validator, /* animationEnabled */ true, callback);
|
||||
}
|
||||
|
||||
@@ -74,7 +79,7 @@ public abstract class DataEntryDialog<T> {
|
||||
* {@link AsyncCallback#onSuccess(Object) confirmed}
|
||||
*/
|
||||
public DataEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
|
||||
Validator<T> validator, boolean animationEnabled, final AsyncCallback<T> callback) {
|
||||
Validator<T> validator, boolean animationEnabled, final DialogCallback<T> callback) {
|
||||
dateEntryDialog = new DialogBox();
|
||||
dateEntryDialog.setText(title);
|
||||
dateEntryDialog.setAnimationEnabled(animationEnabled);
|
||||
@@ -103,14 +108,14 @@ public abstract class DataEntryDialog<T> {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
dateEntryDialog.hide();
|
||||
callback.onFailure(null);
|
||||
callback.cancel();
|
||||
}
|
||||
});
|
||||
dateEntryDialog.setWidget(dialogFPanel);
|
||||
okButton.addClickHandler(new ClickHandler() {
|
||||
public void onClick(ClickEvent event) {
|
||||
dateEntryDialog.hide();
|
||||
callback.onSuccess(getResult());
|
||||
callback.ok(getResult());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+5
-5
@@ -18,8 +18,8 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
private boolean autoAdjustPlayMode;
|
||||
private RaceTimesInfoDTO lastRaceTimesInfo;
|
||||
|
||||
public RaceTimePanel(Timer timer, StringMessages stringMessages, RaceTimesInfoProvider raceTimesInfoProvider) {
|
||||
super(timer, stringMessages);
|
||||
public RaceTimePanel(Timer timer, TimeRangeProvider timeRangeProvider, StringMessages stringMessages, RaceTimesInfoProvider raceTimesInfoProvider) {
|
||||
super(timer, timeRangeProvider, stringMessages);
|
||||
this.raceTimesInfoProvider = raceTimesInfoProvider;
|
||||
selectedRace = null;
|
||||
autoAdjustPlayMode = true;
|
||||
@@ -66,7 +66,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
timer.setPlayMode(PlayModes.Live);
|
||||
}
|
||||
|
||||
boolean timerAlreadyInitialized = getMin() != null && getMax() != null && timeSlider.getCurrentValue() != null;
|
||||
boolean timerAlreadyInitialized = getFromTime() != null && getToTime() != null && timeSlider.getCurrentValue() != null;
|
||||
if (!isTimeZoomed) {
|
||||
updateMinMax(raceTimesInfo);
|
||||
if (!timerAlreadyInitialized) {
|
||||
@@ -83,7 +83,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeZoom(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
isTimeZoomed = true;
|
||||
timeSlider.setZoomed(true);
|
||||
timer.setAutoAdvance(false);
|
||||
@@ -151,7 +151,7 @@ public class RaceTimePanel extends TimePanel<RaceTimePanelSettings> implements R
|
||||
Date max = raceMinMax.getB();
|
||||
|
||||
// never reduce max if it was already set
|
||||
if (min != null && max != null && (getMax() == null || getMax().before(max))) {
|
||||
if (min != null && max != null && (getToTime() == null || getToTime().before(max))) {
|
||||
setMinMax(min, max, /* fireEvent */ false); // no event because we guarantee time to be between min and max
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -31,6 +31,7 @@ import com.sap.sailing.gwt.ui.shared.ManeuverDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.MultiCompetitorRaceDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceBuoysDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
@@ -141,19 +142,17 @@ public interface SailingService extends RemoteService {
|
||||
|
||||
void removeRegatta(RegattaIdentifier regattaIdentifier);
|
||||
|
||||
void addColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
|
||||
List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
|
||||
|
||||
void addColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
RaceColumnInSeriesDTO addRaceColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
|
||||
void removeColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
|
||||
void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames);
|
||||
|
||||
void removeColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
void removeRaceColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
|
||||
void renameColumnInSeries(RegattaIdentifier regattaIdentifier, String seriesName, String oldColumnName, String newColumnName);
|
||||
void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
|
||||
void moveColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
|
||||
void moveColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName);
|
||||
|
||||
boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName,
|
||||
String fleetName, RegattaAndRaceIdentifier raceIdentifier);
|
||||
|
||||
+10
-13
@@ -24,6 +24,7 @@ import com.sap.sailing.gwt.ui.shared.ControlPointDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.CourseDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.EventDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceBuoysDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.GPSFixDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
|
||||
@@ -370,30 +371,26 @@ public interface SailingServiceAsync {
|
||||
|
||||
void removeRegatta(RegattaIdentifier regattaIdentifier, AsyncCallback<Void> callback);
|
||||
|
||||
void addColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName, AsyncCallback<Void> callback);
|
||||
void addRaceColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
AsyncCallback<RaceColumnInSeriesDTO> callback);
|
||||
|
||||
void removeColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
void removeRaceColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void renameColumnInSeries(RegattaIdentifier regattaIdentifier, String seriesName, String oldColumnName,
|
||||
String newColumnName, AsyncCallback<Void> callback);
|
||||
|
||||
void moveColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void moveColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void createRegatta(
|
||||
String regattaName,
|
||||
String boatClassName,
|
||||
void createRegatta(String regattaName, String boatClassName,
|
||||
LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
|
||||
boolean persistent, ScoringSchemeType scoringSchemeType, AsyncCallback<RegattaDTO> callback);
|
||||
|
||||
void addColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
|
||||
AsyncCallback<Void> callback);
|
||||
void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
|
||||
AsyncCallback<List<RaceColumnInSeriesDTO>> callback);
|
||||
|
||||
void removeColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
|
||||
void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
|
||||
AsyncCallback<Void> callback);
|
||||
|
||||
void getScoreCorrectionProviderDTOs(AsyncCallback<Iterable<ScoreCorrectionProviderDTO>> callback);
|
||||
|
||||
+3
@@ -173,6 +173,7 @@ public interface StringMessages extends Messages {
|
||||
String delete();
|
||||
String showCharts();
|
||||
String raceWithThisNameAlreadyExists();
|
||||
String raceWithThisNameAlreadyExistsInRegatta();
|
||||
String headUp();
|
||||
String bearAway();
|
||||
String tack();
|
||||
@@ -382,6 +383,7 @@ public interface StringMessages extends Messages {
|
||||
String useOverallLeaderboard();
|
||||
String overallStandings();
|
||||
String scoringSchemeHighPointEssOverall();
|
||||
String scoringSchemeHighPointLastBreaksTie();
|
||||
String type();
|
||||
String actionAddRaces();
|
||||
String racesWithNamePrefix();
|
||||
@@ -402,4 +404,5 @@ public interface StringMessages extends Messages {
|
||||
String isPublic();
|
||||
String unsuppress();
|
||||
String suppressedCompetitors();
|
||||
String pleaseSelectASeries();
|
||||
}
|
||||
|
||||
+5
-2
@@ -168,7 +168,8 @@ no3LetterCodes=Unable to find the IOC 3-letter-codes.
|
||||
add=Add
|
||||
delete=Delete
|
||||
showCharts=Show charts
|
||||
raceWithThisNameAlreadyExists=A race with that name already exists
|
||||
raceWithThisNameAlreadyExists=A race with that name already exists.
|
||||
raceWithThisNameAlreadyExistsInRegatta=A race with that name already exists in this regatta.
|
||||
headUp=Head up
|
||||
bearAway=Bear away
|
||||
tack=Tack
|
||||
@@ -375,6 +376,7 @@ insertWaypointAfterSelected=Insert waypoint after selected
|
||||
scoringSchemeLowPointSystem=Low Point System
|
||||
scoringSchemeHighPointSystem=High Point System
|
||||
scoringSchemeHighPointEssOverall=High Point System ESS Overall
|
||||
scoringSchemeHighPointLastBreaksTie=High Point System, Last Race Breaks Tie
|
||||
scoringSystem=Scoring system
|
||||
createFlexibleLeaderboard=Create flexible leaderboard
|
||||
createRegattaLeaderboard=Create regatta leaderboard
|
||||
@@ -402,5 +404,6 @@ suppress=Suppress
|
||||
isPublic=Is public
|
||||
suppress=Suppress
|
||||
unsuppress=Unsuppress
|
||||
suppressedCompetitors=Suppressed Competitors
|
||||
suppressedCompetitors=Suppressed Competitors
|
||||
pleaseSelectASeries=Please select a series.
|
||||
|
||||
|
||||
+4
-2
@@ -170,7 +170,8 @@ no3LetterCodes=IOC 3-Buchstaben-Codes können nicht gefunden werden.
|
||||
add=Hinzufügen
|
||||
delete=Löschen
|
||||
showCharts=Grafische Ansicht
|
||||
raceWithThisNameAlreadyExists=Ein Rennen mit diesem Namen existiert schon
|
||||
raceWithThisNameAlreadyExists=Ein Rennen mit diesem Namen existiert schon.
|
||||
raceWithThisNameAlreadyExistsInRegatta=Ein Rennen mit diesem Namen existiert schon in der Regatta.
|
||||
headUp=anluven
|
||||
bearAway=abfallen
|
||||
tack=Wende
|
||||
@@ -376,6 +377,7 @@ insertWaypointAfterSelected=Wegpunkt vor dem selektierten einfügen
|
||||
scoringSchemeLowPointSystem=Low Point System
|
||||
scoringSchemeHighPointSystem=High Point System
|
||||
scoringSchemeHighPointEssOverall=High Point System ESS Gesamtwertung
|
||||
scoringSchemeHighPointLastBreaksTie=High Point System, letztes Rennen entscheidet bei Gleichstand
|
||||
scoringSystem=Bepunktungssystem
|
||||
createFlexibleLeaderboard=Flexible Rangliste anlegen
|
||||
createRegattaLeaderboard=Rangliste für Regatta anlegen
|
||||
@@ -404,4 +406,4 @@ isPublic=Öffentlich zugänglich
|
||||
suppress=Entfernen
|
||||
unsuppress=Wieder hinzufügen
|
||||
suppressedCompetitors=Unterdrückte Wettkampfteilnehmer
|
||||
|
||||
pleaseSelectASeries=Bitte wählen Sie eine Serie aus.
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
@@ -15,7 +14,7 @@ public class TextfieldEntryDialog extends DataEntryDialog<String> {
|
||||
private final TextBox entryField;
|
||||
|
||||
public TextfieldEntryDialog(String title, String message, String okButtonName, String cancelButtonName,
|
||||
String initialValue, final Validator<String> validator, final AsyncCallback<String> callback) {
|
||||
String initialValue, final Validator<String> validator, final DialogCallback<String> callback) {
|
||||
super(title, message, okButtonName, cancelButtonName, validator, callback);
|
||||
entryField = createTextBox(initialValue);
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.TextBox;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
@@ -12,7 +11,7 @@ public class TextfieldEntryDialogWithCheckbox extends DataEntryDialog<Pair<Strin
|
||||
private final TextBox entryField;
|
||||
|
||||
public TextfieldEntryDialogWithCheckbox(String title, String message, String okButtonName, String cancelButtonName,
|
||||
String checkboxLabel, String initialValue, Validator<Pair<String, Boolean>> validator, AsyncCallback<Pair<String, Boolean>> callback) {
|
||||
String checkboxLabel, String initialValue, Validator<Pair<String, Boolean>> validator, DialogCallback<Pair<String, Boolean>> callback) {
|
||||
super(title, message, okButtonName, cancelButtonName, validator, callback);
|
||||
checkbox = createCheckbox(checkboxLabel);
|
||||
entryField = createTextBox(initialValue);
|
||||
|
||||
+36
-37
@@ -31,23 +31,10 @@ import com.sap.sailing.gwt.ui.shared.controls.slider.SliderBar;
|
||||
import com.sap.sailing.gwt.ui.shared.controls.slider.TimeSlider;
|
||||
|
||||
public class TimePanel<T extends TimePanelSettings> extends FormPanel implements Component<T>, TimeListener, TimeZoomChangeListener,
|
||||
PlayStateListener, RequiresResize {
|
||||
TimeRangeChangeListener, PlayStateListener, RequiresResize {
|
||||
protected final Timer timer;
|
||||
protected boolean isTimeZoomed;
|
||||
|
||||
/**
|
||||
* The start time point of the time interval visualized by this time panel. May be <code>null</code> if not yet initialized.
|
||||
*
|
||||
* @see #setMinMax(Date, Date, boolean)
|
||||
*/
|
||||
private Date min;
|
||||
|
||||
/**
|
||||
* The end time point of the time interval visualized by this time panel. May be <code>null</code> if not yet initialized.
|
||||
*
|
||||
* @see #setMinMax(Date, Date, boolean)
|
||||
*/
|
||||
private Date max;
|
||||
protected final TimeRangeProvider timeRangeProvider;
|
||||
|
||||
private final IntegerBox playSpeedBox;
|
||||
private final Label timeDelayLabel;
|
||||
@@ -67,7 +54,7 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
private final Image playModeImage;
|
||||
protected Date lastReceivedDataTimepoint;
|
||||
private final Button slowDownButton;
|
||||
private final Button speedUpButton;
|
||||
private final Button speedUpButton;
|
||||
|
||||
/**
|
||||
* The live delay may be adjusted automatically if the server decides so. However, if the user explicitly sets a live delay,
|
||||
@@ -96,12 +83,14 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
}
|
||||
}
|
||||
|
||||
public TimePanel(Timer timer, StringMessages stringMessages) {
|
||||
public TimePanel(Timer timer, TimeRangeProvider timeRangeProvider, StringMessages stringMessages) {
|
||||
this.timer = timer;
|
||||
this.timeRangeProvider = timeRangeProvider;
|
||||
this.stringMessages = stringMessages;
|
||||
isTimeZoomed = false;
|
||||
timer.addTimeListener(this);
|
||||
timer.addPlayStateListener(this);
|
||||
timer.addPlayStateListener(this);
|
||||
timeRangeProvider.addTimeRangeChangeListener(this);
|
||||
userExplicitlyChangedLivePlayDelay = false;
|
||||
FlowPanel timePanelInnerWrapper = new FlowPanel();
|
||||
timePanelInnerWrapper.setStyleName("timePanelInnerWrapper");
|
||||
@@ -296,16 +285,21 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
|
||||
@Override
|
||||
public void timeChanged(Date time) {
|
||||
if (getMin() != null && getMax() != null) {
|
||||
// Handle also the case where time advances beyond slider's end.
|
||||
// Handle it equally for replay and live mode for robustness reasons. This at least allows a user
|
||||
// to watch on even if the time panel was off in its assumptions about race end and end of tracking.
|
||||
if (time.after(getMax())) {
|
||||
Date newMaxTime = new Date(time.getTime());
|
||||
if (newMaxTime.getTime() - getMax().getTime() < MINIMUM_AUTO_ADVANCE_TIME_IN_MS) {
|
||||
newMaxTime.setTime(getMax().getTime() + MINIMUM_AUTO_ADVANCE_TIME_IN_MS);
|
||||
if (getFromTime() != null && getToTime() != null) {
|
||||
// handle the case where time advances beyond slider's end.
|
||||
if (time.after(getToTime())) {
|
||||
switch (timer.getPlayMode()) {
|
||||
case Live:
|
||||
Date newMaxTime = new Date(time.getTime());
|
||||
if (newMaxTime.getTime() - getToTime().getTime() < MINIMUM_AUTO_ADVANCE_TIME_IN_MS) {
|
||||
newMaxTime.setTime(getToTime().getTime() + MINIMUM_AUTO_ADVANCE_TIME_IN_MS);
|
||||
}
|
||||
setMinMax(getFromTime(), newMaxTime, /* fireEvent */ false); // no event because we guarantee that time is between min/max
|
||||
break;
|
||||
case Replay:
|
||||
timer.stop();
|
||||
break;
|
||||
}
|
||||
setMinMax(getMin(), newMaxTime, /* fireEvent */ false); // no event because we guarantee that time is between min/max
|
||||
}
|
||||
long t = time.getTime();
|
||||
timeSlider.setCurrentValue(new Double(t), false);
|
||||
@@ -318,12 +312,12 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
}
|
||||
}
|
||||
|
||||
protected Date getMin() {
|
||||
return min;
|
||||
protected Date getFromTime() {
|
||||
return timeRangeProvider.getFromTime();
|
||||
}
|
||||
|
||||
protected Date getMax() {
|
||||
return max;
|
||||
protected Date getToTime() {
|
||||
return timeRangeProvider.getToTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,20 +328,20 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
assert min != null && max != null;
|
||||
|
||||
boolean changed = false;
|
||||
if (!max.equals(this.max)) {
|
||||
if (!max.equals(timeRangeProvider.getToTime())) {
|
||||
changed = true;
|
||||
this.max = max;
|
||||
timeSlider.setMaxValue(new Double(max.getTime()), fireEvent);
|
||||
}
|
||||
if (!min.equals(this.min)) {
|
||||
if (!min.equals(timeRangeProvider.getFromTime())) {
|
||||
changed = true;
|
||||
this.min = min;
|
||||
timeSlider.setMinValue(new Double(min.getTime()), fireEvent);
|
||||
if (timeSlider.getCurrentValue() == null) {
|
||||
timeSlider.setCurrentValue(new Double(min.getTime()), fireEvent);
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
timeRangeProvider.setTimeRange(min, max, this);
|
||||
|
||||
int numSteps = timeSlider.getElement().getClientWidth();
|
||||
if (numSteps > 0) {
|
||||
timeSlider.setStepSize(numSteps, fireEvent);
|
||||
@@ -379,6 +373,7 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
case Paused:
|
||||
playPauseButton.getElement().removeClassName("playPauseButtonPause");
|
||||
case Stopped:
|
||||
playPauseButton.getElement().removeClassName("playPauseButtonPause");
|
||||
playModeImage.setResource(playModeInactiveImg);
|
||||
break;
|
||||
}
|
||||
@@ -406,13 +401,17 @@ public class TimePanel<T extends TimePanelSettings> extends FormPanel implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeZoom(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeZoomReset() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTimeRangeChanged(Date fromTime, Date toTime) {
|
||||
}
|
||||
|
||||
protected boolean isLiveModeToBeMadePossible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface TimeRangeChangeListener {
|
||||
void onTimeRangeChanged(Date fromTime, Date toTime);
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
|
||||
public class TimeRangeModel implements TimeRangeProvider {
|
||||
|
||||
/**
|
||||
* The 'from' time of the time interval. May be <code>null</code> if not yet initialized.
|
||||
*/
|
||||
protected Date fromTime;
|
||||
|
||||
/**
|
||||
* The 'to' time of the time interval. May be <code>null</code> if not yet initialized.
|
||||
*/
|
||||
protected Date toTime;
|
||||
|
||||
protected final Set<TimeRangeChangeListener> listeners;
|
||||
|
||||
public TimeRangeModel() {
|
||||
listeners = new HashSet<TimeRangeChangeListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTimeRangeChangeListener(TimeRangeChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTimeRangeChangeListener(TimeRangeChangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setTimeRange(final Date fromTime, final Date toTime, TimeRangeChangeListener... listenersNotToNotify) {
|
||||
this.fromTime = fromTime != null ? new Date(fromTime.getTime()) : null;
|
||||
this.toTime = toTime != null ? new Date(toTime.getTime()) : null;
|
||||
|
||||
for (TimeRangeChangeListener listener : listeners) {
|
||||
if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) {
|
||||
listener.onTimeRangeChanged(fromTime, toTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<Date, Date> getTimeRange() {
|
||||
return new Pair<Date, Date>(fromTime, toTime);
|
||||
}
|
||||
|
||||
public Date getFromTime() {
|
||||
return fromTime;
|
||||
}
|
||||
|
||||
public Date getToTime() {
|
||||
return toTime;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.sap.sailing.gwt.ui.client;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
|
||||
public interface TimeRangeProvider {
|
||||
|
||||
public void addTimeRangeChangeListener(TimeRangeChangeListener listener);
|
||||
|
||||
public void removeTimeRangeChangeListener(TimeRangeChangeListener listener);
|
||||
|
||||
public void setTimeRange(Date fromTime, Date toTime, TimeRangeChangeListener... listenersNotToNotify);
|
||||
|
||||
public Date getFromTime();
|
||||
|
||||
public Date getToTime();
|
||||
|
||||
public Pair<Date, Date> getTimeRange();
|
||||
}
|
||||
+3
-3
@@ -7,14 +7,14 @@ import java.util.Set;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
|
||||
public class TimeZoomModel implements TimeZoomProvider {
|
||||
public class TimeRangeWithZoomModel extends TimeRangeModel implements TimeRangeWithZoomProvider {
|
||||
private Date zoomStartTimepoint;
|
||||
private Date zoomEndTimepoint;
|
||||
private boolean isTimeZoomed;
|
||||
|
||||
private final Set<TimeZoomChangeListener> listeners;
|
||||
|
||||
public TimeZoomModel() {
|
||||
public TimeRangeWithZoomModel() {
|
||||
isTimeZoomed = false;
|
||||
listeners = new HashSet<TimeZoomChangeListener>();
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class TimeZoomModel implements TimeZoomProvider {
|
||||
this.isTimeZoomed = true;
|
||||
for (TimeZoomChangeListener listener : listeners) {
|
||||
if (listenersNotToNotify == null || !Arrays.asList(listenersNotToNotify).contains(listener)) {
|
||||
listener.onTimeZoom(zoomStartTimepoint, zoomEndTimepoint);
|
||||
listener.onTimeZoomChanged(zoomStartTimepoint, zoomEndTimepoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import java.util.Date;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
|
||||
public interface TimeZoomProvider {
|
||||
public interface TimeRangeWithZoomProvider extends TimeRangeProvider {
|
||||
|
||||
public void addTimeZoomChangeListener(TimeZoomChangeListener listener);
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import java.util.Date;
|
||||
|
||||
public interface TimeZoomChangeListener {
|
||||
|
||||
void onTimeZoom(Date zoomStartTimepoint, Date zoomEndTimepoint);
|
||||
void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint);
|
||||
|
||||
void onTimeZoomReset();
|
||||
}
|
||||
|
||||
+2
-8
@@ -18,10 +18,9 @@ import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomModel;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomModel;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.shared.charts.MultiChartPanel;
|
||||
import com.sap.sailing.gwt.ui.shared.charts.MultiChartSettings;
|
||||
@@ -37,8 +36,6 @@ public class CompareCompetitorsChartDialog extends DialogBoxExt {
|
||||
private final RaceSelectionProvider raceSelectionProvider;
|
||||
|
||||
private final MultiChartPanel multiChartPanel;
|
||||
|
||||
private final RaceTimesInfoProvider raceTimesInfoProvider;
|
||||
|
||||
final ListBox racesListBox;
|
||||
|
||||
@@ -54,12 +51,9 @@ public class CompareCompetitorsChartDialog extends DialogBoxExt {
|
||||
raceSelectionProvider = new RaceSelectionModel();
|
||||
raceSelectionProvider.setAllRaces(races);
|
||||
|
||||
raceTimesInfoProvider = new RaceTimesInfoProvider(sailingService, errorReporter, races, 1000l);
|
||||
|
||||
multiChartPanel = new MultiChartPanel(sailingService, new AsyncActionsExecutor(), competitorSelectionProvider, raceSelectionProvider,
|
||||
timer, new TimeZoomModel(), stringConstants, errorReporter, false, false);
|
||||
timer, new TimeRangeWithZoomModel(), stringConstants, errorReporter, false, false);
|
||||
multiChartPanel.setSize("100%", "100%");
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(multiChartPanel);
|
||||
|
||||
VerticalPanel contentPanel = new VerticalPanel();
|
||||
contentPanel.setSize("100%", "100%");
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ public class ScoringSchemeTypeFormatter {
|
||||
return stringConstants.scoringSchemeHighPointSystem();
|
||||
case HIGH_POINT_ESS_OVERALL:
|
||||
return stringConstants.scoringSchemeHighPointEssOverall();
|
||||
case HIGH_POINT_LAST_BREAKS_TIE:
|
||||
return stringConstants.scoringSchemeHighPointLastBreaksTie();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+5
-2
@@ -28,6 +28,7 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
|
||||
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
|
||||
import com.google.gwt.text.shared.SafeHtmlRenderer;
|
||||
import com.google.gwt.user.cellview.client.CellTable;
|
||||
import com.google.gwt.user.cellview.client.CellTable.Resources;
|
||||
import com.google.gwt.user.cellview.client.Column;
|
||||
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
|
||||
import com.google.gwt.user.cellview.client.Header;
|
||||
@@ -50,6 +51,7 @@ import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.domain.common.impl.Util.Triple;
|
||||
import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
|
||||
import com.sap.sailing.gwt.ui.adminconsole.AdminConsoleTableResources;
|
||||
import com.sap.sailing.gwt.ui.client.Collator;
|
||||
import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
@@ -398,7 +400,7 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
|
||||
private boolean isNetPointsCorrected() {
|
||||
LeaderboardEntryDTO leaderboardEntryDTO = getCurrentlyRendering().fieldsByRaceColumnName.get(raceName);
|
||||
return leaderboardEntryDTO.netPointsCorrected;
|
||||
return leaderboardEntryDTO != null && leaderboardEntryDTO.netPointsCorrected;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -523,7 +525,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
|
||||
}
|
||||
|
||||
private CellTable<CompetitorDTO> createSuppressedCompetitorsTable() {
|
||||
CellTable<CompetitorDTO> result = new CellTable<CompetitorDTO>();
|
||||
final Resources tableResources = GWT.create(AdminConsoleTableResources.class);
|
||||
CellTable<CompetitorDTO> result = new CellTable<CompetitorDTO>(10000, tableResources);
|
||||
suppressedCompetitorsShown.addDataDisplay(result);
|
||||
final SuppressedSailIDColumn suppressedSailIDColumn = new SuppressedSailIDColumn();
|
||||
suppressedSailIDColumn.setSortable(true);
|
||||
|
||||
+3
-3
@@ -378,7 +378,7 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
|
||||
}
|
||||
}
|
||||
|
||||
private static class Callback implements AsyncCallback<BulkScoreCorrectionDTO> {
|
||||
private static class Callback implements DialogCallback<BulkScoreCorrectionDTO> {
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final StringMessages stringMessages;
|
||||
private final ErrorReporter errorReporter;
|
||||
@@ -393,12 +393,12 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<BulkSco
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
// user has canceled the dialog
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(final BulkScoreCorrectionDTO result) {
|
||||
public void ok(final BulkScoreCorrectionDTO result) {
|
||||
leaderboardPanel.getBusyIndicator().setBusy(true);
|
||||
sailingService.updateLeaderboardScoreCorrectionsAndMaxPointsReasons(result, new AsyncCallback<Void>() {
|
||||
@Override
|
||||
|
||||
+3
-3
@@ -43,7 +43,7 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog<Triple<String
|
||||
}
|
||||
}
|
||||
|
||||
private static class Callback implements AsyncCallback<Triple<String, String, Pair<String, Date>>> {
|
||||
private static class Callback implements DialogCallback<Triple<String, String, Pair<String, Date>>> {
|
||||
private final EditableLeaderboardPanel leaderboardPanel;
|
||||
private final SailingServiceAsync sailingService;
|
||||
private final StringMessages stringMessages;
|
||||
@@ -58,12 +58,12 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog<Triple<String
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
public void cancel() {
|
||||
// don't do anything; dialog was canceled
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Triple<String, String, Pair<String, Date>> result) {
|
||||
public void ok(Triple<String, String, Pair<String, Date>> result) {
|
||||
final String scoreCorrectionProviderName = result.getA();
|
||||
final String eventName = result.getB();
|
||||
final String boatClassName = result.getC().getA();
|
||||
|
||||
+7
-9
@@ -33,7 +33,7 @@ import com.sap.sailing.gwt.ui.client.RegattaDisplayer;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeListener;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomModel;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomModel;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.client.UserAgentDetails;
|
||||
import com.sap.sailing.gwt.ui.leaderboard.LeaderboardPanel;
|
||||
@@ -84,7 +84,7 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS
|
||||
private final RaceSelectionProvider raceSelectionProvider;
|
||||
private final UserAgentDetails userAgent;
|
||||
private final CompetitorSelectionModel competitorSelectionModel;
|
||||
private final TimeZoomModel timeZoomModel;
|
||||
private final TimeRangeWithZoomModel timeRangeWithZoomModel;
|
||||
private final RegattaAndRaceIdentifier selectedRaceIdentifier;
|
||||
|
||||
private LeaderboardPanel leaderboardPanel;
|
||||
@@ -123,7 +123,7 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS
|
||||
setWidget(mainPanel);
|
||||
|
||||
this.timer = timer;
|
||||
timeZoomModel = new TimeZoomModel();
|
||||
timeRangeWithZoomModel = new TimeRangeWithZoomModel();
|
||||
componentViewers = new ArrayList<ComponentViewer>();
|
||||
competitorSelectionModel = new CompetitorSelectionModel(/* hasMultiSelection */ true);
|
||||
|
||||
@@ -138,8 +138,8 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS
|
||||
break;
|
||||
}
|
||||
|
||||
timePanel = new RaceTimePanel(timer, stringMessages, raceTimesInfoProvider);
|
||||
timeZoomModel.addTimeZoomChangeListener(timePanel);
|
||||
timePanel = new RaceTimePanel(timer, timeRangeWithZoomModel, stringMessages, raceTimesInfoProvider);
|
||||
timeRangeWithZoomModel.addTimeZoomChangeListener(timePanel);
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(timePanel);
|
||||
raceSelectionProvider.addRaceSelectionChangeListener(timePanel);
|
||||
timePanel.onRaceSelectionChange(raceSelectionProvider.getSelectedRaces());
|
||||
@@ -155,16 +155,14 @@ public class RaceBoardPanel extends FormPanel implements RegattaDisplayer, RaceS
|
||||
List<Component<?>> components = new ArrayList<Component<?>>();
|
||||
|
||||
competitorChart = new MultiChartPanel(sailingService, asyncActionsExecutor, competitorSelectionModel, raceSelectionProvider,
|
||||
timer, timeZoomModel, stringMessages, errorReporter, true, true);
|
||||
timer, timeRangeWithZoomModel, stringMessages, errorReporter, true, true);
|
||||
competitorChart.setVisible(false);
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(competitorChart);
|
||||
competitorChart.onRaceSelectionChange(raceSelectionProvider.getSelectedRaces());
|
||||
components.add(competitorChart);
|
||||
|
||||
windChart = new WindChart(sailingService, raceSelectionProvider, timer, timeZoomModel, new WindChartSettings(),
|
||||
windChart = new WindChart(sailingService, raceSelectionProvider, timer, timeRangeWithZoomModel, new WindChartSettings(),
|
||||
stringMessages, asyncActionsExecutor, errorReporter, /* compactChart */ true);
|
||||
windChart.setVisible(false);
|
||||
raceTimesInfoProvider.addRaceTimesInfoProviderListener(windChart);
|
||||
windChart.onRaceSelectionChange(raceSelectionProvider.getSelectedRaces());
|
||||
components.add(windChart);
|
||||
|
||||
|
||||
+5
@@ -264,6 +264,11 @@ public class LeaderboardDTOCache {
|
||||
removeFromCache(leaderboard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAddRaceColumnToContainer(RaceColumn raceColumn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceColumnAddedToContainer(RaceColumn raceColumn) {
|
||||
removeFromCache(leaderboard);
|
||||
|
||||
+36
-20
@@ -152,6 +152,7 @@ import com.sap.sailing.gwt.ui.shared.PositionDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.QuickRankDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceBuoysDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceColumnInSeriesDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceMapDataDTO;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
@@ -197,7 +198,6 @@ import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard;
|
||||
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardColumn;
|
||||
import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardGroup;
|
||||
import com.sap.sailing.server.operationaltransformation.RemoveRegatta;
|
||||
import com.sap.sailing.server.operationaltransformation.RenameColumnInSeries;
|
||||
import com.sap.sailing.server.operationaltransformation.RenameEvent;
|
||||
import com.sap.sailing.server.operationaltransformation.RenameLeaderboard;
|
||||
import com.sap.sailing.server.operationaltransformation.RenameLeaderboardColumn;
|
||||
@@ -459,7 +459,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
result.setSuppressed(convertToCompetitorDTO(suppressedCompetitor), true);
|
||||
}
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
RaceColumnDTO raceColumnDTO = result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace());
|
||||
RaceColumnDTO raceColumnDTO = result.createEmptyRaceColumn(raceColumn.getName(), raceColumn.isMedalRace(),
|
||||
leaderboard.getScoringScheme().isValidInTotalScore(leaderboard, raceColumn, timePoint));
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
RegattaAndRaceIdentifier raceIdentifier = null;
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
|
||||
@@ -468,6 +469,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
raceIdentifier = new RegattaNameAndRaceName(trackedRace.getTrackedRegatta().getRegatta()
|
||||
.getName(), trackedRace.getRace().getName());
|
||||
}
|
||||
// Note: the RaceColumnDTO won't be created by the following addRace call because it has been created
|
||||
// above by the result.createEmptyRaceColumn call
|
||||
result.addRace(raceColumn.getName(), fleetDTO, raceColumn.isMedalRace(),
|
||||
raceIdentifier, /* StrippedRaceDTO */ null);
|
||||
}
|
||||
@@ -876,7 +879,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
}
|
||||
List<RaceColumnDTO> raceColumns = new ArrayList<RaceColumnDTO>();
|
||||
for (RaceColumnInSeries raceColumn : series.getRaceColumns()) {
|
||||
RaceColumnDTO raceColumnDTO = new RaceColumnDTO();
|
||||
RaceColumnDTO raceColumnDTO = new RaceColumnDTO(/* isValidInTotalScore not relevant here because no scores conveyed */ null);
|
||||
raceColumnDTO.name = raceColumn.getName();
|
||||
raceColumnDTO.setMedalRace(raceColumn.isMedalRace());
|
||||
raceColumns.add(raceColumnDTO);
|
||||
@@ -904,7 +907,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
trackedRaceDTO.timePointOfNewestEvent = trackedRace.getTimePointOfNewestEvent() == null ? null : trackedRace.getTimePointOfNewestEvent().asDate();
|
||||
trackedRaceDTO.delayToLiveInMs = trackedRace.getDelayToLiveInMillis();
|
||||
}
|
||||
RaceWithCompetitorsDTO raceDTO = new RaceWithCompetitorsDTO(raceIdentifier, convertToCompetitorDTOs(r.getCompetitors()), trackedRaceDTO);
|
||||
RaceWithCompetitorsDTO raceDTO = new RaceWithCompetitorsDTO(raceIdentifier, convertToCompetitorDTOs(r.getCompetitors()),
|
||||
trackedRaceDTO, getService().isRaceBeingTracked(r));
|
||||
if (trackedRace != null) {
|
||||
raceDTO.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate();
|
||||
raceDTO.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate();
|
||||
@@ -1901,8 +1905,8 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
leaderboardDTO.hasCarriedPoints = leaderboard.hasCarriedPoints();
|
||||
leaderboardDTO.discardThresholds = leaderboard.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces();
|
||||
for (RaceColumn raceColumn : leaderboard.getRaceColumns()) {
|
||||
RaceDTO raceDTO = null;
|
||||
for (Fleet fleet : raceColumn.getFleets()) {
|
||||
RaceDTO raceDTO = null;
|
||||
RegattaAndRaceIdentifier raceIdentifier = null;
|
||||
TrackedRace trackedRace = raceColumn.getTrackedRace(fleet);
|
||||
if (trackedRace != null) {
|
||||
@@ -1917,7 +1921,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
trackedRaceDTO.startOfTracking = trackedRace.getStartOfTracking() == null ? null : trackedRace.getStartOfTracking().asDate();
|
||||
trackedRaceDTO.hasWindData = trackedRace.hasWindData();
|
||||
trackedRaceDTO.hasGPSData = trackedRace.hasGPSData();
|
||||
raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO);
|
||||
raceDTO = new RaceDTO(raceIdentifier, trackedRaceDTO, getService().isRaceBeingTracked(trackedRace.getRace()));
|
||||
raceDTO.places = racePlaces;
|
||||
raceDTO.startOfRace = trackedRace.getStartOfRace() == null ? null : trackedRace.getStartOfRace().asDate();
|
||||
raceDTO.endOfRace = trackedRace.getEndOfRace() == null ? null : trackedRace.getEndOfRace().asDate();
|
||||
@@ -2622,43 +2626,55 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
|
||||
getService().apply(new RemoveRegatta(regattaIdentifier));
|
||||
}
|
||||
|
||||
private RaceColumnInSeriesDTO convertToRaceColumnInSeriesDTO(RaceColumnInSeries raceColumnInSeries) {
|
||||
RaceColumnInSeriesDTO raceColumnInSeriesDTO = new RaceColumnInSeriesDTO(raceColumnInSeries.getSeries().getName(),
|
||||
raceColumnInSeries.getRegatta().getName());
|
||||
raceColumnInSeriesDTO.name = raceColumnInSeries.getName();
|
||||
raceColumnInSeriesDTO.setMedalRace(raceColumnInSeries.isMedalRace());
|
||||
return raceColumnInSeriesDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
||||
public List<RaceColumnInSeriesDTO> addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
||||
List<RaceColumnInSeriesDTO> result = new ArrayList<RaceColumnInSeriesDTO>();
|
||||
for(String columnName: columnNames) {
|
||||
getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
||||
RaceColumnInSeries raceColumnInSeries = getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
||||
if(raceColumnInSeries != null) {
|
||||
result.add(convertToRaceColumnInSeriesDTO(raceColumnInSeries));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
||||
public RaceColumnInSeriesDTO addRaceColumnToSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
RaceColumnInSeriesDTO result = null;
|
||||
RaceColumnInSeries raceColumnInSeries = getService().apply(new AddColumnToSeries(regattaIdentifier, seriesName, columnName));
|
||||
if(raceColumnInSeries != null) {
|
||||
result = convertToRaceColumnInSeriesDTO(raceColumnInSeries);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
||||
public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames) {
|
||||
for(String columnName: columnNames) {
|
||||
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
public void removeRaceColumnFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renameColumnInSeries(RegattaIdentifier regattaIdentifier, String seriesName, String oldColumnName,
|
||||
String newColumnName) {
|
||||
getService().apply(new RenameColumnInSeries(regattaIdentifier, seriesName, oldColumnName, newColumnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
public void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
getService().apply(new MoveColumnInSeriesUp(regattaIdentifier, seriesName, columnName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
public void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) {
|
||||
getService().apply(new MoveColumnInSeriesDown(regattaIdentifier, seriesName, columnName));
|
||||
}
|
||||
|
||||
|
||||
+12
-31
@@ -79,12 +79,12 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable {
|
||||
|
||||
public Double getTotalPoints(LeaderboardRowDTO object) {
|
||||
Double totalPoints = object.carriedPoints == null ? null : object.carriedPoints;
|
||||
for (LeaderboardEntryDTO e : object.fieldsByRaceColumnName.values()) {
|
||||
if(e.totalPoints != null) {
|
||||
if(totalPoints == null) {
|
||||
totalPoints = e.totalPoints;
|
||||
for (Map.Entry<String, LeaderboardEntryDTO> e : object.fieldsByRaceColumnName.entrySet()) {
|
||||
if (e.getValue().totalPoints != null && getOrCreateRaceColumn(e.getKey()).isValidInTotalScore()) {
|
||||
if (totalPoints == null) {
|
||||
totalPoints = e.getValue().totalPoints;
|
||||
} else {
|
||||
totalPoints += e.totalPoints;
|
||||
totalPoints += e.getValue().totalPoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable {
|
||||
private RaceColumnDTO getOrCreateRaceColumn(String raceColumnName) {
|
||||
RaceColumnDTO result = getRaceInLeaderboardByName(raceColumnName);
|
||||
if (result == null) {
|
||||
result = new RaceColumnDTO();
|
||||
result = new RaceColumnDTO(/* isValidInTotalScore */ true);
|
||||
result.name = raceColumnName;
|
||||
races.add(result);
|
||||
}
|
||||
@@ -133,9 +133,10 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable {
|
||||
|
||||
/**
|
||||
* If the {@link RaceColumnDTO} by the name <code>raceColumnName</code> doesn't exist yet within this leaderboard
|
||||
* DTO, it is created. This method ensures that a fleet named <code>fleetName</code> is present. If it's not present
|
||||
* yet, it's added to the race column's fleet name list. The <code>trackedRaceIdentifier</code> and
|
||||
* <code>race</code> are associated with the column for the fleet identified by <code>fleetName</code>.
|
||||
* DTO, it is created, setting is {@link RaceColumnDTO#isValidInTotalScore()} to <code>true</code>. This method
|
||||
* ensures that a fleet named <code>fleetName</code> is present. If it's not present yet, it's added to the race
|
||||
* column's fleet name list. The <code>trackedRaceIdentifier</code> and <code>race</code> are associated with the
|
||||
* column for the fleet identified by <code>fleetName</code>.
|
||||
*
|
||||
* @param fleetDTO
|
||||
* must not be null
|
||||
@@ -160,28 +161,8 @@ public abstract class AbstractLeaderboardDTO implements IsSerializable {
|
||||
return raceColumnDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* A new {@link RaceColumnDTO} by the name <code>raceColumnName</code> is created and added to this leaderboard at
|
||||
* position <code>index</code>. The single fleet <code>fleet</code> is added to the column. The
|
||||
* <code>trackedRaceIdentifier</code> and <code>race</code> are associated with the column for the fleet identified
|
||||
* by <code>fleetName</code>.
|
||||
*
|
||||
* @param fleet
|
||||
* must not be null
|
||||
*/
|
||||
public void createRaceColumnAt(String raceColumnName, FleetDTO fleet, boolean medalRace,
|
||||
RegattaAndRaceIdentifier trackedRaceIdentifier, int index) {
|
||||
assert fleet != null;
|
||||
RaceColumnDTO raceInLeaderboardDTO = new RaceColumnDTO();
|
||||
raceInLeaderboardDTO.name = raceColumnName;
|
||||
raceInLeaderboardDTO.setMedalRace(medalRace);
|
||||
raceInLeaderboardDTO.addFleet(fleet);
|
||||
raceInLeaderboardDTO.setRaceIdentifier(fleet, trackedRaceIdentifier);
|
||||
races.add(index, raceInLeaderboardDTO);
|
||||
}
|
||||
|
||||
public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace) {
|
||||
RaceColumnDTO raceColumn = new RaceColumnDTO();
|
||||
public RaceColumnDTO createEmptyRaceColumn(String raceColumnName, boolean medalRace, boolean isValidInTotalScore) {
|
||||
RaceColumnDTO raceColumn = new RaceColumnDTO(isValidInTotalScore);
|
||||
raceColumn.name = raceColumnName;
|
||||
raceColumn.setMedalRace(medalRace);
|
||||
races.add(raceColumn);
|
||||
|
||||
+9
-1
@@ -17,13 +17,21 @@ public class RaceColumnDTO extends NamedDTO implements IsSerializable {
|
||||
private List<FleetDTO> fleets;
|
||||
private Map<FleetDTO, RegattaAndRaceIdentifier> trackedRaceIdentifiersPerFleet;
|
||||
private Map<FleetDTO, RaceDTO> racesPerFleet;
|
||||
private Boolean isValidInTotalScore;
|
||||
|
||||
public RaceColumnDTO() {
|
||||
RaceColumnDTO() {} // for GWT serialization
|
||||
|
||||
public RaceColumnDTO(Boolean isValidInTotalScore) {
|
||||
this.isValidInTotalScore = isValidInTotalScore;
|
||||
trackedRaceIdentifiersPerFleet = new HashMap<FleetDTO, RegattaAndRaceIdentifier>();
|
||||
racesPerFleet = new HashMap<FleetDTO, RaceDTO>();
|
||||
fleets = new ArrayList<FleetDTO>();
|
||||
}
|
||||
|
||||
public boolean isValidInTotalScore() {
|
||||
return isValidInTotalScore;
|
||||
}
|
||||
|
||||
public String getRaceColumnName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.sap.sailing.gwt.ui.shared;
|
||||
|
||||
public class RaceColumnInSeriesDTO extends RaceColumnDTO {
|
||||
private String seriesName;
|
||||
private String regattaName;
|
||||
|
||||
// for GWT serialization
|
||||
RaceColumnInSeriesDTO() {}
|
||||
|
||||
public RaceColumnInSeriesDTO(String seriesName, String regattaName) {
|
||||
super();
|
||||
this.seriesName = seriesName;
|
||||
this.regattaName = regattaName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((regattaName == null) ? 0 : regattaName.hashCode());
|
||||
result = prime * result + ((seriesName == null) ? 0 : seriesName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!super.equals(obj))
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
RaceColumnInSeriesDTO other = (RaceColumnInSeriesDTO) obj;
|
||||
if (regattaName == null) {
|
||||
if (other.regattaName != null)
|
||||
return false;
|
||||
} else if (!regattaName.equals(other.regattaName))
|
||||
return false;
|
||||
if (seriesName == null) {
|
||||
if (other.seriesName != null)
|
||||
return false;
|
||||
} else if (!seriesName.equals(other.seriesName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getSeriesName() {
|
||||
return seriesName;
|
||||
}
|
||||
|
||||
public String getRegattaName() {
|
||||
return regattaName;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -27,14 +27,14 @@ public class RaceDTO extends NamedDTO implements IsSerializable {
|
||||
public RaceDTO() {}
|
||||
|
||||
public RaceDTO(RegattaAndRaceIdentifier raceIdentifier) {
|
||||
this(raceIdentifier, null);
|
||||
this(raceIdentifier, null, false);
|
||||
}
|
||||
|
||||
public RaceDTO(RegattaAndRaceIdentifier raceIdentifier, TrackedRaceDTO trackedRace) {
|
||||
public RaceDTO(RegattaAndRaceIdentifier raceIdentifier, TrackedRaceDTO trackedRace, boolean isCurrentlyTracked) {
|
||||
super(raceIdentifier.getRaceName());
|
||||
this.regattaName = raceIdentifier.getRegattaName();
|
||||
this.trackedRace = trackedRace;
|
||||
this.isTracked = trackedRace != null;
|
||||
this.isTracked = isCurrentlyTracked;
|
||||
}
|
||||
|
||||
public RegattaAndRaceIdentifier getRaceIdentifier() {
|
||||
|
||||
+3
-2
@@ -10,8 +10,9 @@ public class RaceWithCompetitorsDTO extends RaceDTO {
|
||||
*/
|
||||
RaceWithCompetitorsDTO() {}
|
||||
|
||||
public RaceWithCompetitorsDTO(RegattaAndRaceIdentifier raceIdentifier, Iterable<CompetitorDTO> competitors, TrackedRaceDTO trackedRace) {
|
||||
super(raceIdentifier, trackedRace);
|
||||
public RaceWithCompetitorsDTO(RegattaAndRaceIdentifier raceIdentifier, Iterable<CompetitorDTO> competitors,
|
||||
TrackedRaceDTO trackedRace, boolean isCurrentlyTracked) {
|
||||
super(raceIdentifier, trackedRace, isCurrentlyTracked);
|
||||
this.competitors = competitors;
|
||||
}
|
||||
|
||||
|
||||
+7
-9
@@ -47,7 +47,7 @@ import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
|
||||
import com.sap.sailing.gwt.ui.shared.CompetitorDTO;
|
||||
@@ -88,9 +88,9 @@ implements CompetitorSelectionChangeListener, RequiresResize {
|
||||
|
||||
public AbstractChartPanel(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
|
||||
CompetitorSelectionProvider competitorSelectionProvider, RaceSelectionProvider raceSelectionProvider,
|
||||
Timer timer, TimeZoomProvider timeZoomProvider, final StringMessages stringMessages, ErrorReporter errorReporter, DetailType dataToShow,
|
||||
Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, final StringMessages stringMessages, ErrorReporter errorReporter, DetailType dataToShow,
|
||||
boolean compactChart, boolean allowTimeAdjust) {
|
||||
super(sailingService, timer, timeZoomProvider, stringMessages, asyncActionsExecutor, errorReporter);
|
||||
super(sailingService, timer, timeRangeWithZoomProvider, stringMessages, asyncActionsExecutor, errorReporter);
|
||||
this.competitorSelectionProvider = competitorSelectionProvider;
|
||||
this.dataToShow = dataToShow;
|
||||
this.compactChart = compactChart;
|
||||
@@ -107,8 +107,6 @@ implements CompetitorSelectionChangeListener, RequiresResize {
|
||||
|
||||
competitorSelectionProvider.addCompetitorSelectionChangeListener(this);
|
||||
raceSelectionProvider.addRaceSelectionChangeListener(this);
|
||||
timer.addTimeListener(this);
|
||||
timeZoomProvider.addTimeZoomChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,14 +241,14 @@ implements CompetitorSelectionChangeListener, RequiresResize {
|
||||
if (!chartData.contains(competitor)) {
|
||||
dataQuery.add(new Pair<Date, CompetitorDTO>(new Date(0), competitor));
|
||||
} else if (competitorDateOfNewestData.before(chartDataDateOfNewestData)
|
||||
|| competitorDateOfNewestData.before(maxTimepoint)) {
|
||||
|| competitorDateOfNewestData.before(timeRangeWithZoomProvider.getToTime())) {
|
||||
dataQuery.add(new Pair<Date, CompetitorDTO>(new Date(competitorDateOfNewestData.getTime()
|
||||
+ getStepSize()), competitor));
|
||||
}
|
||||
}
|
||||
|
||||
GetCompetitorsRaceDataAction getCompetitorsRaceDataAction = new GetCompetitorsRaceDataAction(
|
||||
sailingService, selectedRaceIdentifier, dataQuery, maxTimepoint, getStepSize(),
|
||||
sailingService, selectedRaceIdentifier, dataQuery, timeRangeWithZoomProvider.getToTime(), getStepSize(),
|
||||
getDataToShow(), new AsyncCallback<MultiCompetitorRaceDataDTO>() {
|
||||
|
||||
@Override
|
||||
@@ -273,8 +271,8 @@ implements CompetitorSelectionChangeListener, RequiresResize {
|
||||
}
|
||||
}
|
||||
}
|
||||
chart.getXAxis().setMin(minTimepoint.getTime());
|
||||
chart.getXAxis().setMax(maxTimepoint.getTime());
|
||||
chart.getXAxis().setMin(timeRangeWithZoomProvider.getFromTime().getTime());
|
||||
chart.getXAxis().setMax(timeRangeWithZoomProvider.getToTime().getTime());
|
||||
|
||||
drawChartData();
|
||||
chart.redraw();
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@ import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.shared.components.Component;
|
||||
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
@@ -27,9 +27,9 @@ import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
public class ChartPanel extends AbstractChartPanel<ChartSettings> implements Component<ChartSettings> {
|
||||
|
||||
public ChartPanel(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, CompetitorSelectionProvider competitorSelectionProvider,
|
||||
RaceSelectionProvider raceSelectionProvider, Timer timer, TimeZoomProvider timeZoomProvider, DetailType dataToShow, StringMessages stringMessages,
|
||||
RaceSelectionProvider raceSelectionProvider, Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, DetailType dataToShow, StringMessages stringMessages,
|
||||
ErrorReporter errorReporter, boolean compactChart, boolean allowTimeAdjust) {
|
||||
super(sailingService, asyncActionsExecutor, competitorSelectionProvider, raceSelectionProvider, timer, timeZoomProvider, stringMessages, errorReporter,
|
||||
super(sailingService, asyncActionsExecutor, competitorSelectionProvider, raceSelectionProvider, timer, timeRangeWithZoomProvider, stringMessages, errorReporter,
|
||||
dataToShow, compactChart, allowTimeAdjust);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@ import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.shared.components.Component;
|
||||
import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
@@ -27,9 +27,9 @@ import com.sap.sailing.gwt.ui.shared.components.SettingsDialogComponent;
|
||||
public class MultiChartPanel extends AbstractChartPanel<MultiChartSettings> implements Component<MultiChartSettings> {
|
||||
public MultiChartPanel(SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor,
|
||||
CompetitorSelectionProvider competitorSelectionProvider, RaceSelectionProvider raceSelectionProvider,
|
||||
Timer timer, TimeZoomProvider timeZoomProvider, final StringMessages stringMessages, ErrorReporter errorReporter, boolean compactChart,
|
||||
Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, final StringMessages stringMessages, ErrorReporter errorReporter, boolean compactChart,
|
||||
boolean allowTimeAdjust) {
|
||||
super(sailingService, asyncActionsExecutor, competitorSelectionProvider, raceSelectionProvider, timer, timeZoomProvider, stringMessages, errorReporter,
|
||||
super(sailingService, asyncActionsExecutor, competitorSelectionProvider, raceSelectionProvider, timer, timeRangeWithZoomProvider, stringMessages, errorReporter,
|
||||
/*show initially*/ DetailType.WINDWARD_DISTANCE_TO_OVERALL_LEADER, compactChart, allowTimeAdjust);
|
||||
}
|
||||
|
||||
|
||||
+38
-53
@@ -1,7 +1,6 @@
|
||||
package com.sap.sailing.gwt.ui.shared.charts;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.moxieapps.gwt.highcharts.client.Chart;
|
||||
import org.moxieapps.gwt.highcharts.client.Legend;
|
||||
@@ -18,33 +17,26 @@ import org.moxieapps.gwt.highcharts.client.plotOptions.SeriesPlotOptions;
|
||||
import com.google.gwt.i18n.client.DateTimeFormat;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.common.impl.Util.Pair;
|
||||
import com.sap.sailing.gwt.ui.actions.AsyncActionsExecutor;
|
||||
import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionChangeListener;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesCalculationUtil;
|
||||
import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeListener;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeChangeListener;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomChangeListener;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
|
||||
import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO;
|
||||
|
||||
public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProviderListener, RaceSelectionChangeListener,
|
||||
TimeListener, TimeZoomChangeListener {
|
||||
public abstract class RaceChart extends SimplePanel implements RaceSelectionChangeListener,
|
||||
TimeListener, TimeZoomChangeListener, TimeRangeChangeListener {
|
||||
protected Chart chart;
|
||||
|
||||
protected final Timer timer;
|
||||
protected final TimeZoomProvider timeZoomProvider;
|
||||
|
||||
protected Date minTimepoint;
|
||||
protected Date maxTimepoint;
|
||||
|
||||
protected final TimeRangeWithZoomProvider timeRangeWithZoomProvider;
|
||||
|
||||
protected RegattaAndRaceIdentifier selectedRaceIdentifier;
|
||||
protected RaceTimesInfoDTO lastRaceTimesInfo;
|
||||
|
||||
protected final DateTimeFormat dateFormat = DateTimeFormat.getFormat("HH:mm:ss");
|
||||
protected final DateTimeFormat dateFormatHoursMinutes = DateTimeFormat.getFormat("HH:mm");
|
||||
@@ -62,47 +54,17 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv
|
||||
|
||||
private boolean ignoreNextClickEvent;
|
||||
|
||||
public RaceChart(SailingServiceAsync sailingService, Timer timer, TimeZoomProvider timeZoomProvider, final StringMessages stringMessages,
|
||||
public RaceChart(SailingServiceAsync sailingService, Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, final StringMessages stringMessages,
|
||||
AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter) {
|
||||
this.sailingService = sailingService;
|
||||
this.timer = timer;
|
||||
this.timeZoomProvider = timeZoomProvider;
|
||||
this.timeRangeWithZoomProvider = timeRangeWithZoomProvider;
|
||||
this.stringMessages = stringMessages;
|
||||
this.asyncActionsExecutor = asyncActionsExecutor;
|
||||
this.errorReporter = errorReporter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void raceTimesInfosReceived(Map<RegattaAndRaceIdentifier, RaceTimesInfoDTO> raceTimesInfos) {
|
||||
this.lastRaceTimesInfo = raceTimesInfos.get(selectedRaceIdentifier);
|
||||
|
||||
Pair<Date, Date> raceMinMax = RaceTimesCalculationUtil.caluclateRaceMinMax(timer, this.lastRaceTimesInfo);
|
||||
boolean updateMinMax = false;
|
||||
|
||||
if(chart != null) {
|
||||
if (minTimepoint == null || maxTimepoint == null) {
|
||||
minTimepoint = raceMinMax.getA();
|
||||
maxTimepoint = raceMinMax.getB();
|
||||
updateMinMax = true;
|
||||
} else if(minTimepoint.getTime() != raceMinMax.getA().getTime() || maxTimepoint.getTime() != raceMinMax.getB().getTime()) {
|
||||
minTimepoint = raceMinMax.getA();
|
||||
maxTimepoint = raceMinMax.getB();
|
||||
updateMinMax = true;
|
||||
}
|
||||
}
|
||||
if (updateMinMax) {
|
||||
if (minTimepoint != null) {
|
||||
chart.getXAxis().setMin(minTimepoint.getTime());
|
||||
}
|
||||
if (maxTimepoint != null) {
|
||||
chart.getXAxis().setMax(maxTimepoint.getTime());
|
||||
}
|
||||
if (minTimepoint != null && maxTimepoint != null) {
|
||||
chart.getXAxis().setExtremes(minTimepoint.getTime(), maxTimepoint.getTime(), false, false);
|
||||
long tickInterval = (maxTimepoint.getTime() - minTimepoint.getTime()) / TICKCOUNT;
|
||||
chart.getXAxis().setTickInterval(tickInterval);
|
||||
}
|
||||
}
|
||||
timer.addTimeListener(this);
|
||||
timeRangeWithZoomProvider.addTimeZoomChangeListener(this);
|
||||
timeRangeWithZoomProvider.addTimeRangeChangeListener(this);
|
||||
}
|
||||
|
||||
protected void showLoading(String message) {
|
||||
@@ -126,10 +88,10 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv
|
||||
if (!isZoomed) {
|
||||
isZoomed = true;
|
||||
}
|
||||
timeZoomProvider.setTimeZoom(new Date(xAxisMin), new Date(xAxisMax), this);
|
||||
timeRangeWithZoomProvider.setTimeZoom(new Date(xAxisMin), new Date(xAxisMax), this);
|
||||
} catch (Throwable t) {
|
||||
// in case the user clicks the "reset zoom" button chartSelectionEvent.getXAxisMinAsLong() throws in exception
|
||||
timeZoomProvider.resetTimeZoom(this);
|
||||
timeRangeWithZoomProvider.resetTimeZoom(this);
|
||||
// Trigger the redrawing... otherwise chart wouldn't reset the zoom
|
||||
chart.redraw();
|
||||
isZoomed = false;
|
||||
@@ -151,19 +113,42 @@ public abstract class RaceChart extends SimplePanel implements RaceTimesInfoProv
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void resetMinMaxInterval(Date minIntervalTimepoint, Date maxIntervalTimepoint) {
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
Date minTimepoint = timeRangeWithZoomProvider.getFromTime();
|
||||
Date maxTimepoint = timeRangeWithZoomProvider.getToTime();
|
||||
|
||||
if (minTimepoint != null) {
|
||||
xAxis.setMin(minTimepoint.getTime());
|
||||
}
|
||||
if (maxTimepoint != null) {
|
||||
xAxis.setMax(maxTimepoint.getTime());
|
||||
}
|
||||
if (minTimepoint != null && maxTimepoint != null) {
|
||||
xAxis.setExtremes(minTimepoint.getTime(), maxTimepoint.getTime(), false, false);
|
||||
long tickInterval = (maxTimepoint.getTime() - minTimepoint.getTime()) / TICKCOUNT;
|
||||
xAxis.setTickInterval(tickInterval);
|
||||
}
|
||||
chart.redraw();
|
||||
}
|
||||
|
||||
protected void changeMinMaxInterval(Date minIntervalTimepoint, Date maxIntervalTimepoint) {
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
xAxis.setExtremes(minIntervalTimepoint.getTime(), maxIntervalTimepoint.getTime(), true, true);
|
||||
}
|
||||
|
||||
public void onTimeZoom(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
public void onTimeZoomChanged(Date zoomStartTimepoint, Date zoomEndTimepoint) {
|
||||
changeMinMaxInterval(zoomStartTimepoint, zoomEndTimepoint);
|
||||
// Probably there is a function for this in a newer version of highcharts: http://jsfiddle.net/mqz3N/1071/
|
||||
// chart.showResetZoom();
|
||||
}
|
||||
|
||||
public void onTimeRangeChanged(Date fromTime, Date toTime) {
|
||||
resetMinMaxInterval(fromTime, toTime);
|
||||
}
|
||||
|
||||
public void onTimeZoomReset() {
|
||||
changeMinMaxInterval(minTimepoint, maxTimepoint);
|
||||
changeMinMaxInterval(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-9
@@ -43,7 +43,7 @@ import com.sap.sailing.gwt.ui.client.ErrorReporter;
|
||||
import com.sap.sailing.gwt.ui.client.RaceSelectionProvider;
|
||||
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sailing.gwt.ui.client.TimeZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.TimeRangeWithZoomProvider;
|
||||
import com.sap.sailing.gwt.ui.client.Timer;
|
||||
import com.sap.sailing.gwt.ui.client.Timer.PlayModes;
|
||||
import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter;
|
||||
@@ -75,9 +75,9 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
|
||||
* server and displayed in this chart. If no race is selected, the chart is cleared.
|
||||
*/
|
||||
public WindChart(SailingServiceAsync sailingService, RaceSelectionProvider raceSelectionProvider, Timer timer,
|
||||
TimeZoomProvider timeZoomProvider, WindChartSettings settings, final StringMessages stringMessages,
|
||||
TimeRangeWithZoomProvider timeRangeWithZoomProvider, WindChartSettings settings, final StringMessages stringMessages,
|
||||
AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, boolean compactChart) {
|
||||
super(sailingService, timer, timeZoomProvider, stringMessages, asyncActionsExecutor, errorReporter);
|
||||
super(sailingService, timer, timeRangeWithZoomProvider, stringMessages, asyncActionsExecutor, errorReporter);
|
||||
this.windSourceDirectionSeries = new HashMap<WindSource, Series>();
|
||||
this.windSourceSpeedSeries = new HashMap<WindSource, Series>();
|
||||
this.colorMap = new ColorMap<WindSource>();
|
||||
@@ -170,8 +170,6 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
|
||||
setSize("100%", "100%");
|
||||
|
||||
raceSelectionProvider.addRaceSelectionChangeListener(this);
|
||||
timer.addTimeListener(this);
|
||||
timeZoomProvider.addTimeZoomChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -424,7 +422,7 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
|
||||
timeOfEarliestRequestInMillis = null;
|
||||
timeOfLatestRequestInMillis = null;
|
||||
|
||||
loadData(minTimepoint, maxTimepoint, /* append */false);
|
||||
loadData(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime(), /* append */false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -504,9 +502,9 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
|
||||
{
|
||||
// is date before first cache entry or is cache empty?
|
||||
if (timeOfEarliestRequestInMillis == null || timeOfEarliestRequestInMillis > date.getTime()) {
|
||||
loadData(minTimepoint, date, /* append */ true);
|
||||
loadData(timeRangeWithZoomProvider.getFromTime(), date, /* append */ true);
|
||||
} else if (timeOfLatestRequestInMillis < date.getTime()) {
|
||||
loadData(new Date(timeOfLatestRequestInMillis), maxTimepoint, /* append */true);
|
||||
loadData(new Date(timeOfLatestRequestInMillis), timeRangeWithZoomProvider.getToTime(), /* append */true);
|
||||
}
|
||||
// otherwise the cache spans across date and so we don't need to load anything
|
||||
break;
|
||||
@@ -515,7 +513,7 @@ public class WindChart extends RaceChart implements Component<WindChartSettings>
|
||||
{
|
||||
// assuming play mode is replay / non-live
|
||||
if (timeOfLatestRequestInMillis == null) {
|
||||
loadData(minTimepoint, maxTimepoint, /* append */false); // replace old series
|
||||
loadData(timeRangeWithZoomProvider.getFromTime(), timeRangeWithZoomProvider.getToTime(), /* append */false); // replace old series
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package com.sap.sailing.gwt.ui.shared.components;
|
||||
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
|
||||
@@ -12,13 +11,13 @@ public class SettingsDialog<SettingsType> extends DataEntryDialog<SettingsType>
|
||||
public SettingsDialog(final Component<SettingsType> component, StringMessages stringConstants) {
|
||||
super(stringConstants.settingsForComponent(component.getLocalizedShortName()), null, stringConstants.ok(),
|
||||
stringConstants.cancel(), component.getSettingsDialogComponent().getValidator(),
|
||||
new AsyncCallback<SettingsType>() {
|
||||
new DialogCallback<SettingsType>() {
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(SettingsType newSettings) {
|
||||
public void ok(SettingsType newSettings) {
|
||||
component.updateSettings(newSettings);
|
||||
}
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user