started with mapping of official results to leaderboard entries

This commit is contained in:
Axel Uhl committed 2012-06-12 17:12:51 +02:00
1 parent 5b72601de5
commit e65efa42fb
3 files changed
+121 -9

No files matched your search

@@ -1,25 +1,109 @@
package com.sap.sailing.gwt.ui.leaderboardedit;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.client.DataEntryDialog;
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.CompetitorDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardEntryDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardRowDTO;
import com.sap.sailing.gwt.ui.shared.RaceColumnDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO;
import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO.ScoreCorrectionEntryDTO;
public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<ScoreCorrectionsApplicationInstructions> {
private static final RegExp p = RegExp.compile("^\\(A-ZA-ZA-Z\\)[^0-9]\\([0-9]*\\)$");
private final LeaderboardDTO leaderboard;
private final Map<String, CompetitorDTO> sailIDToCompetitor;
private final Map<String, String> raceColumnNameToOfficialRaceNameOrNumber;
private final RegattaScoreCorrectionDTO regattaScoreCorrection;
public MatchAndApplyScoreCorrectionsDialog(LeaderboardDTO leaderboard, StringMessages stringMessages,
SailingServiceAsync sailingService, ErrorReporter errorReporter, RegattaScoreCorrectionDTO result) {
super(stringMessages.assignRaceNumbersToRaceColumns(), stringMessages.assignRaceNumbersToRaceColumns(),
stringMessages.ok(), stringMessages.cancel(), new Validator(), new Callback());
createAdditionalWidget(result);
this.regattaScoreCorrection = result;
this.leaderboard = leaderboard;
this.sailIDToCompetitor = mapCompetitors(leaderboard, result);
this.raceColumnNameToOfficialRaceNameOrNumber = createRaceColumnNameToOfficialRaceNameOrNumberSuggestion(leaderboard, result);
}
private void createAdditionalWidget(RegattaScoreCorrectionDTO result) {
// TODO Auto-generated method stub
/**
* The default suggestion made for the mapping of leaderboard race column names to the official race name/number scheme
* is by their ordering.
*/
private Map<String, String> createRaceColumnNameToOfficialRaceNameOrNumberSuggestion(
LeaderboardDTO leaderboard, RegattaScoreCorrectionDTO regattaScoreCorretion) {
Map<String, String> result = new HashMap<String, String>();
Iterator<RaceColumnDTO> raceColumnIter = leaderboard.getRaceList().iterator();
Iterator<String> officialRaceNameOrNumberIter = regattaScoreCorretion.getScoreCorrectionsByRaceNameOrNumber().keySet().iterator();
while (raceColumnIter.hasNext() && officialRaceNameOrNumberIter.hasNext()) {
result.put(raceColumnIter.next().name, officialRaceNameOrNumberIter.next());
}
return result;
}
/**
* Maps the sail IDs contained in <code>result</code> to the {@link CompetitorDTO}s contained in <code>leaderboard</code>.
* The match making ignores all whitespaces in the sail IDs on both sides. If the {@link CompetitorDTO#sailID} does not start
* with a letter it is assumed the country code is missing. In this case, the {@link CompetitorDTO#threeLetterIocCountryCode} is
* prepended before comparing to <code>result</code>'s sail IDs. The sail ID number is extracted by trimming and using all
* trailing digits.
*
* @return a map mapping the sailIDs as found in <code>result</code> to the {@link CompetitorDTO}s used in <code>leaderboard</code>
*/
private Map<String, CompetitorDTO> mapCompetitors(LeaderboardDTO leaderboard, RegattaScoreCorrectionDTO regattaScoreCorrection) {
Map<String, CompetitorDTO> result = new HashMap<String, CompetitorDTO>();
Map<String, CompetitorDTO> canonicalizedLeaderboardSailIDToCompetitors = canonicalizeLeaderboardSailIDs(leaderboard);
for (Map<String, ScoreCorrectionEntryDTO> scoreCorrectionsBySailID : regattaScoreCorrection.getScoreCorrectionsByRaceNameOrNumber().values()) {
for (String resultSailID : scoreCorrectionsBySailID.keySet()) {
String canonicalizedResultSailID = canonicalizeSailID(resultSailID, /* defaultNationality */ null);
CompetitorDTO competitor = canonicalizedLeaderboardSailIDToCompetitors.get(canonicalizedResultSailID);
if (competitor != null) {
result.put(resultSailID, competitor);
}
}
}
return result;
}
private String canonicalizeSailID(String sailID, String defaultNationality) {
String result = null;
MatchResult m = p.exec(sailID);
if (p.test(sailID)) {
String iocCode = m.getGroup(1);
if (defaultNationality != null && (iocCode == null || iocCode.trim().length() == 0)) {
iocCode = defaultNationality;
}
if (iocCode != null && iocCode.trim().length() > 0) {
String number = m.getGroup(2);
result = iocCode + number;
}
}
return result;
}
private Map<String, CompetitorDTO> canonicalizeLeaderboardSailIDs(LeaderboardDTO leaderboard) {
Map<String, CompetitorDTO> result = new HashMap<String, CompetitorDTO>();
for (CompetitorDTO competitor : leaderboard.competitors) {
String canonicalizedSailID = canonicalizeSailID(competitor.sailID.trim(), competitor.threeLetterIocCountryCode.trim());
if (canonicalizedSailID != null) {
result.put(canonicalizedSailID, competitor);
}
}
return result;
}
@Override
@@ -30,8 +114,35 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog<ScoreCo
@Override
protected Widget getAdditionalWidget() {
// TODO Auto-generated method stub
return super.getAdditionalWidget();
// Create a grid that hosts races on X and competitors on Y with the leaderboard ones as fixed entries and
// the correction ones as selectable drop-downs. The grid cells show the current leaderboard entries
// and the suggested correction plus a checkbox each. Each row and each column has a checkbox as well.
// If a row/column checkbox is toggled, it sets all checkboxes in the row/column to the new state.
// When OKing the dialog, for all ticked cells the corrections are applied.
Grid grid = new Grid(leaderboard.competitors.size()+1, leaderboard.getRaceList().size()+1);
int c = 0;
for (RaceColumnDTO raceColumn : leaderboard.getRaceList()) {
grid.setWidget(0, c, /* TODO */ new Label(raceColumn.name));
c++;
}
int row=1;
for (Map.Entry<String, CompetitorDTO> officialSailIDAndCompetitor : sailIDToCompetitor.entrySet()) {
int column = 0;
grid.setWidget(row, column++, new Label(officialSailIDAndCompetitor.getKey()+"/"+officialSailIDAndCompetitor.getValue().sailID));
LeaderboardRowDTO leaderboardRow = leaderboard.rows.get(officialSailIDAndCompetitor.getValue());
for (RaceColumnDTO raceColumn : leaderboard.getRaceList()) {
LeaderboardEntryDTO entry = leaderboardRow.fieldsByRaceColumnName.get(raceColumn.name);
ScoreCorrectionEntryDTO officialCorrectionEntry =
regattaScoreCorrection.getScoreCorrectionsByRaceNameOrNumber()
.get(raceColumnNameToOfficialRaceNameOrNumber.get(raceColumn.name))
.get(officialSailIDAndCompetitor.getKey());
grid.setWidget(row, column++, /* TODO */ new Label(entry.netPoints+"/"+entry.totalPoints+"/"+entry.reasonForMaxPoints+
(entry.discarded?"/discarded":""+" vs. "+officialCorrectionEntry.getScore()+"/"+officialCorrectionEntry.getMaxPointsReason()+
(officialCorrectionEntry.getDiscarded()?"/discarded":""))));
}
row++;
}
return grid;
}
private static class Validator implements DataEntryDialog.Validator<ScoreCorrectionsApplicationInstructions> {
@@ -2069,7 +2069,7 @@ public class SailingServiceImpl extends RemoteServiceServlet implements SailingS
private RegattaScoreCorrectionDTO createScoreCorrection(RegattaScoreCorrections scoreCorrections) {
// Key is the race name or number as String; values are maps whose key is the sailID.
Map<String, Map<String, ScoreCorrectionEntryDTO>> map = new HashMap<String, Map<String, ScoreCorrectionEntryDTO>>();
LinkedHashMap<String, Map<String, ScoreCorrectionEntryDTO>> map = new LinkedHashMap<String, Map<String, ScoreCorrectionEntryDTO>>();
for (ScoreCorrectionsForRace sc4r : scoreCorrections.getScoreCorrectionsForRaces()) {
Map<String, ScoreCorrectionEntryDTO> entryMap = new HashMap<String, RegattaScoreCorrectionDTO.ScoreCorrectionEntryDTO>();
for (String sailID : sc4r.getSailIDs()) {
@@ -1,5 +1,6 @@
package com.sap.sailing.gwt.ui.shared;
import java.util.LinkedHashMap;
import java.util.Map;
import com.google.gwt.user.client.rpc.IsSerializable;
@@ -38,7 +39,7 @@ public class RegattaScoreCorrectionDTO implements IsSerializable {
/**
* Key is the race name or number as String; values are maps whose key is the sailID.
*/
private Map<String, Map<String, ScoreCorrectionEntryDTO>> scoreCorrectionsByRaceNameOrNumber;
private LinkedHashMap<String, Map<String, ScoreCorrectionEntryDTO>> scoreCorrectionsByRaceNameOrNumber;
public RegattaScoreCorrectionDTO() {}
@@ -47,7 +48,7 @@ public class RegattaScoreCorrectionDTO implements IsSerializable {
* Key is the race name or number as String; values are maps whose key is the sailID.
*/
public RegattaScoreCorrectionDTO(String providerName,
Map<String, Map<String, ScoreCorrectionEntryDTO>> scoreCorrectionsByRaceNameOrNumber) {
LinkedHashMap<String, Map<String, ScoreCorrectionEntryDTO>> scoreCorrectionsByRaceNameOrNumber) {
super();
this.providerName = providerName;
this.scoreCorrectionsByRaceNameOrNumber = scoreCorrectionsByRaceNameOrNumber;
@@ -57,7 +58,7 @@ public class RegattaScoreCorrectionDTO implements IsSerializable {
return providerName;
}
public Map<String, Map<String, ScoreCorrectionEntryDTO>> getScoreCorrectionsByRaceNameOrNumber() {
public LinkedHashMap<String, Map<String, ScoreCorrectionEntryDTO>> getScoreCorrectionsByRaceNameOrNumber() {
return scoreCorrectionsByRaceNameOrNumber;
}
}