fixed bug 1036, also notifying RaceColumnListeners about competitor display name change

This commit is contained in:
Axel Uhl committed 2012-11-12 18:16:32 +01:00
1 parent 1027a92b61
commit 580d7e2a3b
19 files changed
+180 -172

No files matched your search

@@ -22,6 +22,7 @@ public enum DetailType implements Serializable {
WINDWARD_DISTANCE_TO_OVERALL_LEADER(0, ASCENDING), WINDWARD_DISTANCE_TO_OVERALL_LEADER(0, ASCENDING),
HEAD_UP(0, ASCENDING), BEAR_AWAY(0, ASCENDING), HEAD_UP(0, ASCENDING), BEAR_AWAY(0, ASCENDING),
TACK(0, ASCENDING), JIBE(0, ASCENDING), PENALTY_CIRCLE(0, ASCENDING), AVERAGE_MANEUVER_LOSS_IN_METERS(1, ASCENDING), TACK(0, ASCENDING), JIBE(0, ASCENDING), PENALTY_CIRCLE(0, ASCENDING), AVERAGE_MANEUVER_LOSS_IN_METERS(1, ASCENDING),
AVERAGE_TACK_LOSS_IN_METERS(1, ASCENDING), AVERAGE_JIBE_LOSS_IN_METERS(1, ASCENDING),
MARK_PASSING(0, ASCENDING), CURRENT_LEG(0, ASCENDING), MARK_PASSING(0, ASCENDING), CURRENT_LEG(0, ASCENDING),
DISPLAY_LEGS(0, NONE), TIME_TRAVELED(0, ASCENDING), DISPLAY_LEGS(0, NONE), TIME_TRAVELED(0, ASCENDING),
TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS(1, ASCENDING), TOTAL_TIME_SAILED_DOWNWIND_IN_SECONDS(1, ASCENDING),
@@ -206,6 +206,10 @@ public class DelayedLeaderboardCorrectionsImpl implements DelayedLeaderboardCorr
public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) {
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
}
@Override @Override
public boolean isTransient() { public boolean isTransient() {
return false; return false;
@@ -21,6 +21,8 @@ public interface RaceColumnListener extends Serializable {
void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor); void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor);
void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName);
/** /**
* A listener can use this to specify that it must not be serialized together with other listeners. * A listener can use this to specify that it must not be serialized together with other listeners.
* Background: the collections holding race column listeners are usually non-transient. This will cause * Background: the collections holding race column listeners are usually non-transient. This will cause
@@ -240,6 +240,11 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene
raceColumnListeners.notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor); raceColumnListeners.notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor);
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
raceColumnListeners.notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
}
@Override @Override
public boolean isTransient() { public boolean isTransient() {
return false; return false;
@@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnInSeries; import com.sap.sailing.domain.base.RaceColumnInSeries;
@@ -233,6 +234,11 @@ public class SeriesImpl extends NamedImpl implements Series, RaceColumnListener
raceColumnListeners.notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor); raceColumnListeners.notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor);
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
raceColumnListeners.notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
}
@Override @Override
public boolean isTransient() { public boolean isTransient() {
return false; return false;
@@ -186,7 +186,9 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
@Override @Override
public void setDisplayName(Competitor competitor, String displayName) { public void setDisplayName(Competitor competitor, String displayName) {
String oldDisplayName = displayNames.get(competitor);
displayNames.put(competitor, displayName); displayNames.put(competitor, displayName);
getRaceColumnListeners().notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
} }
@Override @Override
@@ -448,6 +450,11 @@ public abstract class AbstractSimpleLeaderboardImpl implements Leaderboard, Race
getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn); getRaceColumnListeners().notifyListenersAboutRaceColumnRemovedFromContainer(raceColumn);
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
getRaceColumnListeners().notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
}
@Override @Override
public boolean isTransient() { public boolean isTransient() {
return false; return false;
@@ -131,6 +131,11 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R
getRaceColumnListeners().notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor); getRaceColumnListeners().notifyListenersAboutFactorChanged(raceColumn, oldFactor, newFactor);
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
getRaceColumnListeners().notifyListenersAboutCompetitorDisplayNameChanged(competitor, oldDisplayName, displayName);
}
@Override @Override
public boolean isTransient() { public boolean isTransient() {
return false; return false;
@@ -7,6 +7,7 @@ import java.io.Serializable;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import com.sap.sailing.domain.base.Competitor;
import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.Fleet;
import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumn;
import com.sap.sailing.domain.base.RaceColumnListener; import com.sap.sailing.domain.base.RaceColumnListener;
@@ -116,4 +117,10 @@ public class RaceColumnListeners implements Serializable {
return result; return result;
} }
public void notifyListenersAboutCompetitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
for (RaceColumnListener listener : getRaceColumnListeners()) {
listener.competitorDisplayNameChanged(competitor, oldDisplayName, displayName);
}
}
} }
@@ -68,6 +68,12 @@ public class DetailTypeFormatter {
return stringMessages.totalTimeSailedReachingInSeconds(); return stringMessages.totalTimeSailedReachingInSeconds();
case TOTAL_TIME_SAILED_IN_SECONDS: case TOTAL_TIME_SAILED_IN_SECONDS:
return stringMessages.totalTimeSailedInSeconds(); return stringMessages.totalTimeSailedInSeconds();
case AVERAGE_MANEUVER_LOSS_IN_METERS:
return stringMessages.averageManeuverLossInMeters();
case AVERAGE_TACK_LOSS_IN_METERS:
return stringMessages.averageTackLossInMeters();
case AVERAGE_JIBE_LOSS_IN_METERS:
return stringMessages.averageJibeLossInMeters();
} }
return null; return null;
@@ -427,4 +427,6 @@ public interface StringMessages extends Messages {
String errorUpdatingIsMedalRace(String message); String errorUpdatingIsMedalRace(String message);
String maneuverLoss(); String maneuverLoss();
String averageManeuverLossInMeters(); String averageManeuverLossInMeters();
String averageTackLossInMeters();
String averageJibeLossInMeters();
} }
@@ -427,4 +427,6 @@ expandLastRace=Always expand last race shown
factor=Factor factor=Factor
errorUpdatingIsMedalRace=Error updating the medal race setting: {0} errorUpdatingIsMedalRace=Error updating the medal race setting: {0}
maneuverLoss=Maneuver loss maneuverLoss=Maneuver loss
averageManeuverLossInMeters=\u2205 Maneuver Loss averageManeuverLossInMeters=\u2205 Maneuver Loss
averageTackLossInMeters=\u2205 Tack Loss
averageJibeLossInMeters=\u2205 Jibe Loss
@@ -428,4 +428,6 @@ expandLastRace=Immer letztes gezeigtes Rennen expandieren
factor=Faktor factor=Faktor
errorUpdatingIsMedalRace=Fehler beim Ändern der Medaillenrennen-Einstellung: {0} errorUpdatingIsMedalRace=Fehler beim Ändern der Medaillenrennen-Einstellung: {0}
maneuverLoss=Manöververlust maneuverLoss=Manöververlust
averageManeuverLossInMeters=\u2205 Manöververlust averageManeuverLossInMeters=\u2205 Manöververlust
averageTackLossInMeters=\u2205 Wendeverlust
averageJibeLossInMeters=\u2205 Halseverlust
@@ -50,8 +50,11 @@ public class LeaderboardSettingsFactory {
case Live: case Live:
List<DetailType> maneuverDetails = new ArrayList<DetailType>(); List<DetailType> maneuverDetails = new ArrayList<DetailType>();
maneuverDetails.add(DetailType.TACK); maneuverDetails.add(DetailType.TACK);
maneuverDetails.add(DetailType.AVERAGE_TACK_LOSS_IN_METERS);
maneuverDetails.add(DetailType.JIBE); maneuverDetails.add(DetailType.JIBE);
maneuverDetails.add(DetailType.AVERAGE_JIBE_LOSS_IN_METERS);
maneuverDetails.add(DetailType.PENALTY_CIRCLE); maneuverDetails.add(DetailType.PENALTY_CIRCLE);
maneuverDetails.add(DetailType.AVERAGE_MANEUVER_LOSS_IN_METERS);
List<DetailType> legDetails = new ArrayList<DetailType>(); List<DetailType> legDetails = new ArrayList<DetailType>();
legDetails.add(DetailType.DISTANCE_TRAVELED); legDetails.add(DetailType.DISTANCE_TRAVELED);
legDetails.add(DetailType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS); legDetails.add(DetailType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
@@ -108,8 +111,11 @@ public class LeaderboardSettingsFactory {
} }
List<DetailType> maneuverDetails = new ArrayList<DetailType>(); List<DetailType> maneuverDetails = new ArrayList<DetailType>();
maneuverDetails.add(DetailType.TACK); maneuverDetails.add(DetailType.TACK);
maneuverDetails.add(DetailType.AVERAGE_TACK_LOSS_IN_METERS);
maneuverDetails.add(DetailType.JIBE); maneuverDetails.add(DetailType.JIBE);
maneuverDetails.add(DetailType.AVERAGE_JIBE_LOSS_IN_METERS);
maneuverDetails.add(DetailType.PENALTY_CIRCLE); maneuverDetails.add(DetailType.PENALTY_CIRCLE);
maneuverDetails.add(DetailType.AVERAGE_MANEUVER_LOSS_IN_METERS);
List<DetailType> legDetails = new ArrayList<DetailType>(); List<DetailType> legDetails = new ArrayList<DetailType>();
legDetails.add(DetailType.DISTANCE_TRAVELED); legDetails.add(DetailType.DISTANCE_TRAVELED);
legDetails.add(DetailType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS); legDetails.add(DetailType.AVERAGE_SPEED_OVER_GROUND_IN_KNOTS);
@@ -9,6 +9,7 @@ import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.cellview.client.Header; import com.google.gwt.user.cellview.client.Header;
import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.InvertibleComparator; import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.SortingOrder; import com.sap.sailing.domain.common.SortingOrder;
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter; import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -133,24 +134,24 @@ public class LegColumn extends ExpandableSortableColumn<String> {
LegEntryDTO entry = getLegEntry(row); LegEntryDTO entry = getLegEntry(row);
if (entry != null) { if (entry != null) {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
if (entry.numberOfTacks != null) { if (entry.numberOfManeuvers.get(ManeuverType.TACK) != null) {
result.append(entry.numberOfTacks); result.append(entry.numberOfManeuvers.get(ManeuverType.TACK));
result.append(" "); result.append(" ");
result.append(stringMessages.tacks()); result.append(stringMessages.tacks());
} }
if (entry.numberOfJibes != null) { if (entry.numberOfManeuvers.get(ManeuverType.JIBE) != null) {
if (result.length() > 0) { if (result.length() > 0) {
result.append(", "); result.append(", ");
} }
result.append(entry.numberOfJibes); result.append(entry.numberOfManeuvers.get(ManeuverType.JIBE));
result.append(" "); result.append(" ");
result.append(stringMessages.jibes()); result.append(stringMessages.jibes());
} }
if (entry.numberOfPenaltyCircles != null) { if (entry.numberOfManeuvers.get(ManeuverType.PENALTY_CIRCLE) != null) {
if (result.length() > 0) { if (result.length() > 0) {
result.append(", "); result.append(", ");
} }
result.append(entry.numberOfPenaltyCircles); result.append(entry.numberOfManeuvers.get(ManeuverType.PENALTY_CIRCLE));
result.append(" "); result.append(" ");
result.append(stringMessages.penaltyCircles()); result.append(stringMessages.penaltyCircles());
} }
@@ -168,9 +169,9 @@ public class LegColumn extends ExpandableSortableColumn<String> {
result.append(getFormatter().format(fieldValue)); result.append(getFormatter().format(fieldValue));
} }
LegEntryDTO entry = getLegEntry(row); LegEntryDTO entry = getLegEntry(row);
if (entry != null && entry.numberOfPenaltyCircles != null && (int) entry.numberOfPenaltyCircles != 0) { if (entry != null && entry.numberOfManeuvers.get(ManeuverType.PENALTY_CIRCLE) != null && (int) entry.numberOfManeuvers.get(ManeuverType.PENALTY_CIRCLE) != 0) {
result.append(" ("); result.append(" (");
result.append(entry.numberOfPenaltyCircles); result.append(entry.numberOfManeuvers.get(ManeuverType.PENALTY_CIRCLE));
result.append("P)"); result.append("P)");
} }
return result.toString(); return result.toString();
@@ -181,28 +182,21 @@ public class LegColumn extends ExpandableSortableColumn<String> {
LegEntryDTO entry = getLegEntry(row); LegEntryDTO entry = getLegEntry(row);
Double result = null; Double result = null;
if (entry != null) { if (entry != null) {
if (entry.numberOfTacks != null) { for (ManeuverType maneuverType : new ManeuverType[] { ManeuverType.TACK, ManeuverType.JIBE,
result = (double) entry.numberOfTacks; ManeuverType.PENALTY_CIRCLE }) {
} if (entry.numberOfManeuvers.get(maneuverType) != null) {
if (entry.numberOfJibes != null) { if (result == null) {
if (result == null) { result = (double) entry.numberOfManeuvers.get(maneuverType);
result = (double) entry.numberOfJibes; } else {
} else { result += (double) entry.numberOfManeuvers.get(maneuverType);
result += (double) entry.numberOfJibes; }
}
}
if (entry.numberOfPenaltyCircles != null) {
if (result == null) {
result = (double) entry.numberOfPenaltyCircles;
} else {
result += (double) entry.numberOfPenaltyCircles;
} }
} }
} }
return result; return result;
} }
} }
public LegColumn(LeaderboardPanel leaderboardPanel, String raceName, int legIndex, SortingOrder preferredSortingOrder, StringMessages stringMessages, public LegColumn(LeaderboardPanel leaderboardPanel, String raceName, int legIndex, SortingOrder preferredSortingOrder, StringMessages stringMessages,
List<DetailType> legDetailSelection, String headerStyle, String columnStyle, List<DetailType> legDetailSelection, String headerStyle, String columnStyle,
String detailHeaderStyle, String detailColumnStyle) { String detailHeaderStyle, String detailColumnStyle) {
@@ -11,8 +11,8 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.cellview.client.Header; import com.google.gwt.user.cellview.client.Header;
import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.InvertibleComparator; import com.sap.sailing.domain.common.InvertibleComparator;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter; import com.sap.sailing.domain.common.impl.InvertibleComparatorAdapter;
import com.sap.sailing.domain.common.impl.Util.Triple;
import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.leaderboard.LegDetailColumn.LegDetailField; import com.sap.sailing.gwt.ui.leaderboard.LegDetailColumn.LegDetailField;
import com.sap.sailing.gwt.ui.shared.LeaderboardDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardDTO;
@@ -46,28 +46,42 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
private class NumberOfTacks extends AbstractManeuverDetailField<Double> { private class NumberOfTacks extends AbstractManeuverDetailField<Double> {
@Override @Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) { protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getTotalNumberOfTacks(entry); return ManeuverCountRaceColumn.this.getTotalNumberOfManeuvers(entry, ManeuverType.TACK);
}
}
private class AverageTackLossInMeters extends AbstractManeuverDetailField<Double> {
@Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getAverageManeuverLossInMeters(entry, ManeuverType.TACK);
} }
} }
private class NumberOfJibes extends AbstractManeuverDetailField<Double> { private class NumberOfJibes extends AbstractManeuverDetailField<Double> {
@Override @Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) { protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getTotalNumberOfJibes(entry); return ManeuverCountRaceColumn.this.getTotalNumberOfManeuvers(entry, ManeuverType.JIBE);
}
}
private class AverageJibeLossInMeters extends AbstractManeuverDetailField<Double> {
@Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getAverageManeuverLossInMeters(entry, ManeuverType.JIBE);
} }
} }
private class NumberOfPenaltyCircles extends AbstractManeuverDetailField<Double> { private class NumberOfPenaltyCircles extends AbstractManeuverDetailField<Double> {
@Override @Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) { protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getTotalNumberOfPenaltyCircles(entry); return ManeuverCountRaceColumn.this.getTotalNumberOfManeuvers(entry, ManeuverType.PENALTY_CIRCLE);
} }
} }
private class AverageManeuverLossInMeters extends AbstractManeuverDetailField<Double> { private class AverageManeuverLossInMeters extends AbstractManeuverDetailField<Double> {
@Override @Override
protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) { protected Double getFromNonNullEntry(LeaderboardEntryDTO entry) {
return ManeuverCountRaceColumn.this.getAverageManeuverLossInMeters(entry); return ManeuverCountRaceColumn.this.getAverageManeuverLossInMeters(entry, ManeuverType.TACK, ManeuverType.JIBE);
} }
} }
@@ -84,118 +98,68 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
this.minmaxRenderer = new MinMaxRenderer(this, getComparator()); this.minmaxRenderer = new MinMaxRenderer(this, getComparator());
} }
public Double getAverageManeuverLossInMeters(LeaderboardEntryDTO row) { private Double getAverageManeuverLossInMeters(LeaderboardEntryDTO row, ManeuverType... maneuverTypes) {
Double maneuverLossInMetersSum = null;
int count = 0; int count = 0;
double totalLossInMeters = 0.0;
if (row != null && row.legDetails != null) { if (row != null && row.legDetails != null) {
for (LegEntryDTO legDetail : row.legDetails) { for (LegEntryDTO legDetail : row.legDetails) {
if (legDetail != null) { if (legDetail != null) {
if (legDetail.averageManeuverLossInMeters != null) { if (legDetail.averageManeuverLossInMeters != null) {
if (maneuverLossInMetersSum == null) { for (ManeuverType maneuverType : maneuverTypes) {
maneuverLossInMetersSum = (double) legDetail.averageManeuverLossInMeters; final Integer maneuverCount = legDetail.numberOfManeuvers.get(maneuverType);
} else { if (maneuverCount != null && maneuverCount != 0) {
maneuverLossInMetersSum += (double) legDetail.averageManeuverLossInMeters; totalLossInMeters += legDetail.averageManeuverLossInMeters.get(maneuverType) * maneuverCount;
count += maneuverCount;
}
} }
Triple<Double, Double, Double> maneuverCounts = getTotalNumberOfTacksJibesAndPenaltyCircles(row);
count += maneuverCounts.getA()+maneuverCounts.getB()+maneuverCounts.getC();
} }
} }
} }
} }
return maneuverLossInMetersSum == null ? null : maneuverLossInMetersSum / count; return count == 0 ? null : totalLossInMeters / count;
} }
private Double getTotalNumberOfTacks(LeaderboardEntryDTO row) { private Double getTotalNumberOfManeuvers(LeaderboardEntryDTO row, ManeuverType maneuverType) {
Double totalNumberOfTacks = null; Double totalNumberOfManeuvers = null;
if (row != null && row.legDetails != null) { if (row != null && row.legDetails != null) {
for (LegEntryDTO legDetail : row.legDetails) { for (LegEntryDTO legDetail : row.legDetails) {
if (legDetail != null) { if (legDetail != null) {
if (legDetail.numberOfTacks != null) { if (legDetail.numberOfManeuvers.get(maneuverType) != null) {
if (totalNumberOfTacks == null) { if (totalNumberOfManeuvers == null) {
totalNumberOfTacks = (double) legDetail.numberOfTacks; totalNumberOfManeuvers = (double) legDetail.numberOfManeuvers.get(maneuverType);
} else { } else {
totalNumberOfTacks += (double) legDetail.numberOfTacks; totalNumberOfManeuvers += (double) legDetail.numberOfManeuvers.get(maneuverType);
} }
} }
} }
} }
} }
return totalNumberOfTacks; return totalNumberOfManeuvers;
} }
private Double getTotalNumberOfJibes(LeaderboardEntryDTO row) { private Map<ManeuverType, Double> getTotalNumberOfTacksJibesAndPenaltyCircles(LeaderboardRowDTO row) {
Double totalNumberOfJibes = null;
if (row != null && row.legDetails != null) {
for (LegEntryDTO legDetail : row.legDetails) {
if (legDetail != null) {
if (legDetail.numberOfJibes != null) {
if (totalNumberOfJibes == null) {
totalNumberOfJibes = (double) legDetail.numberOfJibes;
} else {
totalNumberOfJibes += (double) legDetail.numberOfJibes;
}
}
}
}
}
return totalNumberOfJibes;
}
private Double getTotalNumberOfPenaltyCircles(LeaderboardEntryDTO row) {
Double totalNumberOfPnaltyCicles = null;
if (row != null && row.legDetails != null) {
for (LegEntryDTO legDetail : row.legDetails) {
if (legDetail != null) {
if (legDetail.numberOfPenaltyCircles != null) {
if (totalNumberOfPnaltyCicles == null) {
totalNumberOfPnaltyCicles = (double) legDetail.numberOfPenaltyCircles;
} else {
totalNumberOfPnaltyCicles += (double) legDetail.numberOfPenaltyCircles;
}
}
}
}
}
return totalNumberOfPnaltyCicles;
}
private Triple<Double, Double, Double> getTotalNumberOfTacksJibesAndPenaltyCircles(LeaderboardRowDTO row) {
LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceName()); LeaderboardEntryDTO fieldsForRace = row.fieldsByRaceColumnName.get(getRaceName());
return getTotalNumberOfTacksJibesAndPenaltyCircles(fieldsForRace); return getTotalNumberOfTacksJibesAndPenaltyCircles(fieldsForRace);
} }
private Triple<Double, Double, Double> getTotalNumberOfTacksJibesAndPenaltyCircles(LeaderboardEntryDTO fieldsForRace) { private Map<ManeuverType, Double> getTotalNumberOfTacksJibesAndPenaltyCircles(LeaderboardEntryDTO fieldsForRace) {
Double totalNumberOfTacks = null; Map<ManeuverType, Double> totalNumberOfManeuvers = new HashMap<ManeuverType, Double>();
Double totalNumberOfJibes = null; for (ManeuverType maneuverType : new ManeuverType[] { ManeuverType.TACK, ManeuverType.JIBE, ManeuverType.PENALTY_CIRCLE }) {
Double totalNumberOfPenaltyCircles = null; totalNumberOfManeuvers.put(maneuverType, 0.0);
}
if (fieldsForRace != null && fieldsForRace.legDetails != null) { if (fieldsForRace != null && fieldsForRace.legDetails != null) {
for (LegEntryDTO legDetail : fieldsForRace.legDetails) { for (LegEntryDTO legDetail : fieldsForRace.legDetails) {
if (legDetail != null) { if (legDetail != null) {
if (legDetail.numberOfTacks != null) { for (ManeuverType maneuverType : new ManeuverType[] { ManeuverType.TACK, ManeuverType.JIBE, ManeuverType.PENALTY_CIRCLE }) {
if (totalNumberOfTacks == null) { if (legDetail.numberOfManeuvers.get(maneuverType) != null) {
totalNumberOfTacks = (double) legDetail.numberOfTacks; totalNumberOfManeuvers.put(maneuverType,
} else { totalNumberOfManeuvers.get(maneuverType) + (double) legDetail.numberOfManeuvers.get(maneuverType));
totalNumberOfTacks += legDetail.numberOfTacks;
}
}
if (legDetail.numberOfJibes != null) {
if (totalNumberOfJibes == null) {
totalNumberOfJibes = (double) legDetail.numberOfJibes;
} else {
totalNumberOfJibes += (double) legDetail.numberOfJibes;
}
}
if (legDetail.numberOfPenaltyCircles != null) {
if (totalNumberOfPenaltyCircles == null) {
totalNumberOfPenaltyCircles = (double) legDetail.numberOfPenaltyCircles;
} else {
totalNumberOfPenaltyCircles += (double) legDetail.numberOfPenaltyCircles;
} }
} }
} }
} }
} }
return new Triple<Double, Double, Double>(totalNumberOfTacks, totalNumberOfJibes, totalNumberOfPenaltyCircles); return totalNumberOfManeuvers;
} }
private String getRaceName() { private String getRaceName() {
@@ -251,25 +215,14 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
public Double getDoubleValue(LeaderboardRowDTO row) { public Double getDoubleValue(LeaderboardRowDTO row) {
Double result = null; Double result = null;
Triple<Double, Double, Double> tacksJibesAndPenalties = getTotalNumberOfTacksJibesAndPenaltyCircles(row); Map<ManeuverType, Double> tacksJibesAndPenalties = getTotalNumberOfTacksJibesAndPenaltyCircles(row);
Double totalNumberOfTacks = tacksJibesAndPenalties.getA(); for (Double maneuverCount : tacksJibesAndPenalties.values()) {
Double totalNumberOfJibes = tacksJibesAndPenalties.getB(); if (maneuverCount != null) {
Double totalNumberOfPenaltyCircles = tacksJibesAndPenalties.getC(); if (result == null) {
if (totalNumberOfTacks != null) { result = maneuverCount;
result = (double) totalNumberOfTacks; } else {
} result += maneuverCount;
if (totalNumberOfJibes != null) { }
if (result == null) {
result = (double) totalNumberOfJibes;
} else {
result += (double) totalNumberOfJibes;
}
}
if (totalNumberOfPenaltyCircles != null) {
if (result == null) {
result = (double) totalNumberOfPenaltyCircles;
} else {
result += (double) totalNumberOfPenaltyCircles;
} }
} }
return result; return result;
@@ -293,6 +246,16 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
new FormattedDoubleLegDetailColumn(stringMessages.penaltyCircle(), "", new NumberOfPenaltyCircles(), new FormattedDoubleLegDetailColumn(stringMessages.penaltyCircle(), "", new NumberOfPenaltyCircles(),
DetailType.PENALTY_CIRCLE.getPrecision(), DetailType.PENALTY_CIRCLE.getDefaultSortingOrder(), DetailType.PENALTY_CIRCLE.getPrecision(), DetailType.PENALTY_CIRCLE.getDefaultSortingOrder(),
detailHeaderStyle, detailColumnStyle)); detailHeaderStyle, detailColumnStyle));
result.put(DetailType.AVERAGE_TACK_LOSS_IN_METERS,
new FormattedDoubleLegDetailColumn(stringMessages.averageTackLossInMeters(),
stringMessages.distanceInMetersUnit(), new AverageTackLossInMeters(),
DetailType.AVERAGE_TACK_LOSS_IN_METERS.getPrecision(), DetailType.AVERAGE_TACK_LOSS_IN_METERS.getDefaultSortingOrder(),
detailHeaderStyle, detailColumnStyle));
result.put(DetailType.AVERAGE_JIBE_LOSS_IN_METERS,
new FormattedDoubleLegDetailColumn(stringMessages.averageJibeLossInMeters(),
stringMessages.distanceInMetersUnit(), new AverageJibeLossInMeters(),
DetailType.AVERAGE_JIBE_LOSS_IN_METERS.getPrecision(), DetailType.AVERAGE_JIBE_LOSS_IN_METERS.getDefaultSortingOrder(),
detailHeaderStyle, detailColumnStyle));
result.put(DetailType.AVERAGE_MANEUVER_LOSS_IN_METERS, result.put(DetailType.AVERAGE_MANEUVER_LOSS_IN_METERS,
new FormattedDoubleLegDetailColumn(stringMessages.averageManeuverLossInMeters(), new FormattedDoubleLegDetailColumn(stringMessages.averageManeuverLossInMeters(),
stringMessages.distanceInMetersUnit(), new AverageManeuverLossInMeters(), stringMessages.distanceInMetersUnit(), new AverageManeuverLossInMeters(),
@@ -302,7 +265,8 @@ public class ManeuverCountRaceColumn extends ExpandableSortableColumn<String> im
} }
public static DetailType[] getAvailableManeuverDetailColumnTypes() { public static DetailType[] getAvailableManeuverDetailColumnTypes() {
return new DetailType[] { DetailType.TACK, DetailType.JIBE, DetailType.PENALTY_CIRCLE }; return new DetailType[] { DetailType.TACK, DetailType.AVERAGE_TACK_LOSS_IN_METERS,
DetailType.JIBE, DetailType.AVERAGE_JIBE_LOSS_IN_METERS, DetailType.PENALTY_CIRCLE, DetailType.AVERAGE_MANEUVER_LOSS_IN_METERS };
} }
@Override @Override
@@ -221,7 +221,8 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
} }
getLeaderboard().competitorDisplayNames.put(row.competitor, value == null || value.trim().length() == 0 ? null : value.trim()); getLeaderboard().competitorDisplayNames.put(row.competitor, value == null || value.trim().length() == 0 ? null : value.trim());
cell.setViewData(row, null); // ensure that getValue() is called again cell.setViewData(row, null); // ensure that getValue() is called again
EditableLeaderboardPanel.this.getData().getList().set(rowIndex, row); EditableLeaderboardPanel.this.getData().getList().set(
EditableLeaderboardPanel.this.getData().getList().indexOf(row), row);
} }
}); });
} }
@@ -672,9 +673,10 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
private List<HasCell<LeaderboardRowDTO, ?>> getCellListForEditableCompetitorColumn() { private List<HasCell<LeaderboardRowDTO, ?>> getCellListForEditableCompetitorColumn() {
List<HasCell<LeaderboardRowDTO, ?>> result = new ArrayList<HasCell<LeaderboardRowDTO, ?>>(); List<HasCell<LeaderboardRowDTO, ?>> result = new ArrayList<HasCell<LeaderboardRowDTO, ?>>();
result.add(new HasCell<LeaderboardRowDTO, String>() { result.add(new HasCell<LeaderboardRowDTO, String>() {
private final ButtonCell cell = new ButtonCell();
@Override @Override
public Cell<String> getCell() { public Cell<String> getCell() {
return new ButtonCell(); return cell;
} }
@Override @Override
@@ -707,9 +709,10 @@ public class EditableLeaderboardPanel extends LeaderboardPanel {
} }
}); });
result.add(new HasCell<LeaderboardRowDTO, String>() { result.add(new HasCell<LeaderboardRowDTO, String>() {
private final EditTextCell cell = new EditTextCell();
@Override @Override
public EditTextCell getCell() { public EditTextCell getCell() {
return new EditTextCell(); return cell;
} }
@Override @Override
@@ -288,6 +288,11 @@ public class LeaderboardDTOCache {
public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) { public void factorChanged(RaceColumn raceColumn, Double oldFactor, Double newFactor) {
removeFromCache(leaderboard); removeFromCache(leaderboard);
} }
@Override
public void competitorDisplayNameChanged(Competitor competitor, String oldDisplayName, String displayName) {
removeFromCache(leaderboard);
}
}; };
leaderboard.addRaceColumnListener(raceColumnListener); leaderboard.addRaceColumnListener(raceColumnListener);
synchronized (raceColumnListeners) { synchronized (raceColumnListeners) {
@@ -60,6 +60,7 @@ import com.sap.sailing.domain.common.CountryCode;
import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.DetailType;
import com.sap.sailing.domain.common.Distance; import com.sap.sailing.domain.common.Distance;
import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.LegType;
import com.sap.sailing.domain.common.ManeuverType;
import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.MaxPointsReason;
import com.sap.sailing.domain.common.NoWindError; import com.sap.sailing.domain.common.NoWindError;
import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.NoWindException;
@@ -831,37 +832,34 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
.getMeters(); .getMeters();
List<Maneuver> maneuvers = trackedLeg.getManeuvers(timePoint, waitForLatestAnalyses); List<Maneuver> maneuvers = trackedLeg.getManeuvers(timePoint, waitForLatestAnalyses);
if (maneuvers != null) { if (maneuvers != null) {
result.numberOfTacks = 0; result.numberOfManeuvers = new HashMap<ManeuverType, Integer>();
result.numberOfJibes = 0; result.numberOfManeuvers.put(ManeuverType.TACK, 0);
result.numberOfPenaltyCircles = 0; result.numberOfManeuvers.put(ManeuverType.JIBE, 0);
int maneuverCount = 0; result.numberOfManeuvers.put(ManeuverType.PENALTY_CIRCLE, 0);
double totalManeuverLossInMeters = 0.0; Map<ManeuverType, Double> totalManeuverLossInMeters = new HashMap<ManeuverType, Double>();
totalManeuverLossInMeters.put(ManeuverType.TACK, 0.0);
totalManeuverLossInMeters.put(ManeuverType.JIBE, 0.0);
totalManeuverLossInMeters.put(ManeuverType.PENALTY_CIRCLE, 0.0);
for (Maneuver maneuver : maneuvers) { for (Maneuver maneuver : maneuvers) {
switch (maneuver.getType()) { switch (maneuver.getType()) {
case TACK: case TACK:
result.numberOfTacks++;
if (maneuver.getManeuverLoss() != null) {
maneuverCount++;
totalManeuverLossInMeters += maneuver.getManeuverLoss().getMeters();
}
break;
case JIBE: case JIBE:
result.numberOfJibes++;
if (maneuver.getManeuverLoss() != null) {
maneuverCount++;
totalManeuverLossInMeters += maneuver.getManeuverLoss().getMeters();
}
break;
case PENALTY_CIRCLE: case PENALTY_CIRCLE:
result.numberOfPenaltyCircles++;
if (maneuver.getManeuverLoss() != null) { if (maneuver.getManeuverLoss() != null) {
maneuverCount++; result.numberOfManeuvers.put(maneuver.getType(), result.numberOfManeuvers.get(maneuver.getType())+1);
totalManeuverLossInMeters += maneuver.getManeuverLoss().getMeters(); totalManeuverLossInMeters.put(maneuver.getType(),
totalManeuverLossInMeters.get(maneuver.getType()) + maneuver.getManeuverLoss().getMeters());
} }
break; break;
} }
} }
result.averageManeuverLossInMeters = maneuverCount == 0 ? null : (totalManeuverLossInMeters/maneuverCount); result.averageManeuverLossInMeters = new HashMap<ManeuverType, Double>();
for (ManeuverType maneuverType : new ManeuverType[] { ManeuverType.TACK, ManeuverType.JIBE, ManeuverType.PENALTY_CIRCLE }) {
if (result.numberOfManeuvers.get(maneuverType) != 0) {
result.averageManeuverLossInMeters.put(maneuverType,
totalManeuverLossInMeters.get(maneuverType)/result.numberOfManeuvers.get(maneuverType));
}
}
} }
} }
return result; return result;
@@ -1,6 +1,9 @@
package com.sap.sailing.gwt.ui.shared; package com.sap.sailing.gwt.ui.shared;
import java.util.Map;
import com.google.gwt.user.client.rpc.IsSerializable; import com.google.gwt.user.client.rpc.IsSerializable;
import com.sap.sailing.domain.common.ManeuverType;
/** /**
* Holds data about one competitor's performance in one leg of one race represented in the * Holds data about one competitor's performance in one leg of one race represented in the
@@ -35,10 +38,8 @@ public class LegEntryDTO implements IsSerializable {
public Long timeInMilliseconds; public Long timeInMilliseconds;
public boolean started; public boolean started;
public boolean finished; public boolean finished;
public Integer numberOfJibes; public Map<ManeuverType, Integer> numberOfManeuvers;
public Integer numberOfTacks; public Map<ManeuverType, Double> averageManeuverLossInMeters;
public Double averageManeuverLossInMeters;
public Integer numberOfPenaltyCircles;
public Double averageCrossTrackErrorInMeters; public Double averageCrossTrackErrorInMeters;
@Override @Override
@@ -55,9 +56,7 @@ public class LegEntryDTO implements IsSerializable {
+ ((estimatedTimeToNextWaypointInSeconds == null) ? 0 : estimatedTimeToNextWaypointInSeconds.hashCode()); + ((estimatedTimeToNextWaypointInSeconds == null) ? 0 : estimatedTimeToNextWaypointInSeconds.hashCode());
result = prime * result + (finished ? 1231 : 1237); result = prime * result + (finished ? 1231 : 1237);
result = prime * result + ((gapToLeaderInSeconds == null) ? 0 : gapToLeaderInSeconds.hashCode()); result = prime * result + ((gapToLeaderInSeconds == null) ? 0 : gapToLeaderInSeconds.hashCode());
result = prime * result + ((numberOfJibes == null) ? 0 : numberOfJibes.hashCode()); result = prime * result + ((numberOfManeuvers == null) ? 0 : numberOfManeuvers.hashCode());
result = prime * result + ((numberOfPenaltyCircles == null) ? 0 : numberOfPenaltyCircles.hashCode());
result = prime * result + ((numberOfTacks == null) ? 0 : numberOfTacks.hashCode());
result = prime * result + rank; result = prime * result + rank;
result = prime * result + (started ? 1231 : 1237); result = prime * result + (started ? 1231 : 1237);
result = prime * result + (int) (timeInMilliseconds ^ (timeInMilliseconds >>> 32)); result = prime * result + (int) (timeInMilliseconds ^ (timeInMilliseconds >>> 32));
@@ -102,20 +101,10 @@ public class LegEntryDTO implements IsSerializable {
return false; return false;
} else if (!gapToLeaderInSeconds.equals(other.gapToLeaderInSeconds)) } else if (!gapToLeaderInSeconds.equals(other.gapToLeaderInSeconds))
return false; return false;
if (numberOfJibes == null) { if (numberOfManeuvers == null) {
if (other.numberOfJibes != null) if (other.numberOfManeuvers != null)
return false; return false;
} else if (!numberOfJibes.equals(other.numberOfJibes)) } else if (!numberOfManeuvers.equals(other.numberOfManeuvers))
return false;
if (numberOfPenaltyCircles == null) {
if (other.numberOfPenaltyCircles != null)
return false;
} else if (!numberOfPenaltyCircles.equals(other.numberOfPenaltyCircles))
return false;
if (numberOfTacks == null) {
if (other.numberOfTacks != null)
return false;
} else if (!numberOfTacks.equals(other.numberOfTacks))
return false; return false;
if (rank != other.rank) if (rank != other.rank)
return false; return false;