supporting regatta / series creation with series-specific discarding rules

This commit is contained in:
Axel Uhl committed 2013-06-06 02:03:27 +02:00
1 parent 0994813209
commit d014115405
10 files changed
+63 -41

No files matched your search

@@ -18,7 +18,6 @@ import com.google.gwt.user.client.ui.VerticalPanel;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.RegattaIdentifier;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.gwt.ui.client.DataEntryDialog.DialogCallback;
import com.sap.sailing.gwt.ui.client.ErrorReporter;
@@ -118,15 +117,16 @@ public class RegattaStructureManagementPanel extends SimplePanel implements Rega
}
private void createNewRegatta(final RegattaDTO newRegatta) {
LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesStructure =
new LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>>();
LinkedHashMap<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesStructure =
new LinkedHashMap<String, Triple<List<Triple<String,Integer,Color>>,Boolean,int[]>>();
for (SeriesDTO seriesDTO : newRegatta.series) {
List<Triple<String, Integer, Color>> fleets = new ArrayList<Triple<String, Integer, Color>>();
for(FleetDTO fleetDTO : seriesDTO.getFleets()) {
Triple<String, Integer, Color> fleetTriple = new Triple<String, Integer, Color>(fleetDTO.name, fleetDTO.getOrderNo(), fleetDTO.getColor());
fleets.add(fleetTriple);
}
Pair<List<Triple<String, Integer, Color>>, Boolean> seriesPair = new Pair<List<Triple<String, Integer, Color>>, Boolean>(fleets, seriesDTO.isMedal());
Triple<List<Triple<String, Integer, Color>>, Boolean, int[]> seriesPair = new Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>(
fleets, seriesDTO.isMedal(), seriesDTO.getDiscardThresholds());
seriesStructure.put(seriesDTO.name, seriesPair);
}
sailingService.createRegatta(newRegatta.name, newRegatta.boatClass==null?null:newRegatta.boatClass.name, seriesStructure, true,
@@ -9,6 +9,8 @@ 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.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
@@ -26,11 +28,13 @@ import com.sap.sailing.gwt.ui.shared.SeriesDTO;
public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
private StringMessages stringConstants;
private StringMessages stringMessages;
private SeriesDTO series;
private TextBox nameEntryField;
private CheckBox isMedalSeriesCheckbox;
private CheckBox useSeriesResultDiscardingThresholdsCheckbox;
private DiscardThresholdBoxes discardThresholdBoxes;
private List<TextBox> fleetNameEntryFields;
private List<ListBox> fleetColorEntryFields;
@@ -39,12 +43,11 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
private Grid fleetsGrid;
protected static class SeriesParameterValidator implements Validator<SeriesDTO> {
private StringMessages stringConstants;
private StringMessages stringMessages;
private ArrayList<SeriesDTO> existingSeries;
public SeriesParameterValidator(StringMessages stringConstants, Collection<SeriesDTO> existingSeries) {
this.stringConstants = stringConstants;
this.stringMessages = stringConstants;
this.existingSeries = new ArrayList<SeriesDTO>(existingSeries);
}
@@ -60,9 +63,9 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
}
}
if (!nameNotEmpty) {
errorMessage = stringConstants.pleaseEnterAName();
errorMessage = stringMessages.pleaseEnterAName();
} else if (!unique) {
errorMessage = stringConstants.seriesWithThisNameAlreadyExists();
errorMessage = stringMessages.seriesWithThisNameAlreadyExists();
}
if (errorMessage == null) {
List<FleetDTO> fleetsToValidate = seriesToValidate.getFleets();
@@ -86,32 +89,41 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
index2++;
}
if (!fleetNameNotEmpty) {
errorMessage = stringConstants.fleet() + " " + (index + 1) + ": " + stringConstants.pleaseEnterAName();
errorMessage = stringMessages.fleet() + " " + (index + 1) + ": " + stringMessages.pleaseEnterAName();
} else if (!fleetUnique) {
errorMessage = stringConstants.fleet() + " " + (index2 + 1) + ": " + stringConstants.fleetWithThisNameAlreadyExists();
errorMessage = stringMessages.fleet() + " " + (index2 + 1) + ": " + stringMessages.fleetWithThisNameAlreadyExists();
} else {
errorMessage = DiscardThresholdBoxes.getErrorMessage(seriesToValidate.getDiscardThresholds(), stringMessages);
}
}
return errorMessage;
}
}
public SeriesWithFleetsCreateDialog(Collection<SeriesDTO> existingSeries, StringMessages stringConstants,
public SeriesWithFleetsCreateDialog(Collection<SeriesDTO> existingSeries, StringMessages stringMessages,
DialogCallback<SeriesDTO> callback) {
super(stringConstants.series(), null, stringConstants.ok(), stringConstants.cancel(),
new SeriesParameterValidator(stringConstants, existingSeries), callback);
this.stringConstants = stringConstants;
super(stringMessages.series(), null, stringMessages.ok(), stringMessages.cancel(),
new SeriesParameterValidator(stringMessages, existingSeries), callback);
this.stringMessages = stringMessages;
this.series = new SeriesDTO();
nameEntryField = createTextBox(null);
nameEntryField.setVisibleLength(40);
isMedalSeriesCheckbox = createCheckbox(stringConstants.medalSeries());
isMedalSeriesCheckbox = createCheckbox(stringMessages.medalSeries());
useSeriesResultDiscardingThresholdsCheckbox = createCheckbox(stringMessages.seriesDefinesResultDiscardingRule());
useSeriesResultDiscardingThresholdsCheckbox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
discardThresholdBoxes.getWidget().setVisible(event.getValue());
}
});
discardThresholdBoxes = new DiscardThresholdBoxes(this, stringMessages);
discardThresholdBoxes.getWidget().setVisible(false);
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);
// TODO bug 1414 add checkbox for enabling series-specific result discarding and, if checked, show the discard threshold boxes to be shared with leaderboard create/edit dialogs
}
private Widget createFleetNameWidget(String defaultName) {
@@ -145,7 +157,7 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
validate();
}
});
listBox.addItem(stringConstants.noColor());
listBox.addItem(stringMessages.noColor());
for(FleetColors value: FleetColors.values()) {
listBox.addItem(value.name());
}
@@ -180,6 +192,7 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
fleets.add(fleetDTO);
}
series.setFleets(fleets);
series.setDiscardThresholds(useSeriesResultDiscardingThresholdsCheckbox.getValue() ? discardThresholdBoxes.getDiscardThresholds() : null);
return series;
}
@@ -206,14 +219,16 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
if (additionalWidget != null) {
panel.add(additionalWidget);
}
Grid formGrid = new Grid(2, 2);
Grid formGrid = new Grid(4, 2);
panel.add(formGrid);
formGrid.setWidget(0, 0, new Label(stringConstants.name() + ":"));
formGrid.setWidget(0, 0, new Label(stringMessages.name() + ":"));
formGrid.setWidget(0, 1, nameEntryField);
formGrid.setWidget(1, 1, isMedalSeriesCheckbox);
panel.add(createHeadlineLabel(stringConstants.fleets()));
formGrid.setWidget(2, 1, useSeriesResultDiscardingThresholdsCheckbox);
formGrid.setWidget(3, 1, discardThresholdBoxes.getWidget());
panel.add(createHeadlineLabel(stringMessages.fleets()));
panel.add(fleetsGrid);
Button addFleetButton = new Button(stringConstants.addFleet());
Button addFleetButton = new Button(stringMessages.addFleet());
addFleetButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -238,9 +253,9 @@ public class SeriesWithFleetsCreateDialog extends DataEntryDialog<SeriesDTO> {
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());
fleetsGrid.setHTML(0, 0, stringMessages.color());
fleetsGrid.setHTML(0, 1, stringMessages.name());
fleetsGrid.setHTML(0, 2, stringMessages.rank());
for(int i = 0; i < fleetCount; i++) {
fleetsGrid.setWidget(i+1, 0, fleetColorEntryFields.get(i));
fleetsGrid.setWidget(i+1, 1, fleetNameEntryFields.get(i));
@@ -143,7 +143,7 @@ public interface SailingService extends RemoteService {
void moveLeaderboardColumnDown(String leaderboardName, String columnName);
RegattaDTO createRegatta(String regattaName, String boatClassName,
LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
LinkedHashMap<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
boolean persistent, ScoringSchemeType scoringSchemeType, String defaultCourseAreaId);
void removeRegatta(RegattaIdentifier regattaIdentifier);
@@ -364,7 +364,7 @@ public interface SailingServiceAsync {
AsyncCallback<Void> callback);
void createRegatta(String regattaName, String boatClassName,
LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
LinkedHashMap<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
boolean persistent, ScoringSchemeType scoringSchemeType, String defaultCourseAreaId, AsyncCallback<RegattaDTO> callback);
void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, List<String> columnNames,
@@ -2525,7 +2525,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
@Override
public RegattaDTO createRegatta(String regattaName, String boatClassName,
LinkedHashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
LinkedHashMap<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal,
boolean persistent, ScoringSchemeType scoringSchemeType, String defaultCourseAreaId) {
UUID courseAreaUuid = convertIdentifierStringToUuid(defaultCourseAreaId);
Regatta regatta = getService().apply(
@@ -50,4 +50,8 @@ public class SeriesDTO extends NamedDTO {
public int[] getDiscardThresholds() {
return discardThresholds;
}
public void setDiscardThresholds(int[] discardThresholds) {
this.discardThresholds = discardThresholds;
}
}
@@ -3,11 +3,9 @@ package com.sap.sailing.selenium.test.adminconsole;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import com.sap.sailing.selenium.test.AbstractSeleniumTest;
import com.sap.sailing.selenium.test.DatabaseHelper;
import com.sap.sailing.selenium.test.adminconsole.pages.AdminConsolePage;
import com.sap.sailing.selenium.test.adminconsole.pages.FlexibleLeaderboardCreationDialog;
import com.sap.sailing.selenium.test.adminconsole.pages.LeaderboardConfigurationPanel;
@@ -1,7 +1,6 @@
package com.sap.sailing.selenium.test.adminconsole.pages;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.openqa.selenium.By;
@@ -824,15 +824,18 @@ public class RacingEventServiceImpl implements RacingEventService, RegattaListen
}
}
private Map<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> getSeriesWithoutRaceColumnsConstructionParametersAsMap(Regatta regatta) {
Map<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> result = new HashMap<String, Pair<List<Triple<String, Integer, Color>>, Boolean>>();
private Map<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> getSeriesWithoutRaceColumnsConstructionParametersAsMap(
Regatta regatta) {
Map<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> result =
new HashMap<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>>();
for (Series s : regatta.getSeries()) {
assert Util.isEmpty(s.getRaceColumns());
List<Triple<String, Integer, Color>> fleetNamesAndOrdering = new ArrayList<Triple<String, Integer, Color>>();
for (Fleet f : s.getFleets()) {
fleetNamesAndOrdering.add(new Triple<String, Integer, Color>(f.getName(), f.getOrdering(), f.getColor()));
}
result.put(s.getName(), new Pair<List<Triple<String, Integer, Color>>, Boolean>(fleetNamesAndOrdering, s.isMedal()));
result.put(s.getName(), new Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>(fleetNamesAndOrdering, s.isMedal(),
s.getResultDiscardingRule() == null ? null : s.getResultDiscardingRule().getDiscardIndexResultsStartingWithHowManyRaces()));
}
return result;
}
@@ -12,25 +12,25 @@ import com.sap.sailing.domain.base.Series;
import com.sap.sailing.domain.base.impl.FleetImpl;
import com.sap.sailing.domain.base.impl.SeriesImpl;
import com.sap.sailing.domain.common.Color;
import com.sap.sailing.domain.common.impl.Util.Pair;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.domain.leaderboard.ScoringScheme;
import com.sap.sailing.domain.leaderboard.impl.ThresholdBasedResultDiscardingRuleImpl;
import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
import com.sap.sailing.server.RacingEventService;
import com.sap.sailing.server.RacingEventServiceOperation;
public class AddSpecificRegatta extends AbstractAddRegattaOperation {
private static final long serialVersionUID = -8018855620167669352L;
private final Map<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrderingAndMedal;
private final Map<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds;
private final boolean persistent;
private final ScoringScheme scoringScheme;
private final Serializable defaultCourseAreaId;
public AddSpecificRegatta(String regattaName, String boatClassName, Serializable id,
Map<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> seriesNamesWithFleetNamesAndFleetOrdering,
Map<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds,
boolean persistent, ScoringScheme scoringScheme, Serializable defaultCourseAreaId) {
super(regattaName, boatClassName, id);
this.seriesNamesWithFleetNamesAndFleetOrderingAndMedal = seriesNamesWithFleetNamesAndFleetOrdering;
this.seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds = seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds;
this.persistent = persistent;
this.scoringScheme = scoringScheme;
this.defaultCourseAreaId = defaultCourseAreaId;
@@ -44,10 +44,13 @@ public class AddSpecificRegatta extends AbstractAddRegattaOperation {
private Iterable<? extends Series> createSeries(TrackedRegattaRegistry trackedRegattaRegistry) {
List<Series> result = new ArrayList<Series>();
for (Map.Entry<String, Pair<List<Triple<String, Integer, Color>>, Boolean>> e : seriesNamesWithFleetNamesAndFleetOrderingAndMedal.entrySet()) {
for (Map.Entry<String, Triple<List<Triple<String, Integer, Color>>, Boolean, int[]>> e : seriesNamesWithFleetNamesAndFleetOrderingAndMedalAndDiscardingThresholds.entrySet()) {
final List<String> emptyRaceColumnNamesList = Collections.emptyList();
Series s = new SeriesImpl(e.getKey(), /* isMedal */e.getValue().getB(), createFleets(e.getValue().getA()),
emptyRaceColumnNamesList, trackedRegattaRegistry);
if (e.getValue().getC() != null) {
s.setResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(e.getValue().getC()));
}
result.add(s);
}
return result;